proper implementation of numr and dnom OpenType features
Greetings. I can't seem to get the typophile search function to work, or I probably would have already found the answer to my question. It also doesn't appear to be in the Fontlab 4.6 manual.
Can anyone show me an example of proper implementation of the numr and dnom OpenType features? I can get the frac feature to do basic substitutions for the standard set of fractions, but it seems that the frac feature can call the numr and dnom features, but I haven't seen anywhere a specific example of how to make that work. I'd be most grateful for some insight into that mysterious process.
Below is the code I'm currently using to get the frac feature to work, in case it gives you some idea where I'm at.
feature frac {
sub [one one.lnum] [slash fraction] [two two.lnum] by onehalf;
sub [one one.lnum] [slash fraction] [four four.lnum] by onequarter;
sub [one one.lnum] [slash fraction] [three three.lnum] by onethird;
sub [one one.lnum] [slash fraction] [eight eight.lnum] by oneeighth;
sub [two two.lnum] [slash fraction] [three three.lnum] by twothirds;
sub [three three.lnum] [slash fraction] [four four.lnum] by threequarters;
sub [three three.lnum] [slash fraction] [eight eight.lnum] by threeeighths;
sub [five five.lnum] [slash fraction] [eight eight.lnum] by fiveeighths;
sub [seven seven.lnum] [slash fraction] [eight eight.lnum] by seveneighths;
} frac;




21.Mar.2007 11.01pm
Hi Andrew. I'm a little confused by your message. I don't think you want to try to call 'numr' and 'dnom' with 'frac' -- at least for simple, prebuilt fractions like in your example. Your code seems fine for what you're trying to do.
It can be useful to "call" the 'numr' feature in 'frac' with arbitrary fractions. This is an example of what I mean:
feature frac {lookup NUMR;
sub [@SLASH @FIG_DENOMINATOR] @FIG_NUMERATOR' by @FIG_DENOMINATOR;
} frac;
The 'numr' and 'dnom' features are starting to look unnecessary, since there is usually little reason to create numerators or denominators without creating a whole fraction -- which is what 'frac' does all by itself. So I recommend putting 'numr' and 'dnom' in fonts, but not consider them components or "sub-features" of 'frac'.
22.Mar.2007 11.55pm
but it seems that the frac feature can call the numr and dnom features
The official feature descriptions are a bit confusing in this regard. When Adobe first registered the frac, numr and dnom features, they had this idea that frac would 'call' the other two features. And this combination of features would allow for arbitrary fractions. As I understand it, the idea was that the application or layout engine would perform the feature calls to the numr and dnom features, based on a character level analysis (numerals before the slash get the numr feature applied to them, numerals after the slash get the denominator feature applied to them). But no one had got around to implementing this in a layout engine by the time I came along with a scheme building arbitrary fractions contextually, directly within the frac feature. Which is what pretty much everyone has been doing ever since.
I believe Adobe make the arbitrary fraction code available with the FDK.
23.Mar.2007 7.46am
Doesn't Quark do it differently?
I haven't checked this recently, but I recall that in the demo of Quark 7, the fraction feature was ignored, and the fractions built on the fly from numr, fraction character, and dnom. At least that was my understanding, and I assumed it was done for backwards-compatability of older files.
23.Mar.2007 8.31am
The font I'm working on has
fracbut notnumrordnomand the fraction feature works fine in Quark 7.23.Mar.2007 12.57pm
IMO, "numr" and "dnom" should implement simple subsitutions: digits by numerator figures in "numr" and digits by denominator figures in "dnom". The "frac" feature can be implemented completely separately. It may or may not re-use some lookups that were also used in numr or dnom.
A.
29.Sep.2009 5.05pm
OK resurrecting yet another old thread...
I have the following:
feature frac {
sub zero' [slash fraction]' zero' zero' zero' by uni2031;
sub zero' [slash fraction]' zero' zero' by perthousand;
sub zero' [slash fraction]' zero' by percent;
sub one' [slash fraction]' four' by onequarter;
sub one' [slash fraction]' two' by onehalf;
sub three' [slash fraction]' four' by threequarters;
lookup numr0;
sub [slash @dnom] @numr' by @dnom;
} frac;
But of course the lookup in the second section replaces all default numerals with numerators, so the substitutions above don't work to produce permille, perthousand, percent and the prebuilt fractions.
How can I ask the second part of code to ignore the prebuilt fractions? (I only know what I'm learning here so there could be some vital command I don't know about.)
30.Sep.2009 1.55am
Or maybe it's best to try and put the prebuilt fractions in a
ligafeature instead?BTW the second half of the feature currently reads:
lookup numr0;
sub [fraction @dnom] @numr' by @dnom;
sub @numr slash' by fraction;
} frac;
30.Sep.2009 7.01am
Here's the code I use:
feature frac {@numbers = [ zero one two three four five six seven eight nine ] ;
@numerators = [ zero.numr one.numr two.numr three.numr four.numr five.numr six.numr seven.numr eight.numr nine.numr ] ;
@denominators = [ zero.dnom one.dnom two.dnom three.dnom four.dnom five.dnom six.dnom seven.dnom eight.dnom nine.dnom ] ;
@predenominators = [ slash fraction onehalf onequarter threequarters
zero.dnom one.dnom two.dnom three.dnom four.dnom five.dnom six.dnom seven.dnom eight.dnom nine.dnom ] ;
sub one' [slash fraction]' two' by onehalf ;
sub one' [slash fraction]' four' by onequarter ;
sub three' [slash fraction]' four' by threequarters ;
sub @numbers by @numerators ;
sub @predenominators @numerators' by @denominators ;
sub slash by fraction ;
} frac;
If I recall, this was based somewhat on the code Adobe uses. I can't remember for sure.
Tal Lemming has a detailed discussion about frac feature strategy here:
http://talleming.com/2008/04/16/fraction-fever/
30.Sep.2009 7.20am
Elegant code. Thanks :)
30.Sep.2009 9.57am
Mark your code works a dream. Thanks again.
Should the
percentglyph be identical to azero.numr fraction zero.dnomsequence? My percent is a bit lighter.30.Sep.2009 10.31am
It can be. In many fonts, the percent sign does not match the look of the fractions. Even if it does match, I don't think it needs to be included in the frac feature. If a user wants a percent sign, it's right there on the keyboard. I can't imagine someone going to the trouble to type zero slash zero, select it, and then apply the Fraction feature, just to get a percent sign. If they are using 0/0 as a fraction, that would be semantically different from the percent sign anyway, and the Fraction feature would still work on it just like any other arbitrary combination.
30.Sep.2009 11.04am
>I can’t imagine someone going to the trouble to type zero slash zero, select it, and then apply the Fraction feature, just to get a percent sign.
That is a good point. I was thinking it might be useful for the permille U+2031, but I guess that's so rare that it can be found on the glyph palette when needed. Will remove these ones.
30.Sep.2009 11.49am
Doesn't Tal's feature require a space in the search?
ChrisL
30.Sep.2009 12.59pm
Yes. Tal is trying to find a better method than the usual one (which mine generally follows). He admits his solution has some drawbacks and doesn't necessarily recommend it. Looks like it's still a work in progress.
30.Sep.2009 3.11pm
Big thanks to Mr. Simonson for the code. I've been pondering how to most effectively code a fraction feature. Your code... its a beautiful thing. Again thanks.
30.Sep.2009 4.49pm
No problem. As I mentioned, I think I cribbed it partly from Adobe's code.
Note that if you have other pre-built fractions, you can add those in as well in the first section.
Also, Bendy, you mention the idea of using liga for the pre-built fractions. That would be a bad idea. Ligatures are usually on by default, so the fraction sequence would be converted indiscriminately. Thus, if the user typed "9/11/2001" they would get "9/1½001". :-0
30.Sep.2009 5.22pm
Arh, yes, erm, well maybe not then. :S
30.Sep.2009 7.48pm
Mark Simonson -- (about Tal's fraction feature) He admits his solution has some drawbacks and doesn't necessarily recommend it. Looks like it's still a work in progress. (about your fraction feature) Ligatures are usually on by default, so the fraction sequence would be converted indiscriminately. Thus, if the user typed "9/11/2001" they would get "9/1½001".
In both cases, the drawback is the same: indiscriminately applying the feature to strings that should not be touched. In case of Tal's suggestion, this drawback is easily addressed by adding a few "ignore" statements which make sure that dates and other strings following the pattern slash--digit(s)--slash are left intact. Btw, the free style of FF Dagny shows that FontShop has adopted Tal's approach including a safety belt like I mentioned, so obviously they consider this approach as safe enough, like I do too.
As to the second part, it is not necessary to deal with prebuilt fractions in frac. These exist for legacy reasons, so add them to the font but then leave them alone. A frac feature can compose a ½ from numerator-one plus fraction-slash plus denominator-two, the same way it would compose any other arbitrary fraction.
30.Sep.2009 8.46pm
Hm. Good point about the pre-built fractions. I copied that concept from Adobe's code, and (obviously) didn't think to question it.
Regarding Tal's fraction feature idea: Reading it over again, he is more positive about it than I remembered when I first read it a few months ago. I might use that in my next fonts. Have you actually come up with code to handle date exceptions?
1.Oct.2009 2.51am
The following is completely untested hack, but might work and deal correctly with dates. Unfortunately, the current version of FontLab doesn't support
rsubso it isn't viable for those who would prefer not to deal with ADFKO directly (which, unfortunately, includes me or I would have tested this).@Figures = [zero one two three four five six seven eight nine];
@Numerators = [zero.numr one.numr two.numr three.numr four.numr five.numr six.numr seven.numr eight.numr nine.numr];
@Denominators = [zero.dnom one.dnom two.dnom three.dnom four.dnom five.dnom six.dnom seven.dnom eight.dnom nine.dnom];
# perform initial substitutions
sub @Figures' [slash fraction] by @Numerators;
rsub @Figures' @Numerators by @Numerators;
sub [slash fraction] @Figures' by @Denominators;
sub @Denominators @Figures' by @Denominators;
# fix dates
sub [slash fraction] @Numerators' by @Figures;
sub @Figures @Numerators' by @Numerators;
sub @Numerators' [slash fraction] @Figures by @Figures;
rsub @Numerators' @Figures by @Figures;
sub @Figures [slash fraction] @Denominators by @Figures;
sub @Figures @Denominators' by @Figures;
sub @Numerators slash' @Denominators by fraction;
1.Oct.2009 2.54am
That probably needed to be broken into several separate lookups to work properly -- I leave that as an exercise for the reader :)
André
1.Oct.2009 3.19am
What's rsub?
1.Oct.2009 4.21am
reversesub (rsub) parses the input string from right to left rather than left to right (or from left to right in Hebrew or Arabic).
André
1.Oct.2009 10.29am
Tal has just posted an update to the Fractions Fever article which explains the addition: http://talleming.com/2009/10/01/fraction-fever-2/
Trick is to catch cases with multiple slashes via ignore (to make sure these cases are not turned into fractions), then substitute slash by fraction-slash, then substitute numerals by numerators and denominators if in context of fraction-slash.
reversesub would indeed save some lines of code, but better test this lookup type in a couple of applications first, including in XPress ...
1.Oct.2009 11.06am
Very nice solution!
13.Nov.2009 4.06pm
Indeed. Leming’s solution seems to work fine here, too. :D