Downsizing an .OTF font by removing glyphs

2020-02-24 12:21发布

问题:

I can't quite believe this question hasn't been asked specifically for OpenType fonts, but does anyone know of a way to remove glyphs from these fonts?

I have an .OTF with a very large file-size (almost 10MB) and I need to make it smaller. The reasons are two fold.

1) I'm trying to prepare it for web embedding, so the smaller the files, the easier for the client.

2) Font Squirrel (used for easy preparation of font files) has a 2MB upload limit - I know there are alternatives, but none so far have been successful. To save wasting peoples time, the ones I've tried that have failed are http://fontface.codeandmore.com/ and http://www.font2web.com/. CodeAndMore.com appears to work, but the fonts it spits back out are completely different to the one I gave it.

Please be aware I'm not a font expert, so go easy on the answer.

回答1:

Created an account for answering this question. I know that it's an old question. But it's better to have a late answer than having no answer.

I've just run into a similar issue. Apparently, there is no Googlable solution. Therefore, I've written a Python2 script with fontforge library does the following:

  • Accepts a source font
  • Accepts a file containing all characters to be used. It can be a translation file, string asset file, HTML file, etc.
  • Output a font with characters that aren't shown in the file removed

Here is the code:

#!/usr/bin/python2
import sys
import fontforge

if len(sys.argv) == 4:
    font = fontforge.open(sys.argv[1])

    f = open(sys.argv[2], "r")

    for i in f.read().decode("UTF-8"):
        font.selection[ord(i)] = True
    f.close()

    font.selection.invert()

    for i in font.selection.byGlyphs:
        font.removeGlyph(i)

    font.generate(sys.argv[3])
else:
    print "WARNING: Check the license of the source font\nbefore distributing the output font generated by this script.\nI'm not responsible for any legal issue caused by\ninappropriate use of this script!\n"
    print "Usage: {} [source font] [file with glyphs NOT to be removed] [output]".format(sys.argv[0])
    print "Example: {} /path/to/ukai.ttc chineseTranslation.txt ukaiStripped.ttf".format(sys.argv[0])

Please notice that it may not be legal to use this script on certain fonts. Ensure to checkout the license of the source font. I'm not responsible for any legal issue caused by using any font generated by this script.



回答2:

FontTools has a program called pyftsubset that does it

https://github.com/behdad/fonttools

Usage something like this:

pyftsubset MyFont.otf --output-file=MyFontStripped.otf --unicodes-file=file-of-codes.txt

Where file-of-codes.txt contains a list of codes like:

U+09c78
U+09ce5
U+09ce7
U+09ce9
U+09ceb
U+09cec
U+09cf0
U+09cf3
U+09cf4
U+09cf6
...


回答3:

Following latest comment: You can select several sets at a time in the left menu (Languages) using shift and command key all in one shot. Note the image keeps the Basic Latin (A-Z a-z). Once you have the sets selected click in the glyphs window and Select All (cmd-A). It will take some time if there are a lot as this case. Then cmd-Delete and you remove all. You only need to repeat the operation with 'Categories' and you're done. Then export .otf



回答4:

A 10 MB Opentype font is very rare because it's very heavy weight, so I assume it's an in-house specific font and not commercial. For removing glyphs you can edit the font in FontForge (free) or any other commercial font editor and after that regenerate the .otf (also .ttf)

For building webfonts (I guess you'll need .ttf, .svg, .eot and .woff) you can use locally several free tools: sfnt2woff, ttf2eot, Batik SVG and with ttfautohint you can improve the way the font will look in the screen before making the conversion.



回答5:

Ran into this today because I was trying to save a font after CTRL+A and setting width (don't do that, btw). I went with a little more straight-forward Python scripting approach since I already had the font open in FontForge.

This assumes that you have the intended font open and have it active. It also supposes that you only want to keep the first 128 characters (ASCII range). It selects everything then uses the "less" flag to deselect the range from 0-127. Have a look at the FontForge Python scripting guide for some more info on the different ways you can manipulate the selection.

File > Execute Script

font = fontforge.activeFont()
font.selection.all()
font.selection.select(("ranges","less"),0,127)
font.clear()


回答6:

fonttools has now been adopted by Google: https://github.com/googlei18n/fonttools. I've been using it to reduce the number of glyphs in Google's Noto fonts for use in an embedded system. Works a treat!