Making OT/TTF layout features work in MS Word 2010

Matthew Butterick
Matthew Butterick Posts: 143
edited December 2012 in Type Design Software
I'm not the first to get tripped up by this. But I came up with a solution suitable for the cheap & lazy—er, economical & efficient.

For bad and arbitrary reasons, OT/TTF fonts with layout features are only recognized as such in Windows if they have a DSIG (digital signature) table. Without this table, they behave as normal TTF fonts (i.e., none of the layout features work). This is not true of OT/CFF fonts, which need no DSIG table.

Windows customers can use OT/CFF fonts. But MS Office, and MS Word in particular, still works better with TT-based fonts. For instance, for bad and arbitrary reasons, the built-in PDF generator in Word will not embed OT/CFF fonts, only OT/TTF.

To make a DSIG, one solution is to buy an actual digital signature from a certificate authority. Fontlab, for instance, can generate the DSIG table if you have the signature files. (Don't know how it's handled in Glyphs or Robofont.) But this is about $200 per year. Digitally signing your fonts has other ostensible benefits, so if you like that, great. To me, it's a lot to pay just to get OT/TTF fonts to do what they should've been able to do in the first place, which is: work.

FontForge can put in a dummy DSIG table, but that requires dealing with FontForge.

If you have ttx installed, however, you can do it this way:

Create a ttx file with a dummy DSIG table, like so:
<?xml version="1.0" encoding="ISO-8859-1"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="2.2">
<DSIG>
   <hexdata>
     00000001 00000000  
   </hexdata>
</DSIG>
</ttFont>
Then you can merge this into your OT/TTF like this:

ttx -m font.ttf dsig.ttx

This will decompile the ttf, add the DSIG table, and recompile in one step. Then the font will work as intended in MS Office (or so I have found in my testing thus far.) This is also easy to incorporate into other scripts.

Of course, this is not a real digital signature, but it's sufficient to convince Windows that the font has a valid DSIG table.

(Hat tip to Ross Mills for pointing me in the right direction.)

Comments

  • This topic, and a similar solution using different tools was earlier discussed at Typophile: http://typophile.com/node/29770
  • This topic, and a similar solution using different tools was earlier discussed at Typophile: http://typophile.com/node/29770
  • It's only kind of the same topic. The lack of an OT icon is a minor/aesthetic issue, compared to losing the actual OpenType feature functionality. I've known about the icon issue for many years, but if there is an actual functionality issue, that's a big deal.

    I'll be curious to learn if this affects web fonts, either in IE or in general.
  • Indeed Thomas, the topic is not exactly similar. But the moment I saw Matthew’s post I just knew I saw that hack somewhere before...
  • I saw that hack somewhere before
    I think of my hack as a humanist revival of a hack from the previous decade.
  • "...but if there is an actual functionality issue, that's a big deal."

    That's odd. When the table was announced in the 90's, all developers were told that fonts without a DSIG would eventually not work at all on Windows. So, this's a fine compromise.
  • With Office on Windows, for many years a missing DSIG had no meaningful consequences, since Office didn't support OpenType layout features anyhow. That only changed with Office 2010.

    Perhaps predictably, Word 2010 still doesn't implement the DSIG restriction consistently: OT/TTF fonts without a DSIG will still show their layout features in the preview window of the Character formatting box, but the layout features won't show up in the document itself. This was the moment of infuriation that started my hacking spree.

    Despite the infuriations, Word is nevertheless the most popular typesetting program in the world, and with the addition of layout features, it's actually quite capable.
  • Nick Shinn
    Nick Shinn Posts: 2,207
    “Popular”?
    Like income tax.
  • Word is nevertheless the most popular typesetting program in the world
    Huh. I'da thought it'd be some web-based thing, like a browser. Where are you getting your stats?

    Also, what happens if you output the word-document-with-OT-features-used — to a web site, does any it display in... Firefox?
  • 'FontForge can put in a dummy DSIG table, but that requires dealing with FontForge.'

    In DTL OTMaster one can copy a dummy DSIG table from another TTF, but that requires dealing with DTL OTMaster.
  • With fontTools rev.612 (running on 10.8.2), I get a Traceback and a KeyError: 'ulVersion' when I try to merge the table into the TTF as described above. Is it just me or is anybody else also experiencing that problem?
  • Post the whole traceback please, otherwise no way to ascertain the cause of the error.

    Also check if you need this fix.
  • Appreciate your help! The fix did not help though. Or did I do it wrong: I changed macUtils.py as indicated and ran sudo python setup.py install again.
    mekka$ ttx -m test.otf dsig.ttx 
    Compiling "dsig.ttx" to "dsig#1.ttf"...
    Parsing 'DSIG' table...
    Traceback (most recent call last):
    File "/usr/local/bin/ttx", line 11, in
    ttx.main(sys.argv[1:])
    File "/Library/Python/2.7/site-packages/FontTools/fontTools/ttx.py", line 295, in main
    process(jobs, options)
    File "/Library/Python/2.7/site-packages/FontTools/fontTools/ttx.py", line 280, in process
    action(input, output, options)
    File "/Library/Python/2.7/site-packages/FontTools/fontTools/ttx.py", line 186, in ttCompile
    ttf.save(output)
    File "/Library/Python/2.7/site-packages/FontTools/fontTools/ttLib/__init__.py", line 200, in save
    self._writeTable(tag, writer, done)
    File "/Library/Python/2.7/site-packages/FontTools/fontTools/ttLib/__init__.py", line 596, in _writeTable
    tabledata = self.getTableData(tag)
    File "/Library/Python/2.7/site-packages/FontTools/fontTools/ttLib/__init__.py", line 608, in getTableData
    return self.tables[tag].compile(self)
    File "/Library/Python/2.7/site-packages/FontTools/fontTools/ttLib/tables/D_S_I_G_.py", line 57, in compile
    packed = sstruct.pack(DSIG_HeaderFormat, self)
    File "/Library/Python/2.7/site-packages/FontTools/sstruct.py", line 69, in pack
    value = object[name]
    KeyError: 'ulVersion'
    Does this tell you anything?
  • It tells me you appear to be using a development build of FontTools rather than the latest official release, which is version 2.3.
  • Old topic, but I was playing around with scripting this in Robofont yesterday with the added idea of making a pile of fonts with unique IDs as the dummy DSIG.

    Haven't had time to test the resulting fonts to see exactly how viable this is, but it's a start if anyone wants to fork: https://gist.github.com/okay-type/9060558
  • Ben Kiel
    Ben Kiel Posts: 34
    edited August 2014
    For those seeing things like what Rainer got, you are on a more recent version of TTX. You can either put the signature in programtically like so (this needs more to run, it is just a method that takes in a TTFont, but if you get this, then you'll get the rest of what you need to do):
    def makeDSIG(font):
        from fontTools.ttLib.tables.D_S_I_G_ import SignatureRecord
        newDSIG = ttLib.newTable("DSIG")
        newDSIG.ulVersion = 1
        newDSIG.usFlag = 1
        newDSIG.usNumSigs = 1
        sig = SignatureRecord()
        sig.ulLength = 20
        sig.cbSignature = 12
        sig.usReserved2 = 0
        sig.usReserved1 = 0
        sig.pkcs7 = '\xd3M4\xd3M5\xd3M4\xd3M4'
        sig.ulFormat = 1
        sig.ulOffset = 20
        newDSIG.signatureRecords = [sig]
        font.tables["DSIG"] = newDSIG
    
    Or you need to copy/paste this into a TTX dump:
    <DSIG>
        <!-- note that the Digital Signature will be invalid after recompilation! -->
        <tableHeader flag="0x1" numSigs="1" version="1"/>
        <SignatureRecord format="1">
    -----BEGIN PKCS7-----
    0000000100000000
    -----END PKCS7-----
        </SignatureRecord>
      </DSIG>
    
  • Ahh, as a newbie to Python, XML and all that, can someone please just explain the process - without the coding. A step-by-step list of what happens, when. For example, do this, copy that, paste it there. Run this, build that. Otherwise all this coding talk is useless to me.

    I'm using a Mac and FontLab and I'm guessing FontLab has to run this ttx script in order to get the dummy DSIG into the TT font? So it should mean I can do that on the Mac and the resulting TTF will work on Windows.

    Thanks,
    Adrian
  • Things are slightly clearer now, in that I know Fonttools (2.4) input should look like the attached file.

    But I don't know where/when this gets used..?
    ttx -m font.ttf dsig.ttx

    Can the process be explained in a simple way listing the actions like this...

    This is what I did in Terminal:

      Enter which ttx, Return.
      Drag ttx app to Terminal (displays the path to the app).
      Drag dsig.ttx to Terminal (displays the path to the text file).
      Drag SassoBoo.ttx file to Terminal (displays actual TrueType font file path).
      Return.
      Compiling begins... (result is a dsig.ttf file).

  • Adrian Williams
    Adrian Williams Posts: 5
    edited October 2014
    Thanks to Michel Bower on another Forum, I managed to arrive at a basic way to get the job done. Your paths and font names will be different. The process follows for Mac OS.

    Make a text file containing:
    https://us.v-cdn.net/5019405/uploads/FileUpload/44/decaba5c59a35eacd266ec3b1984e5.jpg

    1. Launch Terminal.

    2. Type ‘which ttx’, Return:
    /usr/local/bin/ttx adrians-imac:Dsig fldr adrianshome$

    3. Drag TTX app to Terminal (since it accepted your Dsig fldr snippet):
    /Users/adrianshome/Downloads/fonttools-2.4/Tools/ttx

    4. Type: -m (not forgetting a space after the m).
    /Users/adrianshome/Desktop/Dsig\ fldr/SassoBooIta.ttf /Users/adrianshome/Desktop/Dsig\ fldr/dsig.ttx

    First remove all of the dsig#.ttf files in the Dsig fldr if there are any.
    Then for each font file:
    
5. Drag the ttf font file to terminal (say SassoBoo.ttf)
    
6. Drag dsig.ttx to terminal
    
7. Return

    That will compile only dsig.ttx, merge the DSIG into SassoBoo.ttf and produce a file named dsig.ttf in the Dsig fldr, so now…

    8. Rename dsig.ttf as SassoBoo something.ttf (the original TrueType filename)
    There are much better ways to proceed using scripts.

    Don't switch steps 3 and 4. You need to put the .ttf file before the .ttx file.
  • All that was working fine (under Mavericks) until I installed Yosemite and Xcode 6.2.
    Yes, I've re-installed AFDKO 2.5 version 63782. Now, $PATH is is different from the

    Adrians-iMac:Dsig fldr adrianshome$ echo $PATH
    /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/adrianshome/bin/FDK/Tools/osx:/Users/adrianshome/bin/FDK/Tools/osx
    Adrians-iMac:Dsig fldr adrianshome$ 

    A large 1.1Mb file gets dumped in the Dsig fldr and Terminal gets errors perhaps because its trying to access a version of ttx.py in the Python Folder...?

    Adrians-iMac:~ adrianshome$ /Applications/FDK/Tools/osx/ttx /Users/adrianshome/Documents/\ SASSOON/Sassoon\ Fonts\ DEV/Current\ Versions/font+installer\ builds/S9000\ Pinyin/New\ Family/FolderTest/SassoonInftPY.ttf 
    Dumping "/Users/adrianshome/Documents/ SASSOON/Sassoon Fonts DEV/Current Versions/font+installer builds/S9000 Pinyin/New Family/FolderTest/SassoonInftPY.ttf" to "/Users/adrianshome/Documents/ SASSOON/Sassoon Fonts DEV/Current Versions/font+installer builds/S9000 Pinyin/New Family/FolderTest/SassoonInftPY.ttx"...
    Dumping 'GlyphOrder' table...
    /Applications/FDK/Tools/osx/Python/Current/lib/python2.7/site-packages/FontTools/fontTools/ttLib/tables/_h_e_a_d.py:55: UserWarning: 'created' timestamp seems very low; regarding as unix timestamp
      warnings.warn("'%s' timestamp seems very low; regarding as unix timestamp" % stamp)
    Dumping 'head' table...
    Dumping 'hhea' table...
    etc.

    So why are echo $PATH and the resulting path different?





  • Here's what my .profile looks like...

    ##
    # DELUXE-USR-LOCAL-BIN-INSERT
    # (do not remove this comment)
    ##
    echo $PATH | grep -q -s "/usr/local/bin"
    if [ $? -eq 1 ] ; then
        PATH=$PATH:/usr/local/bin
        export PATH
    fi

    # Setting PATH for MacPython 2.5
    # The orginal version is saved in .profile.pysave
    PATH="/Library/Frameworks/Python.framework/Versions/Current/bin:${PATH}"

    # Setting PATH for Python 3.4
    # The orginal version is saved in .profile.pysave
    PATH="/Library/Frameworks/Python.framework/Versions/3.4/bin:${PATH}"
    # Initialization for FDK command line tools.Fri Apr 10 16:42:22 2015
    FDK_EXE="/Users/adrianshome/bin/FDK/Tools/osx"
    PATH=${PATH}:"/Users/adrianshome/bin/FDK/Tools/osx"
    export PATH
    export FDK_EXE
    BTW, why is the <code> appearing in separate lines? How do I format it so its all in one piece?