Open Rahul-fix opened 4 months ago
I am having the same issue. Did you ever figure out a solution?
Sorry for the late reply, I was on holiday...
I see no reason why it should not work with your font. I also applied the rules to different fonts to find the best for fast-reading. The only important thing is, the font should have the different style variants combined in one font-file. So having on font-file incorporating the regular and the bold version of each letter.
There are some fonts out there, that have a separate font-file for regular, bold, itallic and all other versions... At least on the google drive it looks, like Bookerfly is unfortunately exactly that type of font... They have an extra font-file for the regular, and bold variant.
That would explain, why your script is complaining that it could not find the .bold variant "a.bold-z.bold" is not a glyph in the font
To solve that issue, you have to combine the regular and the bold font variant into one file. That is an easy copy paste process, where you copy all the bold-characters from the bold-font and paste them into the regular font-file, with the naming convention .bold behind every pasted character. It should result in a font file containing the regular characters with standard naming and the bold character with a closing .bold, for instance a -> a.bold
Afterwards your feature python scripts should also work ;-)
The easiest way to combine the fonts is to use a WYSIWYG-Font Editor. I would recommend FontLab, as I also used it for my experiments. An alternatives that should also work is FontCreator and you could also try the opensource alternative FontForge. But I have not worked with FontForge for a long time, so I am not sure if they improved in the meantime.
Thank you for the reply and suggestions. @Born2Root
❯ python3 addfeatures.py -o Fast-Bookerly.ttc testing/Bookerly/OpenType-TT/Bookerly.ttf test.fea
Adding features
Traceback (most recent call last):
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/ttLib/__init__.py", line 409, in __getitem__
return self.tables[tag]
~~~~~~~~~~~^^^^^
KeyError: 'post'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/rk/Sync/utils/FastFonts/addfeatures.py", line 22, in <module>
addOpenTypeFeatures(font, args.feature)
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/feaLib/builder.py", line 15, in addOpenTypeFeatures
builder = Builder(font, featurefile)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/feaLib/builder.py", line 32, in __init__
self.glyphMap = font.getReverseGlyphMap()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/ttLib/__init__.py", line 636, in getReverseGlyphMap
self._buildReverseGlyphOrderDict()
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/ttLib/__init__.py", line 641, in _buildReverseGlyphOrderDict
glyphOrder = self.getGlyphOrder()
^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/ttLib/__init__.py", line 472, in getGlyphOrder
glyphOrder = self['post'].getGlyphOrder()
~~~~^^^^^^^^
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/ttLib/__init__.py", line 424, in __getitem__
table.decompile(data, self)
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/ttLib/tables/_p_o_s_t.py", line 37, in decompile
self.decode_format_2_0(data, ttFont)
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/ttLib/tables/_p_o_s_t.py", line 86, in decode_format_2_0
indices.fromstring(data[:2*numGlyphs])
^^^^^^^^^^^^^^^^^^
AttributeError: 'array.array' object has no attribute 'fromstring'
❯ python3 addfeatures.py -o Fast-Bookerly.ttf testing/Bookerly/Bookerly-R_B_I_BI.ttc test.fea
Traceback (most recent call last):
File "/Users/rk/Sync/utils/FastFonts/addfeatures.py", line 20, in <module>
font = TTFont(args.input)
^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/ttLib/__init__.py", line 180, in __init__
self.reader = sfnt.SFNTReader(file, checkChecksums, fontNumber=fontNumber)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Caskroom/miniforge/base/envs/font/lib/python3.11/site-packages/fontTools/ttLib/sfnt.py", line 62, in __init__
raise ttLib.TTLibError("specify a font number between 0 and %d (inclusive)" % (self.numFonts - 1))
fontTools.ttLib.TTLibError: specify a font number between 0 and 3 (inclusive)
Hi @Rahul-fix, that seems like a problem with the python script.
If you are already using FontLab, then you don't really need Python any more. Simply add the whole font-features directly in FontLab, as it is a full-blown font editor solution. With FontLab you can also directly test the font in the integrated test-bench and are able to directly see the effect of the font-features. Futhermore you can compile the whole font including it's features with FontLab and are able to export the final Font-Files. So thats the premium solution without the need for any external hacky scripts and extra stuff ;-)
https://help.fontlab.com/fontlab/7/manual/OpenType-Features/
I was recently active with FontLab again, so I made some screenshots to make it easier for other users to get active.
First of all, open a font-file with FonLab.
Afterwards open the "Feature" Panel if it is not already visible.
Now you can start adding OpenType features. The one that is use for the bionic speed reading functionality is "calt" contextual alternatives. If it is not already included in the font you can add it via the + symbol.
Afterwards just add the whole program code that you can find in the repo. opentype_feature.fea
Use the code as it is or alternate it as you wish. Afterwards test the font and export it.
Hi thank you this is really helpful! I did what you outlined above for the Bookerly font (Bookerly.ttf) and ran into this error after pressing the play button. I am a lay person and don't know anything about coding so wanted to ask for some guidance as the preview does not seem to be reflecting the feature.
The problem are the lines claiming "Missing glyphs" That means, that there are more letters/ glyphs covered in the pgoram code and the "Fast-Font", than that there are existent in the Bookerly.ttf.
As an explanation, the first line with "Missing glyph: uni0334 -> uni1D6C" tells you that the Unicode-Character uni1D6C is missing in the Bookerly.ttf. Looking the character up on the web tells you that it is a character from the greek alphabet, that is not covered by the Bookerly.ttf.
There are two ways to fix this:
So, just delete the code lines at the beginning.
And delete the two lines with the russian, cyrillic characters, if you don't need them.
Afterwards try to compile again. If he is still complaining about missing glyps search the code for this glyphs and also remove them 😉
Thank you very much! Any idea what I should do about the bottom two red errors about calt and "fatal error"? They still show up even after I remove those codes for the missing glyphs. The preview also does not seem to be working yet either.
I really like that you keep on trying. Don't give up, you are getting better and learn with each step! To help you and other users with the whole process, I wrote a Tutorial explaining the whole process with Screenshots. You can find it here: Tutorial
Regarding your error messages... ... working with Font-Features is like programming. You get errors and with the errors try to fix the mentioned lines. The bottom red errors are also referring to missing glyps. To get the base font working just remove the code that is related to the marked problems.
I recently also added the Fast-Reading features to another font, that was missing many glyphs, so like you I had the need to reduce the code. For me this reduced version worked.
feature calt {
@de = [adieresis odieresis udieresis Adieresis Odieresis Udieresis germandbls];
@DE = [adieresis.bold odieresis.bold udieresis.bold Adieresis.bold Odieresis.bold Udieresis.bold germandbls.bold];
#EU languages: Albanian, Bosnian, Croatian, Czech, Danish, Dutch, Estonian, Finnish, French, Hungarian, Italian, Lithuanian, Montenegrin, Norwegian, Polish, Portugese, Romanian, Serbian, Slovene, Spanish, Swedish, Turkish
@eu = [aring Scaron OE Zcaron Aring scaron oe zcaron Ydieresis Agrave Aacute Acircumflex Atilde AE Ccedilla Egrave Eacute Ecircumflex Edieresis Igrave Iacute Icircumflex Idieresis Ntilde Ograve Oacute Ocircumflex Otilde Oslash Ugrave Uacute Ucircumflex Yacute agrave aacute acircumflex atilde ae ccedilla egrave eacute ecircumflex edieresis igrave iacute icircumflex idieresis ntilde ograve oacute ocircumflex otilde oslash ugrave uacute ucircumflex yacute ydieresis Abreve abreve Aogonek aogonek Cacute cacute Ccaron ccaron Dcaron dcaron Dcroat dcroat Edotaccent edotaccent Eogonek eogonek Ecaron ecaron Gbreve gbreve Iogonek iogonek Idotaccent dotlessi IJ ij Lslash lslash Nacute nacute Ncaron ncaron Ohungarumlaut ohungarumlaut Rcaron rcaron Sacute sacute Scedilla scedilla Tcaron tcaron Umacron umacron Uring uring Uhungarumlaut uhungarumlaut Uogonek uogonek Zacute zacute Zdotaccent zdotaccent];
@EU = [aring.bold Scaron.bold OE.bold Zcaron.bold Aring.bold scaron.bold oe.bold zcaron.bold Ydieresis.bold Agrave.bold Aacute.bold Acircumflex.bold Atilde.bold AE.bold Ccedilla.bold Egrave.bold Eacute.bold Ecircumflex.bold Edieresis.bold Igrave.bold Iacute.bold Icircumflex.bold Idieresis.bold Ntilde.bold Ograve.bold Oacute.bold Ocircumflex.bold Otilde.bold Oslash.bold Ugrave.bold Uacute.bold Ucircumflex.bold Yacute.bold agrave.bold aacute.bold acircumflex.bold atilde.bold ae.bold ccedilla.bold egrave.bold eacute.bold ecircumflex.bold edieresis.bold igrave.bold iacute.bold icircumflex.bold idieresis.bold ntilde.bold ograve.bold oacute.bold ocircumflex.bold otilde.bold oslash.bold ugrave.bold uacute.bold ucircumflex.bold yacute.bold ydieresis.bold Abreve.bold abreve.bold Aogonek.bold aogonek.bold Cacute.bold cacute.bold Ccaron.bold ccaron.bold Dcaron.bold dcaron.bold Dcroat.bold dcroat.bold Edotaccent.bold edotaccent.bold Eogonek.bold eogonek.bold Ecaron.bold ecaron.bold Gbreve.bold gbreve.bold Iogonek.bold iogonek.bold Idotaccent.bold dotlessi.bold IJ.bold ij.bold Lslash.bold lslash.bold Nacute.bold nacute.bold Ncaron.bold ncaron.bold Ohungarumlaut.bold ohungarumlaut.bold Rcaron.bold rcaron.bold Sacute.bold sacute.bold Scedilla.bold scedilla.bold Tcaron.bold tcaron.bold Umacron.bold umacron.bold Uring.bold uring.bold Uhungarumlaut.bold uhungarumlaut.bold Uogonek.bold uogonek.bold Zacute.bold zacute.bold Zdotaccent.bold zdotaccent.bold];
@sp = [@de @eu];
@SP = [@DE @EU];
@az = [a-z A-Z @sp];
@AZ = [a.bold-z.bold A.bold-Z.bold @SP];
@all = [@az @AZ @sp @SP];
#17
ignore sub @all @all @all @all @all @all @all @az' @all @all @all @all @all @all @all @all @all @all;
sub @all @all @all @all @all @all @az' @all @all @all @all @all @all @all @all @all @all by @AZ;
#14,15,16
ignore sub @all @all @all @all @all @all @az' @all @all @all @all @all @all @all @all;
sub @all @all @all @all @all @az' @all @all @all @all @all @all @all @all by @AZ;
#12,13
ignore sub @all @all @all @all @all @az' @all @all @all @all @all @all;
sub @all @all @all @all @az' @all @all @all @all @all @all @all by @AZ;
#9,10,11
#ignore sub @all @all @all @all @az' @all @all @all @all @all @all;
ignore sub @all @all @all @all @az' @all @all @all @all @all;
sub @all @all @all @az' @all @all @all @all @all by @AZ;
#7,8
ignore sub @all @all @all @az' @all @all @all @all;
sub @all @all @az' @all @all @all @all by @AZ;
#4,5,6
#ignore sub @all @all @az' @all @all @all;
ignore sub @all @all @az' @all @all;
sub @all @az' @all @all by @AZ;
#1,2,3
ignore sub @all @az';
sub @az' by @AZ;
} calt;
If you don't need any special characters, and just want the basic reading functionality, I guess the basic latin-alphabet would also be enough. The complete reduced code would look like this. This code version should work with every font out there, because it's just using the basic latin alphabet and no special characters at all.
feature calt {
@az = [a-z A-Z];
@AZ = [a.bold-z.bold A.bold-Z.bold];
@all = [@az @AZ];
#17
ignore sub @all @all @all @all @all @all @all @az' @all @all @all @all @all @all @all @all @all @all;
sub @all @all @all @all @all @all @az' @all @all @all @all @all @all @all @all @all @all by @AZ;
#14,15,16
ignore sub @all @all @all @all @all @all @az' @all @all @all @all @all @all @all @all;
sub @all @all @all @all @all @az' @all @all @all @all @all @all @all @all by @AZ;
#12,13
ignore sub @all @all @all @all @all @az' @all @all @all @all @all @all;
sub @all @all @all @all @az' @all @all @all @all @all @all @all by @AZ;
#9,10,11
#ignore sub @all @all @all @all @az' @all @all @all @all @all @all;
ignore sub @all @all @all @all @az' @all @all @all @all @all;
sub @all @all @all @az' @all @all @all @all @all by @AZ;
#7,8
ignore sub @all @all @all @az' @all @all @all @all;
sub @all @all @az' @all @all @all @all by @AZ;
#4,5,6
#ignore sub @all @all @az' @all @all @all;
ignore sub @all @all @az' @all @all;
sub @all @az' @all @all by @AZ;
#1,2,3
ignore sub @all @az';
sub @az' by @AZ;
} calt;
Hi, I want to modify the kindle font "Bookerly" to have same features as Fast-Fonts. How I can achieve it? Is it even possible? I am using the custom Bookerly fonts from here: drive from reddit I tried the following and got the error: