def setupTable_CFF(self):
        """Make the CFF table."""
        if not {"CFF", "CFF "}.intersection(self.tables):
            return

        self.otf["CFF "] = cff = newTable("CFF ")
        cff = cff.cff
        # set up the basics
        cff.major = 1
        cff.minor = 0
        cff.hdrSize = 4
        cff.offSize = 4
        cff.fontNames = []
        strings = IndexedStrings()
        cff.strings = strings
        private = PrivateDict(strings=strings)
        private.rawDict.update(private.defaults)
        globalSubrs = GlobalSubrsIndex(private=private)
        topDict = TopDict(GlobalSubrs=globalSubrs, strings=strings)
        topDict.Private = private
        charStrings = topDict.CharStrings = CharStrings(file=None, charset=None,
            globalSubrs=globalSubrs, private=private, fdSelect=None, fdArray=None)
        charStrings.charStringsAreIndexed = True
        topDict.charset = []
        charStringsIndex = charStrings.charStringsIndex = SubrsIndex(private=private, globalSubrs=globalSubrs)
        cff.topDictIndex = topDictIndex = TopDictIndex()
        topDictIndex.append(topDict)
        topDictIndex.strings = strings
        cff.GlobalSubrs = globalSubrs
        # populate naming data
        info = self.ufo.info
        psName = getAttrWithFallback(info, "postscriptFontName")
        cff.fontNames.append(psName)
        topDict = cff.topDictIndex[0]
        topDict.version = "%d.%d" % (getAttrWithFallback(info, "versionMajor"), getAttrWithFallback(info, "versionMinor"))
        trademark = getAttrWithFallback(info, "trademark")
        if trademark:
            trademark = normalizeStringForPostscript(trademark.replace("\u00A9", "Copyright"))
        if trademark != self.ufo.info.trademark:
            logger.info("The trademark was normalized for storage in the "
                        "CFF table and consequently some characters were "
                        "dropped: '%s'", trademark)
        if trademark is None:
            trademark = ""
        topDict.Notice = trademark
        copyright = getAttrWithFallback(info, "copyright")
        if copyright:
            copyright = normalizeStringForPostscript(copyright.replace("\u00A9", "Copyright"))
        if copyright != self.ufo.info.copyright:
            logger.info("The copyright was normalized for storage in the "
                        "CFF table and consequently some characters were "
                        "dropped: '%s'", copyright)
        if copyright is None:
            copyright = ""
        topDict.Copyright = copyright
        topDict.FullName = getAttrWithFallback(info, "postscriptFullName")
        topDict.FamilyName = getAttrWithFallback(info, "openTypeNamePreferredFamilyName")
        topDict.Weight = getAttrWithFallback(info, "postscriptWeightName")
        # populate various numbers
        topDict.isFixedPitch = getAttrWithFallback(info, "postscriptIsFixedPitch")
        topDict.ItalicAngle = getAttrWithFallback(info, "italicAngle")
        underlinePosition = getAttrWithFallback(info, "postscriptUnderlinePosition")
        topDict.UnderlinePosition = otRound(underlinePosition)
        underlineThickness = getAttrWithFallback(info, "postscriptUnderlineThickness")
        topDict.UnderlineThickness = otRound(underlineThickness)
        # populate font matrix
        unitsPerEm = otRound(getAttrWithFallback(info, "unitsPerEm"))
        topDict.FontMatrix = [1.0 / unitsPerEm, 0, 0, 1.0 / unitsPerEm, 0, 0]
        # populate the width values
        if (not any(hasattr(info, attr) and getattr(info, attr) is not None
                    for attr in ("postscriptDefaultWidthX",
                                 "postscriptNominalWidthX"))
                and "hmtx" in self.otf):
            # no custom values set in fontinfo.plist; compute optimal ones
            from fontTools.cffLib.width import optimizeWidths
            hmtx = self.otf['hmtx']
            widths = [m[0] for m in hmtx.metrics.values()]
            defaultWidthX, nominalWidthX = optimizeWidths(widths)
        else:
            defaultWidthX = otRound(getAttrWithFallback(info, "postscriptDefaultWidthX"))
            nominalWidthX = otRound(getAttrWithFallback(info, "postscriptNominalWidthX"))
        if defaultWidthX:
            private.rawDict["defaultWidthX"] = defaultWidthX
        if nominalWidthX:
            private.rawDict["nominalWidthX"] = nominalWidthX
        # populate hint data
        blueFuzz = otRound(getAttrWithFallback(info, "postscriptBlueFuzz"))
        blueShift = otRound(getAttrWithFallback(info, "postscriptBlueShift"))
        blueScale = getAttrWithFallback(info, "postscriptBlueScale")
        forceBold = getAttrWithFallback(info, "postscriptForceBold")
        blueValues = getAttrWithFallback(info, "postscriptBlueValues")
        if isinstance(blueValues, list):
            blueValues = [otRound(i) for i in blueValues]
        otherBlues = getAttrWithFallback(info, "postscriptOtherBlues")
        if isinstance(otherBlues, list):
            otherBlues = [otRound(i) for i in otherBlues]
        familyBlues = getAttrWithFallback(info, "postscriptFamilyBlues")
        if isinstance(familyBlues, list):
            familyBlues = [otRound(i) for i in familyBlues]
        familyOtherBlues = getAttrWithFallback(info, "postscriptFamilyOtherBlues")
        if isinstance(familyOtherBlues, list):
            familyOtherBlues = [otRound(i) for i in familyOtherBlues]
        stemSnapH = getAttrWithFallback(info, "postscriptStemSnapH")
        if isinstance(stemSnapH, list):
            stemSnapH = [otRound(i) for i in stemSnapH]
        stemSnapV = getAttrWithFallback(info, "postscriptStemSnapV")
        if isinstance(stemSnapV, list):
            stemSnapV = [otRound(i) for i in stemSnapV]
        # only write the blues data if some blues are defined.
        if any((blueValues, otherBlues, familyBlues, familyOtherBlues)):
            private.rawDict["BlueFuzz"] = blueFuzz
            private.rawDict["BlueShift"] = blueShift
            private.rawDict["BlueScale"] = blueScale
            private.rawDict["ForceBold"] = forceBold
            if blueValues:
                private.rawDict["BlueValues"] = blueValues
            if otherBlues:
                private.rawDict["OtherBlues"] = otherBlues
            if familyBlues:
                private.rawDict["FamilyBlues"] = familyBlues
            if familyOtherBlues:
                private.rawDict["FamilyOtherBlues"] = familyOtherBlues
        # only write the stems if both are defined.
        if (stemSnapH and stemSnapV):
            private.rawDict["StemSnapH"] = stemSnapH
            private.rawDict["StdHW"] = stemSnapH[0]
            private.rawDict["StemSnapV"] = stemSnapV
            private.rawDict["StdVW"] = stemSnapV[0]
        # populate glyphs
        for glyphName in self.glyphOrder:
            glyph = self.allGlyphs[glyphName]
            charString = self.getCharStringForGlyph(glyph, private, globalSubrs)
            # add to the font
            if glyphName in charStrings:
                # XXX a glyph already has this name. should we choke?
                glyphID = charStrings.charStrings[glyphName]
                charStringsIndex.items[glyphID] = charString
            else:
                charStringsIndex.append(charString)
                glyphID = len(topDict.charset)
                charStrings.charStrings[glyphName] = glyphID
                topDict.charset.append(glyphName)
        topDict.FontBBox = self.fontBoundingBox
Make the CFF table.