Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    def build_CFF(self):
        ctx = self.ctx
        data = self.metadataProvider
        self.otf["CFF "] = cff = ttLib.newTable("CFF ")
        cff = cff.cff

        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

        cff.fontNames.append(data.name_postscriptFontName(ctx))
        topDict = cff.topDictIndex[0]
        topDict.version = data.version(ctx)
        topDict.Notice = conversion.to_postscript_string(
            data.name_trademark(ctx), lambda result: ctx.log.append(
                semlog.warning_attr_truncated(attr="trademark", result=result))
        )
        topDict.Copyright = conversion.to_postscript_string(
            data.copyright(ctx), lambda result: ctx.log.append(
                semlog.warning_attr_truncated(attr="copyright", result=result))
        )
        topDict.FullName = data.name_postscriptFullName(ctx)
        topDict.FamilyName = data.CFF_postscriptFamilyName(ctx)
        topDict.Weight = data.CFF_postscriptWeightName(ctx)

        topDict.isFixedPitch = data.post_isFixedPitch(ctx)
        topDict.ItalicAngle = data.italicAngle(ctx)
        topDict.UnderlinePosition = otRound(data.post_underlinePosition(ctx))
        topDict.UnderlineThickness = otRound(data.post_underlineThickness(ctx))

        scale = 1.0 / otRound(data.unitsPerEm(ctx))
        topDict.FontMatrix = [scale, 0, 0, scale, 0, 0]

        defaultWidthX, nominalWidthX = FontProc.postscript_width_stats(
            ctx, self.otf)
        if defaultWidthX:
            private.rawDict["defaultWidthX"] = defaultWidthX
        if nominalWidthX:
            private.rawDict["nominalWidthX"] = nominalWidthX

        blueFuzz = otRound(data.CFF_postscriptBlueFuzz(ctx))
        blueShift = otRound(data.CFF_postscriptBlueShift(ctx))
        blueScale = data.CFF_postscriptBlueScale(ctx)
        forceBold = data.CFF_postscriptForceBold(ctx)
        blueValues = otRoundSequence(data.CFF_postscriptBlueValues(ctx))
        otherBlues = otRoundSequence(data.CFF_postscriptOtherBlues(ctx))
        familyBlues = otRoundSequence(data.CFF_postscriptFamilyBlues(ctx))
        familyOtherBlues = otRoundSequence(
            data.CFF_postscriptFamilyOtherBlues(ctx))
        stemSnapH = otRoundSequence(data.CFF_postscriptStemSnapH(ctx))
        stemSnapV = otRoundSequence(data.CFF_postscriptStemSnapV(ctx))
        # 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.glyphMap[glyphName]
            charString = self.draw_charstring(glyph, private, globalSubrs)

            # add to the font
            charStringsIndex.append(charString)
            glyphID = len(topDict.charset)
            charStrings.charStrings[glyphName] = glyphID
            topDict.charset.append(glyphName)
        bounds = self.fontBounds
        topDict.FontBBox = (bounds.left, bounds.bottom, bounds.right,
                            bounds.top)
Ejemplo n.º 3
0
def lib_convertCFFToCFF2(cff, otFont):
    # This assumes a decompiled CFF table.
    cff2GetGlyphOrder = cff.otFont.getGlyphOrder
    topDictData = TopDictIndex(None, cff2GetGlyphOrder, None)
    topDictData.items = cff.topDictIndex.items
    cff.topDictIndex = topDictData
    topDict = topDictData[0]
    if hasattr(topDict, 'Private'):
        privateDict = topDict.Private
    else:
        privateDict = None
    opOrder = buildOrder(topDictOperators2)
    topDict.order = opOrder
    topDict.cff2GetGlyphOrder = cff2GetGlyphOrder
    if not hasattr(topDict, "FDArray"):
        fdArray = topDict.FDArray = FDArrayIndex()
        fdArray.strings = None
        fdArray.GlobalSubrs = topDict.GlobalSubrs
        topDict.GlobalSubrs.fdArray = fdArray
        charStrings = topDict.CharStrings
        if charStrings.charStringsAreIndexed:
            charStrings.charStringsIndex.fdArray = fdArray
        else:
            charStrings.fdArray = fdArray
        fontDict = FontDict()
        fontDict.setCFF2(True)
        fdArray.append(fontDict)
        fontDict.Private = privateDict
        privateOpOrder = buildOrder(privateDictOperators2)
        if privateDict is not None:
            for entry in privateDictOperators:
                key = entry[1]
                if key not in privateOpOrder:
                    if key in privateDict.rawDict:
                        # print "Removing private dict", key
                        del privateDict.rawDict[key]
                    if hasattr(privateDict, key):
                        delattr(privateDict, key)
                        # print "Removing privateDict attr", key
    else:
        # clean up the PrivateDicts in the fdArray
        fdArray = topDict.FDArray
        privateOpOrder = buildOrder(privateDictOperators2)
        for fontDict in fdArray:
            fontDict.setCFF2(True)
            for key in list(fontDict.rawDict.keys()):
                if key not in fontDict.order:
                    del fontDict.rawDict[key]
                    if hasattr(fontDict, key):
                        delattr(fontDict, key)

            privateDict = fontDict.Private
            for entry in privateDictOperators:
                key = entry[1]
                if key not in privateOpOrder:
                    if key in privateDict.rawDict:
                        # print "Removing private dict", key
                        del privateDict.rawDict[key]
                    if hasattr(privateDict, key):
                        delattr(privateDict, key)
                        # print "Removing privateDict attr", key
    # Now delete up the decrecated topDict operators from CFF 1.0
    for entry in topDictOperators:
        key = entry[1]
        if key not in opOrder:
            if key in topDict.rawDict:
                del topDict.rawDict[key]
            if hasattr(topDict, key):
                delattr(topDict, key)

    # At this point, the Subrs and Charstrings are all still T2Charstring class
    # easiest to fix this by compiling, then decompiling again
    cff.major = 2
    file = BytesIO()
    cff.compile(file, otFont, isCFF2=True)
    file.seek(0)
    cff.decompile(file, otFont, isCFF2=True)
Ejemplo n.º 4
0
def lib_convertCFFToCFF2(cff, otFont):
	# This assumes a decompiled CFF table.
	cff2GetGlyphOrder = cff.otFont.getGlyphOrder
	topDictData = TopDictIndex(None, cff2GetGlyphOrder, None)
	topDictData.items = cff.topDictIndex.items
	cff.topDictIndex = topDictData
	topDict = topDictData[0]
	if hasattr(topDict, 'Private'):
		privateDict = topDict.Private
	else:
		privateDict = None
	opOrder = buildOrder(topDictOperators2)
	topDict.order = opOrder
	topDict.cff2GetGlyphOrder = cff2GetGlyphOrder
	if not hasattr(topDict, "FDArray"):
		fdArray = topDict.FDArray = FDArrayIndex()
		fdArray.strings = None
		fdArray.GlobalSubrs = topDict.GlobalSubrs
		topDict.GlobalSubrs.fdArray = fdArray
		charStrings = topDict.CharStrings
		if charStrings.charStringsAreIndexed:
			charStrings.charStringsIndex.fdArray = fdArray
		else:
			charStrings.fdArray = fdArray
		fontDict = FontDict()
		fontDict.setCFF2(True)
		fdArray.append(fontDict)
		fontDict.Private = privateDict
		privateOpOrder = buildOrder(privateDictOperators2)
		for entry in privateDictOperators:
			key = entry[1]
			if key not in privateOpOrder:
				if key in privateDict.rawDict:
					# print "Removing private dict", key
					del privateDict.rawDict[key]
				if hasattr(privateDict, key):
					delattr(privateDict, key)
					# print "Removing privateDict attr", key
	else:
		# clean up the PrivateDicts in the fdArray
		fdArray = topDict.FDArray
		privateOpOrder = buildOrder(privateDictOperators2)
		for fontDict in fdArray:
			fontDict.setCFF2(True)
			for key in fontDict.rawDict.keys():
				if key not in fontDict.order:
					del fontDict.rawDict[key]
					if hasattr(fontDict, key):
						delattr(fontDict, key)

			privateDict = fontDict.Private
			for entry in privateDictOperators:
				key = entry[1]
				if key not in privateOpOrder:
					if key in privateDict.rawDict:
						# print "Removing private dict", key
						del privateDict.rawDict[key]
					if hasattr(privateDict, key):
						delattr(privateDict, key)
						# print "Removing privateDict attr", key
	# Now delete up the decrecated topDict operators from CFF 1.0
	for entry in topDictOperators:
		key = entry[1]
		if key not in opOrder:
			if key in topDict.rawDict:
				del topDict.rawDict[key]
			if hasattr(topDict, key):
				delattr(topDict, key)

	# At this point, the Subrs and Charstrings are all still T2Charstring class
	# easiest to fix this by compiling, then decompiling again
	cff.major = 2
	file = BytesIO()
	cff.compile(file, otFont, isCFF2=True)
	file.seek(0)
	cff.decompile(file, otFont, isCFF2=True)