可安装OpenType字体的Windows要求是什么?

Mik*_*ans 6 windows fonts opentype

利基编程问题:我正在通过字节处理(而不是使用诸如Fontlab或FontForge之类的设计工具)来开发OpenType字体,现在有一个自定义的OpenType-CFF字体,该字体实现了Basic Latin unicode块的一个子集(特别是它实现.notdef和波浪号)。

The CFF block passes tx -3 validation (http://www.adobe.com/devnet/opentype/afdko.html), the font as a whole passes a round-trip de/recompile through TTX (https://github.com/behdad/fonttools), and Microsoft's "Font Validator" (http://www.microsoft.com/typography/FontValidator.mspx) does not report any errors in the font. Loading it as a custom webfont (both as plain otf in browsers that support otf, and wrapped as WOFF in browsers that don't) styles the implemented glyphs correctly.

However, even with all that apparent correctness, the windows font previewer reports that it is not a valid font file, and window will not let me install it. I've looked high and low for information on what windows requires for a font to be installable, but the internet seems to be filled with how to use fonts as a user, rather than what requirements need to be met as developer.

I'm not quite sure what the best way is to include the code for this question, since it's not quite conventional programming; the generator code is in JavaScript, but that code works perfectly fine and generates a for all intents and purposes (save one) proper font.

If you know how to work with hex editors, then the following is the hex string for the font:

4F 54 54 4F 00 09 00 80 00 03 00 10 43 46 46 20 03 00 B4 92 00 00 02 A4 00 00 00 B3 4F 53 2F 32
30 F6 24 D4 00 00 01 00 00 00 00 60 63 6D 61 70 00 0D 00 B7 00 00 02 50 00 00 00 32 68 65 61 64
61 E4 43 91 00 00 00 9C 00 00 00 36 68 68 65 61 06 96 01 52 00 00 00 D4 00 00 00 24 68 6D 74 78
02 A8 00 00 00 00 03 58 00 00 00 08 6D 61 78 70 00 02 50 00 00 00 00 F8 00 00 00 06 6E 61 6D 65
C6 CC FF EC 00 00 01 60 00 00 00 F0 70 6F 73 74 00 03 00 01 00 00 02 84 00 00 00 20 00 01 00 00
00 01 00 00 1A EA FF 64 5F 0F 3C F5 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 14 FF EC 02 BC 02 A8 00 00 00 08 00 02 00 00 00 00 00 00 00 01 00 00 03 EC FE A8 00 00 02 A8
00 00 00 00 02 A8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 50 00 00 02 00 00
00 03 00 00 01 90 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 20 3D 29 20 00 40
00 7E 00 7E 02 A8 FF EC 01 44 03 EC 01 58 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 7E 00 00
00 00 00 08 00 66 00 01 00 20 00 00 00 01 00 0B 00 00 00 01 00 20 00 00 00 02 00 07 00 21 00 01
00 20 00 00 00 04 00 11 00 36 00 01 00 20 00 00 00 05 00 0B 00 69 00 03 00 01 04 09 00 01 00 16
00 0B 00 03 00 01 04 09 00 02 00 0E 00 28 00 03 00 01 04 09 00 04 00 22 00 47 00 03 00 01 04 09
00 05 00 16 00 74 43 75 73 74 6F 6D 20 46 6F 6E 74 00 43 00 75 00 73 00 74 00 6F 00 6D 00 20 00
46 00 6F 00 6E 00 74 52 65 67 75 6C 61 72 00 52 00 65 00 67 00 75 00 6C 00 61 00 72 43 75 73 74
6F 6D 20 47 6C 79 70 68 20 46 6F 6E 74 00 43 00 75 00 73 00 74 00 6F 00 6D 00 20 00 47 00 6C 00
79 00 70 00 68 00 20 00 46 00 6F 00 6E 00 74 56 65 72 73 69 6F 6E 20 31 2E 30 00 56 00 65 00 72
00 73 00 69 00 6F 00 6E 00 20 00 31 00 2E 00 30 00 00 00 01 00 03 00 01 00 00 00 0C 00 04 00 26
00 00 00 04 00 04 00 01 00 00 00 7E FF FF 00 00 00 7E FF FF FF 83 00 01 00 00 00 00 00 00 00 00
00 01 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 01 00 04 01 00 01 01 01 0B 63 75 73 74 6F 6D 66 6F 6E 74 00 01 01 01 23 F8 1B 00 F8
1C 02 F8 1D 03 F8 19 04 8C 0D 9F 77 F9 50 F9 3C 05 F7 05 0F F7 08 10 F7 0B 11 9B F7 37 12 00 04
01 01 0C 1D 28 2E 56 65 72 73 69 6F 6E 20 31 2E 30 43 75 73 74 6F 6D 20 47 6C 79 70 68 20 46 6F
6E 74 43 75 73 74 6F 6D 20 46 6F 6E 74 63 75 73 74 6F 6D 00 00 00 01 8A 00 01 01 00 02 01 01 02
27 0E 9F 77 15 8B F9 50 05 F9 3C 8B 05 8B FD 50 05 FD 3C 8B 05 F7 2A F7 2A 15 8B F8 24 05 F8 10
8B 05 8B FC 24 05 0E 8B 8B 06 8B 8B 08 95 0A 95 0B F9 50 14 F9 50 14 00 00 00 00 00 02 A8 00 00
Run Code Online (Sandbox Code Playgroud)

(custom fonts can be made very small =)

But, if actual files and/or TTX output are desirable, they can be found over at https://github.com/Pomax/CFF-glyphlet-fonts/tree/gh-pages/binaries/test, including the TTX xml (direct link for that: https://github.com/Pomax/CFF-glyphlet-fonts/blob/gh-pages/binaries/with%20GSUB/customfont.ttx), which in the interest of a self-contained question is:

<?xml version="1.0" encoding="utf-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="2.4">

  <GlyphOrder>
    <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
    <GlyphID id="0" name=".notdef"/>
    <GlyphID id="1" name="custom"/>
  </GlyphOrder>

  <head>
    <!-- Most of this table will be recalculated by the compiler -->
    <tableVersion value="1.0"/>
    <fontRevision value="1.0"/>
    <checkSumAdjustment value="0x1aeaff64"/>
    <magicNumber value="0x5f0f3cf5"/>
    <flags value="00000000 00000000"/>
    <unitsPerEm value="1024"/>
    <created value="Thu Jan 01 00:00:00 1970"/>
    <modified value="Thu Jan 01 00:00:00 1970"/>
    <xMin value="20"/>
    <yMin value="-20"/>
    <xMax value="700"/>
    <yMax value="680"/>
    <macStyle value="00000000 00000000"/>
    <lowestRecPPEM value="8"/>
    <fontDirectionHint value="2"/>
    <indexToLocFormat value="0"/>
    <glyphDataFormat value="0"/>
  </head>

  <hhea>
    <tableVersion value="1.0"/>
    <ascent value="1004"/>
    <descent value="-344"/>
    <lineGap value="0"/>
    <advanceWidthMax value="680"/>
    <minLeftSideBearing value="0"/>
    <minRightSideBearing value="0"/>
    <xMaxExtent value="680"/>
    <caretSlopeRise value="0"/>
    <caretSlopeRun value="0"/>
    <caretOffset value="0"/>
    <reserved0 value="0"/>
    <reserved1 value="0"/>
    <reserved2 value="0"/>
    <reserved3 value="0"/>
    <metricDataFormat value="0"/>
    <numberOfHMetrics value="2"/>
  </hhea>

  <maxp>
    <tableVersion value="0x5000"/>
    <numGlyphs value="2"/>
  </maxp>

  <OS_2>
    <version value="3"/>
    <xAvgCharWidth value="0"/>
    <usWeightClass value="400"/>
    <usWidthClass value="1"/>
    <fsType value="00000000 00000000"/>
    <ySubscriptXSize value="0"/>
    <ySubscriptYSize value="0"/>
    <ySubscriptXOffset value="0"/>
    <ySubscriptYOffset value="0"/>
    <ySuperscriptXSize value="0"/>
    <ySuperscriptYSize value="0"/>
    <ySuperscriptXOffset value="0"/>
    <ySuperscriptYOffset value="0"/>
    <yStrikeoutSize value="0"/>
    <yStrikeoutPosition value="0"/>
    <sFamilyClass value="0"/>
    <panose>
      <bFamilyType value="0"/>
      <bSerifStyle value="0"/>
      <bWeight value="0"/>
      <bProportion value="0"/>
      <bContrast value="0"/>
      <bStrokeVariation value="0"/>
      <bArmStyle value="0"/>
      <bLetterForm value="0"/>
      <bMidline value="0"/>
      <bXHeight value="0"/>
    </panose>
    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
    <achVendID value=" =) "/>
    <fsSelection value="00000000 01000000"/>
    <fsFirstCharIndex value="126"/>
    <fsLastCharIndex value="126"/>
    <sTypoAscender value="680"/>
    <sTypoDescender value="-20"/>
    <sTypoLineGap value="324"/>
    <usWinAscent value="1004"/>
    <usWinDescent value="344"/>
    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
    <sxHeight value="0"/>
    <sCapHeight value="0"/>
    <usDefaultChar value="0"/>
    <usBreakChar value="126"/>
    <usMaxContex value="0"/>
  </OS_2>

  <name>
    <namerecord nameID="1" platformID="1" platEncID="32" langID="0x0">
      Custom Font
    </namerecord>
    <namerecord nameID="2" platformID="1" platEncID="32" langID="0x0">
      Regular
    </namerecord>
    <namerecord nameID="4" platformID="1" platEncID="32" langID="0x0">
      Custom Glyph Font
    </namerecord>
    <namerecord nameID="5" platformID="1" platEncID="32" langID="0x0">
      Version 1.0
    </namerecord>
    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
      Custom Font
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
      Regular
    </namerecord>
    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
      Custom Glyph Font
    </namerecord>
    <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
      Version 1.0
    </namerecord>
  </name>

  <cmap>
    <tableVersion version="0"/>
    <cmap_format_4 platformID="3" platEncID="1" language="0">
      <map code="0x7e" name="custom"/><!-- TILDE -->
    </cmap_format_4>
  </cmap>

  <post>
    <formatType value="3.0"/>
    <italicAngle value="0.0"/>
    <underlinePosition value="0"/>
    <underlineThickness value="0"/>
    <isFixedPitch value="1"/>
    <minMemType42 value="0"/>
    <maxMemType42 value="0"/>
    <minMemType1 value="0"/>
    <maxMemType1 value="0"/>
  </post>

  <CFF>
    <CFFFont name="customfont">
      <version value="Version 1.0"/>
      <FullName value="Custom Glyph Font"/>
      <FamilyName value="Custom Font"/>
      <Weight value="Roman"/>
      <isFixedPitch value="0"/>
      <ItalicAngle value="0"/>
      <UnderlineThickness value="50"/>
      <PaintType value="0"/>
      <CharstringType value="2"/>
      <FontMatrix value="0.001 0 0 0.001 0 0"/>
      <UniqueID value="1"/>
      <FontBBox value="20 -20 700 680"/>
      <StrokeWidth value="0"/>
      <!-- charset is dumped separately as the 'GlyphOrder' element -->
      <Encoding>
        <map code="0x1" name="custom"/>
      </Encoding>
      <Private>
        <BlueValues value="0 0"/>
        <FamilyBlues value="0 0"/>
        <BlueScale value="0.039625"/>
        <BlueShift value="7"/>
        <BlueFuzz value="1"/>
        <StdHW value="10"/>
        <StdVW value="10"/>
        <ForceBold value="0"/>
        <LanguageGroup value="0"/>
        <ExpansionFactor value="0.06"/>
        <initialRandomSeed value="0"/>
        <defaultWidthX value="700"/>
        <nominalWidthX value="0"/>
      </Private>
      <CharStrings>
        <CharString name=".notdef">
          endchar
        </CharString>
        <CharString name="custom">
          20 -20 rmoveto
          0 700 rlineto
          680 0 rlineto
          0 -700 rlineto
          -680 0 rlineto
          150 150 rmoveto
          0 400 rlineto
          380 0 rlineto
          0 -400 rlineto
          endchar
        </CharString>
      </CharStrings>
    </CFFFont>

    <GlobalSubrs>
      <!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
    </GlobalSubrs>
  </CFF>

  <hmtx>
    <mtx name=".notdef" width="0" lsb="0"/>
    <mtx name="custom" width="680" lsb="0"/>
  </hmtx>

</ttFont>
Run Code Online (Sandbox Code Playgroud)

If there are any additional tools that can be used to determine whether or not a font is "done" enough to be installable, or if anyone knows of documentation that explains which criteria a font needs to meet before it can be installed, that information is extremely welcome. And of course, if someone happens to know what my font code is still missing (either as bytecode or as TTX XML), or they see odd/buggy bits, I am also keenly interested in your comments/answers.

Mik*_*ans 5

正如Typophile论坛上的某人指出的,事实证明,就Windows而言,“名称”表是不完整的。尽管Microsoft字体验证程序没有标记任何问题,但字体必须列出以下名称表条目才能安装:

1: the regular font name
2: the font subfamily ("Regular", etc)
3: any (seriously, ANY) string to act as a unique font identifier
6: the postscript font name (a subset of true ASCII. Not ANSI)
Run Code Online (Sandbox Code Playgroud)

我定义的字体使用的是NameIDs 1、2、4和5。尽管实际上“验证”需要4和5,但它们对于预览/安装完全不相关,而3和6是至关重要的。谁知道(认真地,谁知道...如果您知道,我想通过聊天或Twitter或与您交谈的方式与您交谈=)

(请注意,要在OSX上安装字体,仍然需要4和5)

2017年编辑:微软的Font Validator于2015年开源,由于MS(出于法律原因)无法合并到重要的社区贡献中,因此建立了一个社区维护的分支,并与社区中的更改保持同步https://github.com/HinTak/Font-Validator上的OpenType规范-如果Font Validator是工具集的一部分,则您绝对想开始使用此fork。

  • 公平地说:现在存在的MS验证器有点可怕。值得庆幸的是,它最近是开源的(是吗?!?!是的),并且已经有了一套即时PR,以使其可以在https://github.com/Microsoft/Font-Validator/pull上用于现代OpenType。 / 1 (2认同)
  • 还值得订阅OpenType邮件列表,这是一个很好的地方,询问“这里到底出了什么问题?” 在以工程师(而不是字体设计师)进行字体开发时。 (2认同)