def setupTable_CFF(self): """Make the CFF table.""" 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: self.log.append( "[Warning] 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: self.log.append( "[Warning] 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") topDict.FontName = psName # populate various numbers topDict.isFixedPitch = getAttrWithFallback(info, "postscriptIsFixedPitch") topDict.ItalicAngle = getAttrWithFallback(info, "italicAngle") underlinePosition = getAttrWithFallback(info, "postscriptUnderlinePosition") topDict.UnderlinePosition = _roundInt(underlinePosition) underlineThickness = getAttrWithFallback( info, "postscriptUnderlineThickness") topDict.UnderlineThickness = _roundInt(underlineThickness) # populate font matrix unitsPerEm = _roundInt(getAttrWithFallback(info, "unitsPerEm")) topDict.FontMatrix = [1.0 / unitsPerEm, 0, 0, 1.0 / unitsPerEm, 0, 0] # populate the width values defaultWidthX = _roundInt( getAttrWithFallback(info, "postscriptDefaultWidthX")) if defaultWidthX: private.rawDict["defaultWidthX"] = defaultWidthX nominalWidthX = _roundInt( getAttrWithFallback(info, "postscriptNominalWidthX")) if nominalWidthX: private.rawDict["nominalWidthX"] = nominalWidthX # populate hint data blueFuzz = _roundInt(getAttrWithFallback(info, "postscriptBlueFuzz")) blueShift = _roundInt(getAttrWithFallback(info, "postscriptBlueShift")) blueScale = getAttrWithFallback(info, "postscriptBlueScale") forceBold = getAttrWithFallback(info, "postscriptForceBold") blueValues = getAttrWithFallback(info, "postscriptBlueValues") if isinstance(blueValues, list): blueValues = [_roundInt(i) for i in blueValues] otherBlues = getAttrWithFallback(info, "postscriptOtherBlues") if isinstance(otherBlues, list): otherBlues = [_roundInt(i) for i in otherBlues] familyBlues = getAttrWithFallback(info, "postscriptFamilyBlues") if isinstance(familyBlues, list): familyBlues = [_roundInt(i) for i in familyBlues] familyOtherBlues = getAttrWithFallback(info, "postscriptFamilyOtherBlues") if isinstance(familyOtherBlues, list): familyOtherBlues = [_roundInt(i) for i in familyOtherBlues] stemSnapH = getAttrWithFallback(info, "postscriptStemSnapH") if isinstance(stemSnapH, list): stemSnapH = [_roundInt(i) for i in stemSnapH] stemSnapV = getAttrWithFallback(info, "postscriptStemSnapV") if isinstance(stemSnapV, list): stemSnapV = [_roundInt(i) for i in stemSnapV] # only write the blues data if some blues are defined. if (blueValues or otherBlues): private.rawDict["BlueFuzz"] = blueFuzz private.rawDict["BlueShift"] = blueShift private.rawDict["BlueScale"] = blueScale private.rawDict["ForceBold"] = forceBold private.rawDict["BlueValues"] = blueValues private.rawDict["OtherBlues"] = otherBlues private.rawDict["FamilyBlues"] = familyBlues 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] unicodes = glyph.unicodes 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 # write the glyph order self.otf.setGlyphOrder(self.glyphOrder)
def test_no_change(self): self.assertEqual( normalizeStringForPostscript('Sample copyright notice.'), "Sample copyright notice.")
def setupTable_CFF(self): """Make the CFF table.""" 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: self.log.append("[Warning] 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: self.log.append("[Warning] 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") topDict.FontName = getAttrWithFallback(info, "postscriptFontName") # populate various numbers topDict.isFixedPitch = getAttrWithFallback(info, "postscriptIsFixedPitch") topDict.ItalicAngle = getAttrWithFallback(info, "italicAngle") underlinePosition = getAttrWithFallback(info, "postscriptUnderlinePosition") if underlinePosition is None: underlinePosition = 0 topDict.UnderlinePosition = _roundInt(underlinePosition) underlineThickness = getAttrWithFallback(info, "postscriptUnderlineThickness") if underlineThickness is None: underlineThickness = 0 topDict.UnderlineThickness = _roundInt(underlineThickness) # populate font matrix unitsPerEm = _roundInt(getAttrWithFallback(info, "unitsPerEm")) topDict.FontMatrix = [1.0 / unitsPerEm, 0, 0, 1.0 / unitsPerEm, 0, 0] # populate the width values defaultWidthX = _roundInt(getAttrWithFallback(info, "postscriptDefaultWidthX")) if defaultWidthX: private.rawDict["defaultWidthX"] = defaultWidthX nominalWidthX = _roundInt(getAttrWithFallback(info, "postscriptNominalWidthX")) if nominalWidthX: private.rawDict["nominalWidthX"] = nominalWidthX # populate hint data blueFuzz = _roundInt(getAttrWithFallback(info, "postscriptBlueFuzz")) blueShift = _roundInt(getAttrWithFallback(info, "postscriptBlueShift")) blueScale = getAttrWithFallback(info, "postscriptBlueScale") forceBold = getAttrWithFallback(info, "postscriptForceBold") blueValues = getAttrWithFallback(info, "postscriptBlueValues") if isinstance(blueValues, list): blueValues = [_roundInt(i) for i in blueValues] otherBlues = getAttrWithFallback(info, "postscriptOtherBlues") if isinstance(otherBlues, list): otherBlues = [_roundInt(i) for i in otherBlues] familyBlues = getAttrWithFallback(info, "postscriptFamilyBlues") if isinstance(familyBlues, list): familyBlues = [_roundInt(i) for i in familyBlues] familyOtherBlues = getAttrWithFallback(info, "postscriptFamilyOtherBlues") if isinstance(familyOtherBlues, list): familyOtherBlues = [_roundInt(i) for i in familyOtherBlues] stemSnapH = getAttrWithFallback(info, "postscriptStemSnapH") if isinstance(stemSnapH, list): stemSnapH = [_roundInt(i) for i in stemSnapH] stemSnapV = getAttrWithFallback(info, "postscriptStemSnapV") if isinstance(stemSnapV, list): stemSnapV = [_roundInt(i) for i in stemSnapV] # only write the blues data if some blues are defined. if (blueValues or otherBlues): private.rawDict["BlueFuzz"] = blueFuzz private.rawDict["BlueShift"] = blueShift private.rawDict["BlueScale"] = blueScale private.rawDict["ForceBold"] = forceBold private.rawDict["BlueValues"] = blueValues private.rawDict["OtherBlues"] = otherBlues private.rawDict["FamilyBlues"] = familyBlues 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] unicodes = glyph.unicodes 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 # write the glyph order self.otf.setGlyphOrder(self.glyphOrder)
def setupTable_name(self): """ Make the name table. **This should not be called externally.** Subclasses may override or supplement this method to handle the table creation in a different way if desired. """ font = self.ufo familyName = getAttrWithFallback(font.info, "styleMapFamilyName") styleName = getAttrWithFallback(font.info, "styleMapStyleName").title() # If name ID 2 is "Regular", it can be omitted from name ID 4 fullName = familyName if styleName != "Regular": fullName += " %s" % styleName nameVals = { "0": getAttrWithFallback(font.info, "copyright"), "1": familyName, "2": styleName, "3": getAttrWithFallback(font.info, "openTypeNameUniqueID"), "4": fullName, "5": getAttrWithFallback(font.info, "openTypeNameVersion"), "6": getAttrWithFallback(font.info, "postscriptFontName"), "7": getAttrWithFallback(font.info, "trademark"), "8": getAttrWithFallback(font.info, "openTypeNameManufacturer"), "9": getAttrWithFallback(font.info, "openTypeNameDesigner"), "10": getAttrWithFallback(font.info, "openTypeNameDescription"), "11": getAttrWithFallback(font.info, "openTypeNameManufacturerURL"), "12": getAttrWithFallback(font.info, "openTypeNameDesignerURL"), "13": getAttrWithFallback(font.info, "openTypeNameLicense"), "14": getAttrWithFallback(font.info, "openTypeNameLicenseURL") } # don't add typographic names if they are the same as the legacy ones typographicFamilyName = getAttrWithFallback( font.info, "openTypeNamePreferredFamilyName") typographicSubfamilyName = getAttrWithFallback( font.info, "openTypeNamePreferredSubfamilyName") if nameVals["1"] != typographicFamilyName: nameVals["16"] = typographicFamilyName if nameVals["2"] != typographicSubfamilyName: nameVals["17"] = typographicSubfamilyName self.otf["name"] = name = newTable("name") name.names = [] for nameId in sorted(nameVals.keys()): nameVal = nameVals[nameId] if not nameVal: continue nameIdVal = int(nameId) if nameIdVal == 6: # postscript font name nameVal = normalizeStringForPostscript(nameVal) rec = NameRecord() rec.platformID = 3 rec.platEncID = 10 if _isNonBMP(nameVal) else 1 rec.langID = 0x409 rec.nameID = nameIdVal rec.string = nameVal.encode(rec.getEncoding()) name.names.append(rec)
def setupTable_name(self): """ Make the name table. **This should not be called externally.** Subclasses may override or supplement this method to handle the table creation in a different way if desired. """ font = self.ufo familyName = getAttrWithFallback(font.info, "styleMapFamilyName") styleName = getAttrWithFallback(font.info, "styleMapStyleName").title() # If name ID 2 is "Regular", it can be omitted from name ID 4 fullName = familyName if styleName != "Regular": fullName += " %s" % styleName nameVals = { "0": getAttrWithFallback(font.info, "copyright"), "1": familyName, "2": styleName, "3": getAttrWithFallback(font.info, "openTypeNameUniqueID"), "4": fullName, "5": getAttrWithFallback(font.info, "openTypeNameVersion"), "6": getAttrWithFallback(font.info, "postscriptFontName"), "7": getAttrWithFallback(font.info, "trademark"), "8": getAttrWithFallback(font.info, "openTypeNameManufacturer"), "9": getAttrWithFallback(font.info, "openTypeNameDesigner"), "11": getAttrWithFallback(font.info, "openTypeNameManufacturerURL"), "12": getAttrWithFallback(font.info, "openTypeNameDesignerURL"), "13": getAttrWithFallback(font.info, "openTypeNameLicense"), "14": getAttrWithFallback(font.info, "openTypeNameLicenseURL")} # don't add typographic names if they are the same as the legacy ones typographicFamilyName = getAttrWithFallback(font.info, "openTypeNamePreferredFamilyName") typographicSubfamilyName = getAttrWithFallback(font.info, "openTypeNamePreferredSubfamilyName") if nameVals["1"] != typographicFamilyName: nameVals["16"] = typographicFamilyName if nameVals["2"] != typographicSubfamilyName: nameVals["17"] = typographicSubfamilyName self.otf["name"] = name = newTable("name") name.names = [] for nameId in sorted(nameVals.keys()): nameVal = nameVals[nameId] if not nameVal: continue nameIdVal = int(nameId) if nameIdVal == 6: # postscript font name nameVal = normalizeStringForPostscript(nameVal) rec = NameRecord() rec.platformID = 3 rec.platEncID = 10 if _isNonBMP(nameVal) else 1 rec.langID = 0x409 rec.nameID = nameIdVal rec.string = nameVal.encode(rec.getEncoding()) name.names.append(rec)
def test_no_change(self): assert ( normalizeStringForPostscript("Sample copyright notice.") == "Sample copyright notice." )
def setupTable_name(self): """ Make the name table. **This should not be called externally.** Subclasses may override or supplement this method to handle the table creation in a different way if desired. """ font = self.ufo self.otf["name"] = name = newTable("name") name.names = [] # Set name records from font.info.openTypeNameRecords for nameRecord in getAttrWithFallback(font.info, "openTypeNameRecords"): nameId = nameRecord["nameID"] platformId = nameRecord["platformID"] platEncId = nameRecord["encodingID"] langId = nameRecord["languageID"] # on Python 2, plistLib (used by ufoLib) returns unicode strings # only when plist data contain non-ascii characters, and returns # ascii-encoded bytes when it can. On the other hand, fontTools's # name table `setName` method wants unicode strings, so we must # decode them first nameVal = tounicode(nameRecord["string"], encoding='ascii') name.setName(nameVal, nameId, platformId, platEncId, langId) # Build name records familyName = getAttrWithFallback(font.info, "styleMapFamilyName") styleName = getAttrWithFallback(font.info, "styleMapStyleName").title() # If name ID 2 is "Regular", it can be omitted from name ID 4 fullName = familyName if styleName != "Regular": fullName += " %s" % styleName nameVals = { 0: getAttrWithFallback(font.info, "copyright"), 1: familyName, 2: styleName, 3: getAttrWithFallback(font.info, "openTypeNameUniqueID"), 4: fullName, 5: getAttrWithFallback(font.info, "openTypeNameVersion"), 6: getAttrWithFallback(font.info, "postscriptFontName"), 7: getAttrWithFallback(font.info, "trademark"), 8: getAttrWithFallback(font.info, "openTypeNameManufacturer"), 9: getAttrWithFallback(font.info, "openTypeNameDesigner"), 10: getAttrWithFallback(font.info, "openTypeNameDescription"), 11: getAttrWithFallback(font.info, "openTypeNameManufacturerURL"), 12: getAttrWithFallback(font.info, "openTypeNameDesignerURL"), 13: getAttrWithFallback(font.info, "openTypeNameLicense"), 14: getAttrWithFallback(font.info, "openTypeNameLicenseURL"), 16: getAttrWithFallback(font.info, "openTypeNamePreferredFamilyName"), 17: getAttrWithFallback(font.info, "openTypeNamePreferredSubfamilyName"), } # don't add typographic names if they are the same as the legacy ones if nameVals[1] == nameVals[16]: del nameVals[16] if nameVals[2] == nameVals[17]: del nameVals[17] # postscript font name if nameVals[6]: nameVals[6] = normalizeStringForPostscript(nameVals[6]) platformIds = [1, 3] for platformId in platformIds: if platformId == 1: langId = 0x0 platEncId = 0 elif platformId == 3: langId = 0x409 platEncId = 10 if _isNonBMP(nameVal) else 1 for nameId in sorted(nameVals.keys()): nameVal = nameVals[nameId] if not nameVal: continue nameVal = tounicode(nameVal, encoding='ascii') # Set built name record if not set yet if name.getName(nameId, platformId, platEncId, langId): continue name.setName(nameVal, nameId, platformId, platEncId, langId)
def setupTable_name(self): """ Make the name table. **This should not be called externally.** Subclasses may override or supplement this method to handle the table creation in a different way if desired. """ font = self.ufo self.otf["name"] = name = newTable("name") name.names = [] # Set name records from font.info.openTypeNameRecords for nameRecord in getAttrWithFallback( font.info, "openTypeNameRecords"): nameId = nameRecord["nameID"] platformId = nameRecord["platformID"] platEncId = nameRecord["encodingID"] langId = nameRecord["languageID"] # on Python 2, plistLib (used by ufoLib) returns unicode strings # only when plist data contain non-ascii characters, and returns # ascii-encoded bytes when it can. On the other hand, fontTools's # name table `setName` method wants unicode strings, so we must # decode them first nameVal = tounicode(nameRecord["string"], encoding='ascii') name.setName(nameVal, nameId, platformId, platEncId, langId) # Build name records familyName = getAttrWithFallback(font.info, "styleMapFamilyName") styleName = getAttrWithFallback(font.info, "styleMapStyleName").title() # If name ID 2 is "Regular", it can be omitted from name ID 4 fullName = familyName if styleName != "Regular": fullName += " %s" % styleName nameVals = { 0: getAttrWithFallback(font.info, "copyright"), 1: familyName, 2: styleName, 3: getAttrWithFallback(font.info, "openTypeNameUniqueID"), 4: fullName, 5: getAttrWithFallback(font.info, "openTypeNameVersion"), 6: getAttrWithFallback(font.info, "postscriptFontName"), 7: getAttrWithFallback(font.info, "trademark"), 8: getAttrWithFallback(font.info, "openTypeNameManufacturer"), 9: getAttrWithFallback(font.info, "openTypeNameDesigner"), 10: getAttrWithFallback(font.info, "openTypeNameDescription"), 11: getAttrWithFallback(font.info, "openTypeNameManufacturerURL"), 12: getAttrWithFallback(font.info, "openTypeNameDesignerURL"), 13: getAttrWithFallback(font.info, "openTypeNameLicense"), 14: getAttrWithFallback(font.info, "openTypeNameLicenseURL"), 16: getAttrWithFallback( font.info, "openTypeNamePreferredFamilyName"), 17: getAttrWithFallback( font.info, "openTypeNamePreferredSubfamilyName"), } # don't add typographic names if they are the same as the legacy ones if nameVals[1] == nameVals[16]: del nameVals[16] if nameVals[2] == nameVals[17]: del nameVals[17] # postscript font name if nameVals[6]: nameVals[6] = normalizeStringForPostscript(nameVals[6]) for nameId in sorted(nameVals.keys()): nameVal = nameVals[nameId] if not nameVal: continue nameVal = tounicode(nameVal, encoding='ascii') platformId = 3 platEncId = 10 if _isNonBMP(nameVal) else 1 langId = 0x409 # Set built name record if not set yet if name.getName(nameId, platformId, platEncId, langId): continue name.setName(nameVal, nameId, platformId, platEncId, langId)
def test_no_change(self): self.assertEqual( normalizeStringForPostscript('Sample copyright notice.'), "Sample copyright notice.")