Typophile

mysterious inflation in OTF file size

RaseOne FTA0 votes

I have an old font that I created a decade or so ago. It's an insane font created with paths that were created by an auto-trace. The glyphs have relatively insane numbers of the paths.

Over the years I have cleaned it up a little here & there resulting in a slowly shrinking file size and smoother performance. I've finally taken the tie to do a more thorough clean up of the font on on exporting the otf & ttf files from FontLab 5.1.4 for mac I noticed that the resulting files are significantly bigger that the last revision.

The newer version has 20% or so less paths & no other intentional changes, no new glyphs etc…. so this should not be the case.
I've gone through the font glyph by glyph to verify that it truly does have far fewer paths.

Does anyone have any ideas how I might further investigate this issue? It is a free font & people like it. The clean up barely changes it's appearance at all & is definitely a good thing but my goal is to make the font less computationally demanding, not more.

Thanks

- I downloaded your font
- made .pfa Type1 font
- in command line mode:
makeOTF -f c:\...\font.pfa -S
( http://www.adobe.com/devnet/opentype/afdko.html )

I get otf font 88 kB, your original font is 110 kB. The key is option -S.
BTW open/generate font in FontForge and FontLab makes much bigger files.

Thank you so much JanekZ!

I am updating my copy of the Adobe FDK right now. I am fairly lame in command line & only a novice user of the adobe fdk. Your instructions seem simple enough & I think I can pull it off. Can you fill me in on the nature of option -S ? is that just a request to display the file size?

I've been cut off from font forge for a while due to operating system upgrades and the lack of an installable binary for the newer versions. Are you aware of any fontforge binary out there on the net anywhere that will run under mac os 10.8 or higher?

I suppose I've got nothing to hide here so here are some links to the exact font files in question.

http://www.graffitifonts.com/downloads/paintcans_old.otf
http://www.graffitifonts.com/downloads/paintcans_new.otf

"the nature of option -S ?"

It looks option -r is good, but I don't have GlyphOrderAndAliasDB file at hand.
"Are you aware of any fontforge binary"
I know nothing, but you may find this useful http://fontforge.github.io/en-US/downloads/mac/

oops, sorry about that. The directory is password protected.

user: guest
pass:welcome

Thank you for the info on options -s & -r

Not entirely sure if font forge is of any particular use to me anymore but I am partial to open source software so I'll take a fresh look. I enjoyed having it in my arsenal. It has nice error reporting.

Thanks!

1) Open font and generate Type1 font - .pfa file
2) (in FontLab) generate GlyphOrderAndAliasDB
use this script http://typophile.com/node/75834
remove font name in generated file name
3) Save this as FontMenuNameDB file:
[PaintCans]
f=PaintCans
s=Regular
c=PaintCans
c=1,PaintCans

All your files are in one folder with font.pfa

4) Finally:
makeOTF -f c:\...\font.pfa -r

5) Your new font:

Job done!

holy smokes! Thanks for the run through. I'll give it a try right now & report back on the results for the benefit of any future readers.

It's funny I can see the massive number of glitched out paths right in your screen shot. The new version has a lot less of that. In my own defense I have newer fonts made by the same method that don't have these problems but this horrifying old font gets around a lot. It will be great to make it less embarrassing.

Ok that seems to have worked well. I think I messed up the first step but I bumbled through it easy enough.

Here's the process in more detailed terms that might be easier to digest.

1.) I used FontLab to create a Postscript version of the font (ASCII/UNIX Type1 ). This creates 4 files: .pfa, .pfm, .inf, .afm

2.) I downloaded the scripts created by Arno Enslin here: http://typophile.com/node/75834

3.) I removed the .txt extention from the end of the downloaded file so my mac would recognize it as a zip file then uncompressed the file & moved into FontLabs standard location for macros & scripts located at Library/Application Support/FontLab/Studio 5/Macros

4.) In FontLab I went to WINDOW>PANELS>EDIT MACROS to open the EDIT MACROS window. I dragged the "Generate_GlyphOrderAndAliasDB_file.py" file into the EDIT MACROS window. The contents of the file appeared in the window.

5.) I hit the RUN MACRO button at the top of the window that looks like a "play" button. This generated the GlyphOrderAndAliasDB file in the folder along with the rest of the type1 font files.

6.) The font in this example was called "PaintCans" so I created a plain-text file named FontMenuNameDB (no file extension) with the following contents and saved it to the folder with the other font files.
[PaintCans]
f=PaintCans
s=Regular
c=PaintCans
c=1,PaintCans

7.) Having the latest Adobe Font Dev Kit for OpenType installed ( Adobe FDKO ) I ran the "makeOTF" script by opening a terminal window and entering:
makeOTF -f c:\...\font.pfa -r

This all worked like a charm and the Adobe makeOTF script spit out an OTF file into the directory with the other files.

This shaved about 7kb off of the file size which is great. I'm not sure why but it's still good.

I had an original font at 166kb. I removed thousands of paths and somehow wound up with a font that was 253kb (bigger when I expected smaller). This method did produce a smaller file but only by a little bit. I was hoping to understand where all this extra file size had come from & to wind up with a new file under 166kb.

Did I screw it up by using FontLab to create the initial Type1 file?

Any thought on where I might go next?

I don't know, it could be FontForge writes down something differently (hinting?). I generated .pfa file as "Type1 (Ascii)" in FontForge, ca 1,5 MB. The rest of this process looks the same. New font file PaintCans_GW.otf is 198 040 bytes (your original paintcans_new.otf is 252 948 bytes).
I created another file - with all hints removed. New file is 167 540 bytes.
That's all for today. Good night!

Edit: your old font has no hints at all - it justify this big difference in size.

That's it!

I had some indication that it was hinting data early in the process but I mistakenly thought the old one had hinting as well. In fact I accidentally auto hinted my FontLab file for the old version some time in the past… so I was totally unable to to reproduce the smaller version from the original source file. The hinting carried over into the new revision & confusion ensued.

I see now that the OTF files for the old version have no hinting but the FontLab file does. I was looking right past this as I thought I had eliminated this possibility. I'm very glad to see it's a simple solution.

I will add that you are still able to get a significantly smaller file through the process above than I am. I will investigate that on my own but in any case you are arriving at right about the expected file size by removing the hinting & this makes me very happy.

I really appreciate you taking the time to help out with this. You have just spared the entire future of the digital world untold millions of useless bits. I will do my best to pass the favor on to some other unfortunate soul… or back to you if there is anything you need.

"you are still able to get a significantly smaller file"
That's strange.
[edited]

If you remove contours that fit in a 4x4 (resp. 5x5) rectangle, you can reduce the size to 115K (resp. 86K). For a limited time only no 4x4 and no 5x5 speckle in PaintCans.

Michel

Wow, cool. Thanks both of you!

I've downloaded the files from both of you & I'm working on compiling a new copy of font forge tonight. I should be able to reproduce everything you have done in these examples soon. My working copy of paintcans_new.otf is now on course to be somewhere between 150k & 168k. Now I see I may be able to get it even smaller. Good stuff.

This font has escaped my control & gets around the internet under it's own power. I've spent far more time messing with it over the last several days than I spent making it all those years ago. It is an inadvisable way to make a font to say the least but it has lead to this great learning experience.

I made a number of path adjustments, kerning adjustments & transformations that make the font a lot better from a design perspective so I'm glad I got into this. I'll come back and post a final version after I run it through fontforge from step 1 to shave off those extra bits.

I figure you would have to be nuts to use this font at any size that would benefit from hinting

I can see what you did there & the speed with which you can accomplish that with your method is great. I'm working manually to treat & reduce those little speckles but this process you've showed me could certainly come in very handy. The reduction is size is significant but the visual effect is a bit random. A great trick to learn in any case. Thank you!

If you look at the newer version you will see there are a lot less of those & many of them have been enlarged to a more reasonable size & moved so they do not overlap.

This font also has a pretty bad problem with nodes that have fallen in exactly the same place so there are many nodes directly on top of each other. I have fixed tons of them manually but a script based solution could go a long way here with little or no visual impact. Do you have any magic for that?

The file size depends on the number of points. Identifying contours that fit in a 5x5 square is a basic exercise with Python and removing them (or rather drawing a new glyph without them) is only a few lines. Here nf is the new font where I draw the glyphs for some selection I made in FontForge

for g in font.selection.byGlyphs:
if g.foreground and len(list(g.foreground)) != 0:
pen=nf[g.glyphname].glyphPen()
for c in g.foreground:
if largeside(c)>5:
c.draw(pen)
pen = None

where largeside is length of the large side of the rectangle that circumscribes the contour.

Something else that could be tried* is removing only tiny contours that create holes because, once printed, they should disappear due to flowing ink, unless the character is printed very large.

*Something still easier to do: when largeside(c) is not larger than 5, decide with some probabilty  p  to draw the contour c too. That might help keeping the appearance and, starting with 86K, there is room to add contours. Those contours could also be enlarged (with matrix transformations instead of doing it by hand).

That is fantastic tool, but unluckily doesn't work on my computer (winXP SP3, FF 31 DEC 2014, python 2.7 2012)
"Execution of script c:\...\1.py failed"
or new message:
"NameError: name 'font' is not defined"

Sorry, that is just a stub. It is not the full script. The tool is something that can be clicked in the tools menu and requires a file in a special format (on unix, in the ~/.fontforge/Python directory).

Here is a full script usable as a script. The advantage in copying in a new font and copying back is that the operation can be undone and redone (copy can be undone). I could not get that behaviour otherwise.

import fontforge;
ff=fontforge

cwidth = {} # **
def largeside(c):
(xmin,ymin,xmax,ymax) = c.boundingBox()
width = xmax-xmin
height = ymax - ymin
if width > height: return width
else: return height

f = ff.activeFont()
# f.copy() # **
nf= ff.font()
fsel = f.selection.byGlyphs;
for g in fsel:
nf.createChar(g.unicode,g.glyphname)
nf.selection.select(("more",None), g)
# nf.paste() # **
for g in fsel:
cwidth[g.glyphname] = g.width # **
if g.foreground and len(list(g.foreground)) != 0:
pen=nf[g.glyphname].glyphPen()
for c in g.foreground:
if largeside(c)>5:
c.draw(pen)
pen = None
nf.copy()
f.paste()
for g in fsel: # **
g.width = cwidth[g.glyphname] # **
nf.close()

# ** Modifications according to post below

Works like a charm!
I suppose it can be ignored:
line 12, in
f.copy()
AttributeError: 'NoneType' object has no attribute 'copy'

Many thanks for such a great tool.
edit: I generated again the PaintCans_GW.otf, this time 98 304 B, and from .pfb - 93 415 B.

I see that for some reason the character widths were not preserved by my code. The lines

f.copy()
nf.paste()

can indeed be removed and are now commented out. I also modified the code so as to keep a dictionary of the glyph widths before the clean up so as to restore those widths in the end.

Hello again Michel & JanekZ & anyone else.

I wound up adding a bunch of characters to that paintcans font so final processing & reduction have been delayed a bit. All of your info was quite helpful though.

I still think I am failing to strip away all the hinting data from not just this font but a few others as well. I have mysterious file inflation of 20-60k on a few fonts & hinting data is my best guess. I have a fairly good handle on the basics of hinting controls in fontlab & fontforge but there must be something I'm missing. I've been through the manual & all over the net looking for ideas.

Can anyone suggest one sure method to know for sure if any hinting data is present and/or one sure method to remove all hinting data if any is present?

I may be on a wild goose chase but I'd like to know once & for all.

Captured from web.archive.org on 11 Sep 2019. view this capture