afdko
afdko copied to clipboard
[makeotfexe] writes pre-determined glyph order, different from input font glyph order
According to makeotfexe docs, the -nga switch is supposed to turn off glyph reordering:
-ga/-nga : Quick mode. Use/do not use the GlyphOrderAndAliasDB file to
rename and re-order glyphs. Default is to not do the renaming and
re-ordering. If used after -r, -nga overrides the default -r setting.
But it does not. Here is a (disassembled) pfa with five glyphs in order D C B A .notdef. When this pfa is passed to makeotfexe -nga, the resulting font has the glyphs in the reverse order .notdef A B C D. I know that .notdef will always be moved to GID 0. But the others should remain in their current order, so the resulting font should be ordered .notdef D C B A.
%!
0 dict dup begin
/FontName /Test def
/Private 0 dict dup begin
/RD {string currentfile exch readstring pop} def
/CharStrings 5 dict dup begin
/D {
0 1000 hsbw
0 0 rmoveto
0 1000 rlineto
1000 0 rlineto
closepath
endchar
} def
/C {
0 1000 hsbw
0 0 rmoveto
0 1000 rlineto
1000 0 rlineto
closepath
endchar
} def
/B {
0 1000 hsbw
0 0 rmoveto
0 1000 rlineto
1000 0 rlineto
closepath
endchar
} def
/A {
0 1000 hsbw
0 0 rmoveto
0 1000 rlineto
1000 0 rlineto
closepath
endchar
} def
/.notdef {
0 1000 hsbw
0 0 rmoveto
0 1000 rlineto
1000 0 rlineto
closepath
endchar
} def
end % of CharStrings dict
def
end % of Private dict
Somewhat related to #1153.
-nga switches adherence to the GOADB off, so your result might be expected?
If you want to apply glyph ordering, use -ga or -r for release mode.
My (perhaps incorrect) expectation based on the docs is that the GOADB can reorder the glyphs, but otherwise the resulting font retains the existing glyph order within the source. Thus makeotfexe with the -nga flag — or with no flag at all, because “Default is to not do the … re-ordering” — ought to preserve the glyph order in the source.
The workaround, of course, is just to generate a GOADB file with the glyphs in the same order as the PFA, which I have done. I’m just observing that the behavior of makeotfexe seems to be different from its documentation. Moreover even without a GOADB file, makeotfexe seems to be applying some kind of non-random ordering rule, and it’s not clear what this rule is.
That’s strange and indeed should not happen. Have you observed the same with e.g. UFO files?
I don’t use UFO, nor do I use the Python interface to makeotfexe.
You don’t have to use the Python interface to makeotfexe (don’t know how to do that, even).
I suggested using UFO because they are free of any pre-determined glyph order (unlike Type 1 fonts, where some assumptions might be made, not sure).
However, I could not reproduce the bug you are referring to (makeotf ordering glyphs different from glyph order if no GlyphOrderAndAliasDB is given).
Try the attached example. It has equivalent UFO and PFA file with glyphs .notdef space A B C D E F G and a GlyphOrderAndAliasDB with glyph order .notdef space G F E D C B A .
For both formats:
| command | result | verdict |
|---|---|---|
makeotf -r |
GlyphOrderAndAliasDB is applied, font has order GFEDCBA |
(expected) |
makeotf -r -nga |
GlyphOrderAndAliasDB is switched off despite release mode, font has order ABCDEFG |
(expected) |
makeotf |
resulting development mode font has glyph order ABCDEFG |
(expected) |
makeotf -ga |
resulting development mode font has glyph order GFEDCBA |
(expected) |
makeotf -ga -nga |
resulting development mode font has glyph order GFEDCBA |
(bug, IMO) |
Maybe I am fooling myself here since I should have used an input file with truly random glyph order, stay tuned for that test.
I changed to glyph order in the UFO/PFA files to be B A D C F E G, while the GlyphOrderAndAliasDB stays the same.
PFA: makeotf → A B C D E F G (bug confirmed, order should be as in input file)
UFO: makeotf → A B C D E F G (bug confirmed, order should be as in input file)
Updated test case attached.
I don’t think there should be a reason for makeotf to reorder glyphs beyond the .notdef.
Thanks for finding this!
You don’t have to use the Python interface to makeotfexe (don’t know how to do that, even).
Docs: “makeotf is a command shell that calls the Python™ script makeotf.py”
Thanks for that note, I did not realize that was what you meant. Why exactly do you prefer typing makeotfexe over makeotf (just curious)?
I will rename the title of this issue to reflect the nature better – it’s not so much about the -nga switch anymore, but about makeotf writing some kind of pre-defined glyph order.
I”m embedding makeotfexe in a larger application so the Python wrapper is unnecessary.
any progress in this issue? Im getting similar results where the order of the source has been altered, without flagging releaseMode or using a GOADB
a simple script to show the problem:
import tempfile
import os
from fontTools.ttLib import TTFont
from fontTools import fontBuilder
from fontTools.pens.t2CharStringPen import T2CharStringPen
# define order
order = [".notdef", "space", "a", "z", "square", "c", "triangle", "b"]
# some basic setting for fontBuilder
nameStrings = dict(
familyName="Glyph",
styleName="Order",
fullName="Glyph-Order",
psName="Glyph-Order",
)
pen = T2CharStringPen(600, None)
charString = pen.getCharString()
charStrings = {glyphName: charString for glyphName in order}
cmap = {ord(glyphName): glyphName for glyphName in order if len(glyphName) == 1}
# create a temp folder
with tempfile.TemporaryDirectory() as root:
sourcePath = os.path.join(root, "source.otf")
binaryPath = os.path.join(root, "dest.otf")
# build the font as simple as posible
builder = fontBuilder.FontBuilder(1000, isTTF=False)
builder.setupGlyphOrder(order)
builder.setupNameTable(nameStrings)
builder.setupCFF(nameStrings["psName"], {"FullName": nameStrings["psName"]}, charStrings, {})
builder.setupCharacterMap(cmap)
builder.setupPost()
builder.save(sourcePath)
binary = TTFont(sourcePath)
print(binary.getGlyphOrder(), binary.getGlyphOrder() == order)
binary.close()
cmds = [
"makeotf",
"-f", sourcePath,
"-o", binaryPath,
]
print(" ".join(cmds))
r = os.popen(" ".join(cmds)).read()
print(r)
binary = TTFont(binaryPath)
print(binary.getGlyphOrder(), binary.getGlyphOrder() == order)
binary.close()