예제 #1
0
파일: ProofPDF.py 프로젝트: zedmar/afdko
def CheckEnvironment():
    txPath = 'tx'
    txError = 0

    try:
        exe_dir, fdkSharedDataDir = FDKUtils.findFDKDirs()
    except FDKUtils.FDKEnvError:
        logMsg(
            "Please re-install the FDK. Cannot find the FDK/Tools/SharedData directory."
        )
        raise FDKEnvironmentError

    command = "%s -u 2>&1" % (txPath)
    report = FDKUtils.runShellCmd(command)
    if "options" not in report:
        txError = 1

    if txError:
        logMsg(
            "Please re-install the FDK. The executable directory \"%s\" is missing the tool: < %s >."
            % (exe_dir, txPath))
        logMsg("or the files referenced by the shell script is missing.")
        raise FDKEnvironmentError

    return txPath, fdkSharedDataDir
예제 #2
0
def mergeFontToCFF(srcPath, outputPath, doSubr):
    # We assume that srcPath is a type 1 font,and outputPath is an OTF font.

    # First, convert src font to cff, and subroutinize it if so requested.
    tempPath = srcPath + ".temp.cff"
    subrArg = ""
    if doSubr:
        subrArg = " +S"
    command = "tx -cff +b%s \"%s\" \"%s\" 2>&1" % (subrArg, srcPath, tempPath)
    report = FDKUtils.runShellCmd(command)
    if ("fatal" in report) or ("error" in report):
        print report
        raise FontInfoParseError("Failed to convert font '%s' to CFF." %
                                 (fontPath))

    # Now merge it into the output file.
    command = "sfntedit -a CFF=\"%s\" \"%s\" 2>&1" % (tempPath, outputPath)
    report = FDKUtils.runShellCmd(command)
    if not debug:
        if os.path.exists(tempPath):
            os.remove(tempPath)
    if ("fatal" in report) or ("error" in report):
        print report
        raise FontInfoParseError("Failed to convert font '%s' to CFF." %
                                 (fontPath))
예제 #3
0
def CheckEnvironment():
    if curSystem == "Windows":
        tx_path = subprocess.check_output(["where", "tx.exe"]).strip()
    else:
        tx_path = subprocess.check_output(["which", "tx"]).strip()
    txError = 0

    try:
        exe_dir, _ = FDKUtils.findFDKDirs()
    except FDKUtils.FDKEnvError:
        logMsg("Please re-install the afdko. Cannot find the "
               "afdko/Tools/SharedData directory.")
        raise FDKEnvironmentError

    command = "%s -u 2>&1" % tx_path
    report = FDKUtils.runShellCmd(command)
    if "options" not in report:
        txError = 1

    if txError:
        logMsg("Please re-install the afdko. The executable directory \"%s\" "
               "is missing the tool: < %s >." % (exe_dir, tx_path))
        logMsg("or the files referenced by the shell script is missing.")
        raise FDKEnvironmentError

    return tx_path
예제 #4
0
def mergeFonts(inputFontPath, outputPath, fontList, glyphList, fontDictList, fdGlyphDict):
	cidfontinfoPath = "%s.temp.cidfontinfo" % (inputFontPath)
	makeCIDFontInfo(inputFontPath, cidfontinfoPath)
	lastFont =""
	tempfileList = []
	i = 0
	print "Merging temp fonts:", 
	for fontPath in fontList:
		print ".",
		sys.stdout.flush()
		gaPath = fontPath + ".ga"
		dstPath = "%s.temp.merge.%s" % (inputFontPath, i)
		removeNotdef = i != 0
		makeGAFile(gaPath, fontPath, glyphList, fontDictList, fdGlyphDict, removeNotdef)
		command = "mergeFonts -std -cid \"%s\" \"%s\" %s %s  %s 2>&1"  % (cidfontinfoPath, dstPath, lastFont, gaPath, fontPath)
		log = FDKUtils.runShellCmd(command)
		if debug:
			print command
			print log
		if "rror" in log:
			msg = "Error merging font %s. Log: %s." % (fontPath, log)
			raise FontInfoParseError(msg)
		i += 1
		lastFont = dstPath
		tempfileList.append(gaPath)
		tempfileList.append(dstPath)
		
	print ""		
	os.rename(dstPath, outputPath)
	if not debug:
		for path in tempfileList:
			if os.path.exists(path):
				os.remove(path)
		os.remove(cidfontinfoPath)
	return
예제 #5
0
def mergeFonts(inputFontPath, outputPath, fontList, glyphList, fontDictList, fdGlyphDict):
	cidfontinfoPath = "%s.temp.cidfontinfo" % (inputFontPath)
	makeCIDFontInfo(inputFontPath, cidfontinfoPath)
	lastFont =""
	tempfileList = []
	i = 0
	print "Merging temp fonts:", 
	for fontPath in fontList:
		print ".",
		sys.stdout.flush()
		gaPath = fontPath + ".ga"
		dstPath = "%s.temp.merge.%s" % (inputFontPath, i)
		removeNotdef = i != 0
		makeGAFile(gaPath, fontPath, glyphList, fontDictList, fdGlyphDict, removeNotdef)
		command = "mergeFonts -std -cid \"%s\" \"%s\" %s %s  %s 2>&1"  % (cidfontinfoPath, dstPath, lastFont, gaPath, fontPath)
		log = FDKUtils.runShellCmd(command)
		if debug:
			print command
			print log
		if "rror" in log:
			msg = "Error merging font %s. Log: %s." % (fontPath, log)
			raise FontInfoParseError(msg)
		i += 1
		lastFont = dstPath
		tempfileList.append(gaPath)
		tempfileList.append(dstPath)
		
	print ""		
	os.rename(dstPath, outputPath)
	if not debug:
		for path in tempfileList:
			if os.path.exists(path):
				os.remove(path)
		os.remove(cidfontinfoPath)
	return
예제 #6
0
def makeTempFonts(fontDictList, glyphSetList, fdGlyphDict, inputPath):
    fontList = []
    setIndex = 0
    for glyphList in glyphSetList:
        if not glyphList:
            continue
        setIndex += 1
        arg = ",".join(glyphList)
        tempPath = "%s.temp.%s.pfa" % (inputPath, setIndex)
        command = "tx -t1 -g \"%s\" \"%s\" \"%s\" 2>&1" % (arg, inputPath,
                                                           tempPath)
        log = FDKUtils.runShellCmd(command)
        if log:
            print "Have log output in subsetting command for %s to %s with %s glyphs." % (
                inputPath, tempPath, len(glyphList))
            print log
        fdIndex = fdGlyphDict[glyphList[0]][0]

        fdDict = fontDictList[fdIndex]
        fixFontDict(tempPath, fdDict)
        fontList.append(tempPath)
        if debug:
            print glyphList[0], len(glyphList), fdGlyphDict[
                glyphList[0]], tempPath
    return fontList
예제 #7
0
def makeTempFonts(fontDictList, glyphSetList, fdGlyphDict, inputPath):
    fontList = []
    setIndex = 0
    for glyphList in glyphSetList:
        if not glyphList:
            continue
        setIndex += 1
        arg = ",".join(glyphList)
        tempPath = "%s.temp.%s.pfa" % (inputPath, setIndex)
        command = 'tx -t1 -g "%s" "%s" "%s" 2>&1' % (arg, inputPath, tempPath)
        log = FDKUtils.runShellCmd(command)
        if log:
            print "Have log output in subsetting command for %s to %s with %s glyphs." % (
                inputPath,
                tempPath,
                len(glyphList),
            )
            print log
        fdIndex = fdGlyphDict[glyphList[0]][0]

        fdDict = fontDictList[fdIndex]
        fixFontDict(tempPath, fdDict)
        fontList.append(tempPath)
        if debug:
            print glyphList[0], len(glyphList), fdGlyphDict[glyphList[0]], tempPath
    return fontList
예제 #8
0
파일: autohint.py 프로젝트: henrich/afdko
def CheckEnvironment():
	txPath = 'tx'
	txError = 0
	command = "%s -u 2>&1" % (txPath)
	report = FDKUtils.runShellCmd(command)
	if "options" not in report:
			txError = 1
	
	if  txError:
		logMsg("Please re-install the FDK. The path to the program 'tx' is not in the environment variable PATH.")
		raise FDKEnvironmentError

	command = "autohintexe -u 2>&1"
	report = FDKUtils.runShellCmd(command)
	if "version" not in report:
		logMsg("Please re-install the FDK. The path to the program 'autohintexe' is not in the environment variable PATH.")
		raise FDKEnvironmentError
	
	return
예제 #9
0
def CheckEnvironment():
	txPath = 'tx'
	txError = 0
	command = "%s -u 2>&1" % (txPath)
	report = FDKUtils.runShellCmd(command)
	if "options" not in report:
			txError = 1
	
	if  txError:
		logMsg("Please re-install the FDK. The path to the program 'tx' is not in the environment variable PATH.")
		raise FDKEnvironmentError

	command = "checkoutlinesexe -u 2>&1"
	report = FDKUtils.runShellCmd(command)
	if "version" not in report:
		logMsg("Please re-install the FDK. The path to the program 'checkoutlinesexe' is not in the environment variable PATH.")
		raise FDKEnvironmentError

	return
예제 #10
0
def getFontName(fPath):
	command = "tx -dump -0 %s 2>&1" % (fPath)
	data = FDKUtils.runShellCmd(command)
	if not data:
		raise FontInfoParseError("Error: Failed getting  log from tx from %, when tryin to get FontName." % (fPath))
		
	m = re.search(r"FontName\s+\"([^\"]+)", data) 
	if not m:
		print data
		raise FontInfoParseError("Error: Failed finding FontName in tx log from  %s." % (fPath))
	return m.group(1)
예제 #11
0
def getBlueFuzz(fPath):
	blueFuzz = 1.0
	command = "tx -dump -0 %s 2>&1" % (fPath)
	data = FDKUtils.runShellCmd(command)
	if not data:
		raise FontInfoParseError("Error: Failed getting  log from tx from %, when trying to get FontName." % (fPath))
		
	m = re.search(r"BlueFuzz\s+(\d+(?:\.\d+)*)", data) 
	if m:
		blueFuzz = int(m.group(1))
	return blueFuzz
예제 #12
0
def getBlueFuzz(fPath):
	blueFuzz = 1.0
	command = "tx -dump -0 %s 2>&1" % (fPath)
	data = FDKUtils.runShellCmd(command)
	if not data:
		raise FontInfoParseError("Error: Failed getting  log from tx from %, when trying to get FontName." % (fPath))
		
	m = re.search(r"BlueFuzz\s+(\d+(?:\.\d+)*)", data) 
	if m:
		blueFuzz = int(m.group(1))
	return blueFuzz
예제 #13
0
def getFontName(fPath):
	command = "tx -dump -0 %s 2>&1" % (fPath)
	data = FDKUtils.runShellCmd(command)
	if not data:
		raise FontInfoParseError("Error: Failed getting  log from tx from %, when tryin to get FontName." % (fPath))
		
	m = re.search(r"FontName\s+\"([^\"]+)", data) 
	if not m:
		print data
		raise FontInfoParseError("Error: Failed finding FontName in tx log from  %s." % (fPath))
	return m.group(1)
예제 #14
0
파일: ProofPDF.py 프로젝트: brawer/afdko
def CheckEnvironment():
	txPath = 'tx'
	txError = 0

	try:
		exe_dir, fdkSharedDataDir = FDKUtils.findFDKDirs()
	except FDKUtils.FDKEnvError:
		logMsg("Please re-install the FDK. Cannot find the FDK/Tools/SharedData directory.")
		raise FDKEnvironmentError

	command = "%s -u 2>&1" % (txPath)
	report = FDKUtils.runShellCmd(command)
	if "options" not in report:
			txError = 1
	
	if  txError:
		logMsg("Please re-install the FDK. The executable directory \"%s\" is missing the tool: < %s >." % (exe_dir, txPath ))
		logMsg("or the files referenced by the shell script is missing.")
		raise FDKEnvironmentError

	return txPath, fdkSharedDataDir
예제 #15
0
def saveFontFile(ttFont, inputPath, outFilePath, fontType, txPath):
    overwriteOriginal = 0
    if inputPath == outFilePath:
        overwriteOriginal = 1
    tempPath = inputPath + ".temp.ac"

    if fontType == 0:  # OTF
        if overwriteOriginal:
            ttFont.save(tempPath)
            ttFont.close()
            if os.path.exists(inputPath):
                try:
                    os.remove(inputPath)
                    os.rename(tempPath, inputPath)
                except (OSError, IOError):
                    logMsg("\t%s" % (traceback.format_exception_only(
                        sys.exc_type, sys.exc_value)[-1]))
                    logMsg(
                        "Error: could not overwrite original font file path '%s'. Hinted font file path is '%s'."
                        % (inputPath, tempPath))
        else:
            ttFont.save(outFilePath)
            ttFont.close()

    else:
        data = ttFont["CFF "].compile(ttFont)
        if fontType == 1:  # CFF
            if overwriteOriginal:
                tf = file(tempPath, "wb")
                tf.write(data)
                tf.close()
                os.rename(tempPath, inputPath)
            else:
                tf = file(outFilePath, "wb")
                tf.write(data)
                tf.close()

        elif fontType == 2:  # PS.
            tf = file(tempPath, "wb")
            tf.write(data)
            tf.close()
            finalPath = outFilePath
            command = "%s  -t1 -std \"%s\" \"%s\" 2>&1" % (txPath, tempPath,
                                                           outFilePath)
            report = FDKUtils.runShellCmd(command)
            logMsg(report)
            if "fatal" in report:
                raise IOError(
                    "Failed to convert hinted font temp file with tx %s. Maybe target font font file '%s' is set to read-only."
                    % (tempPath, outFilePath))

        if os.path.exists(tempPath):
            os.remove(tempPath)
예제 #16
0
	def saveChanges(self):
		ttFont = self.ttFont
		fontType = self.fontType
		inputPath = self.inputPath
		outFilePath = self.outFilePath

		overwriteOriginal = 0
		if inputPath == outFilePath:
			overwriteOriginal = 1
		tempPath = inputPath +  ".temp.ac"
	
		if fontType == 0: # OTF
			if overwriteOriginal:
				ttFont.save(tempPath)
				ttFont.close()
				if os.path.exists(inputPath):
					try:
						os.remove(inputPath)
						os.rename(tempPath, inputPath)
					except (OSError, IOError):
						self.logMsg( "\t%s" %(traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1]))
						self.logMsg("Error: could not overwrite original font file path '%s'. Hinted font file path is '%s'." % (inputPath, tempPath))
			else:
				ttFont.save(outFilePath)
				ttFont.close()
	
		else:
			data = ttFont["CFF "].compile(ttFont)
			if fontType == 1: # CFF
				if overwriteOriginal:
					tf = file(tempPath, "wb")
					tf.write(data)
					tf.close()
					os.rename(tempPath, inputPath)
				else:
					tf = file(outFilePath, "wb")
					tf.write(data)
					tf.close()
	
			elif  fontType == 2: # PS.
				tf = file(tempPath, "wb")
				tf.write(data)
				tf.close()
				finalPath = outFilePath
				command="tx  -t1 -std \"%s\" \"%s\" 2>&1" % (tempPath, outFilePath)
				report = FDKUtils.runShellCmd(command)
				self.logMsg(report)
				if "fatal" in report:
					raise IOError("Failed to convert hinted font temp file with tx %s. Maybe target font font file '%s' is set to read-only." % (tempPath, outFilePath))
	
			if os.path.exists(tempPath):
				os.remove(tempPath)
예제 #17
0
def CheckEnvironment():
    txPath = 'tx'
    txError = 0
    command = "%s -u 2>&1" % (txPath)
    report = FDKUtils.runShellCmd(command)
    if "Copyright" not in report:
        txError = 1

    if txError:
        logMsg(
            "Please re-install the FDK. The path to the program 'tx' is not in the environment variable PATH."
        )
        raise FDKEnvironmentError

    command = "outlineCheck -u 2>&1"
    report = FDKUtils.runShellCmd(command)
    if "version" not in report:
        logMsg(
            "Please re-install the FDK. The path to the program o'utlineCheck' is not in the environment variable PATH."
        )
        raise FDKEnvironmentError

    return txPath
예제 #18
0
파일: StemHist.py 프로젝트: blakejia/afdko
def CheckEnvironment():
	txPath = 'tx'
	txError = 0
	command = "%s -u 2>&1" % (txPath)
	report = FDKUtils.runShellCmd(command)
	if "options" not in report:
			txError = 1
	
	if  txError:
		logMsg("Please re-install the FDK. The executable directory \"%s\" is missing the tool: < %s >." % (exe_dir, txPath ))
		logMsg("or the files referenced by the shell script is missing.")
		raise FDKEnvironmentError

	return txPath
예제 #19
0
def mergeFontToCFF(srcPath, outputPath, doSubr):
	# We assume that srcPath is a type 1 font,and outputPath is an OTF font.
	
	# First, convert src font to cff, and subroutinize it if so requested.
	tempPath = srcPath + ".temp.cff"
	subrArg = ""
	if doSubr:
		subrArg=" +S"
	command="tx -cff +b%s \"%s\" \"%s\" 2>&1" % (subrArg, srcPath, tempPath)
	report = FDKUtils.runShellCmd(command)
	if ("fatal" in report) or ("error" in report):
		print report
		raise FontInfoParseError("Failed to convert font '%s' to CFF." % (fontPath))
		
	# Now merge it into the output file.
	command="sfntedit -a CFF=\"%s\" \"%s\" 2>&1" % (tempPath, outputPath)
	report = FDKUtils.runShellCmd(command)
	if not debug:
		if os.path.exists(tempPath):
			os.remove(tempPath)
	if ("fatal" in report) or ("error" in report):
		print report
		raise FontInfoParseError("Failed to convert font '%s' to CFF." % (fontPath))
예제 #20
0
def getFontBBox(fPath):
	fontBBox = [-200, -200,1000,100]
	command = "tx -dump -0 %s 2>&1" % (fPath)
	data = FDKUtils.runShellCmd(command)
	if not data:
		raise FontInfoParseError("Error: Failed getting  log from tx from %, when tryingg to get FontBBox." % (fPath))
	
	m = re.search(r"FontBBox[^{]+{([^}]+)}", data) 
	if not m:
		print data
		raise FontInfoParseError("Error: Failed finding FontBBox in tx log from  %s." % (fPath))
	fontBBox = m.group(1).split(",")
	fontBBox = map(int, fontBBox)
	return fontBBox
예제 #21
0
def getFontBBox(fPath):
	fontBBox = [-200, -200,1000,100]
	command = "tx -dump -0 %s 2>&1" % (fPath)
	data = FDKUtils.runShellCmd(command)
	if not data:
		raise FontInfoParseError("Error: Failed getting  log from tx from %, when tryingg to get FontBBox." % (fPath))
	
	m = re.search(r"FontBBox[^{]+{([^}]+)}", data) 
	if not m:
		print data
		raise FontInfoParseError("Error: Failed finding FontBBox in tx log from  %s." % (fPath))
	fontBBox = m.group(1).split(",")
	fontBBox = map(int, fontBBox)
	return fontBBox
예제 #22
0
def getGlyphList(fPath, removeNotdef = 0):
	command = "tx -dump -4 %s 2>&1" % (fPath)
	data = FDKUtils.runShellCmd(command)
	if not data:
		print "Error: Failed getting glyph names from  %s with tx." % (fPath)
		return []
	
	nameList = re.findall(r"[\r\n]glyph.+?{([^,]+),", data) # initial newline keeps us from picking up the first column header  line
	if not nameList:
		print "Error: Failed getting glyph names from  %s with tx." % (fPath)
		print data
		return []
	if removeNotdef:
		nameList.remove(".notdef")
	return nameList
예제 #23
0
def getGlyphList(fPath, removeNotdef = 0):
	command = "tx -dump -4 %s 2>&1" % (fPath)
	data = FDKUtils.runShellCmd(command)
	if not data:
		print "Error: Failed getting glyph names from  %s with tx." % (fPath)
		return []
	
	nameList = re.findall(r"[\r\n]glyph.+?{([^,]+),", data) # initial newline keeps us from picking up the first column header  line
	if not nameList:
		print "Error: Failed getting glyph names from  %s with tx." % (fPath)
		print data
		return []
	if removeNotdef:
		nameList.remove(".notdef")
	return nameList
예제 #24
0
def makeCIDFontInfo(fontPath, cidfontinfoPath):
    cfiDict = {}
    for key in kRequiredCIDFontInfoFields + kOptionalFields:
        cfiDict[key] = None
    cfiDict["Weight"] = "(Regular)"
    cfiDict["AdobeCopyright"] = "0"

    # get regular FontDict.
    command = "tx -0 \"%s\" 2>&1" % (fontPath)
    report = FDKUtils.runShellCmd(command)
    if ("fatal" in report) or ("error" in report):
        print report
        raise FontInfoParseError(
            "Failed to dump font dict using tx from font '%s'" % (fontPath))

    for entry in txFields:
        match = re.search(entry[0] + "\s+(.+?)[\r\n]", report)
        if match:
            entry[2] = match.group(1)

    cfiDict["Registry"] = "Adobe"
    cfiDict["Ordering"] = "Identity"
    cfiDict["Supplement"] = "0"

    for entry in txFields:
        if entry[2]:
            cfiDict[entry[1]] = entry[2]
        elif entry[1] in kRequiredCIDFontInfoFields:
            haveError = 1
            print "Error: did not find required info '%s' in tx dump of font '%s'." % (
                entry[1], fontPath)

    try:
        fp = open(cidfontinfoPath, "wt")
        for key in kCIDFontInfokeyList:
            value = cfiDict[key]
            if value == None:
                continue
            if value[0] == "\"":
                value = "(" + value[1:-1] + ")"
            string = "%s\t%s" % (key, value)
            fp.write(string + os.linesep)
            fp.write(os.linesep)
        fp.close()
    except (IOError, OSError):
        msg = "Error. Could not open and write file '%s'" % (cidfontinfoPath)
        raise FontInfoParseError(msg)
    return
예제 #25
0
def CheckEnvironment():
    txPath = 'tx'
    txError = 0
    command = "%s -u 2>&1" % (txPath)
    report = FDKUtils.runShellCmd(command)
    if "Copyright" not in report:
        txError = 1

    if txError:
        logMsg(
            "Please re-install the FDK. The executable directory \"%s\" is missing the tool: < %s >."
            % (exe_dir, txPath))
        logMsg("or the files referenced by the shell script is missing.")
        raise FDKEnvironmentError

    return txPath
예제 #26
0
def makeCIDFontInfo(fontPath, cidfontinfoPath):
	cfiDict = {}
	for key in kRequiredCIDFontInfoFields + kOptionalFields:
		cfiDict[key] = None
	cfiDict["Weight"] = "(Regular)"
	cfiDict["AdobeCopyright"] = "0"

	# get regular FontDict.
	command="tx -0 \"%s\" 2>&1" % (fontPath)
	report = FDKUtils.runShellCmd(command)
	if ("fatal" in report) or ("error" in report):
		print report
		raise FontInfoParseError("Failed to dump font dict using tx from font '%s'" % (fontPath))

	for entry in txFields:
		match = re.search(entry[0]+ "\s+(.+?)[\r\n]", report)
		if match:
			entry[2] = match.group(1)

	cfiDict["Registry"] = "Adobe"
	cfiDict["Ordering"] = "Identity"
	cfiDict["Supplement"] = "0"
	
	for entry in txFields:
		if entry[2]:
			cfiDict[entry[1]] = entry[2]
		elif entry[1] in kRequiredCIDFontInfoFields:
			haveError = 1
			print "Error: did not find required info '%s' in tx dump of font '%s'." % (entry[1], fontPath) 
	

	try:
		fp = open(cidfontinfoPath, "wt")
		for key in kCIDFontInfokeyList:
			value = cfiDict[key]
			if value == None:
				continue
			if value[0] == "\"":
				value = "(" + value[1:-1] + ")"
			string = "%s\t%s" % (key, value)
			fp.write(string + os.linesep)
			fp.write(os.linesep)
		fp.close()
	except (IOError, OSError):
		msg = "Error. Could not open and write file '%s'" % (cidfontinfoPath)
		raise FontInfoParseError(msg)
	return
예제 #27
0
def openOpenTypeFile(path, outFilePath):
	# If input font is  CFF or PS, build a dummy ttFont in memory..
	# return ttFont, and flag if is a real OTF font Return flag is 0 if OTF, 1 if CFF, and 2 if PS/
	fontType  = 0 # OTF
	tempPathCFF = path + kTempCFFSuffix
	try:
		ff = file(path, "rb")
		data = ff.read(10)
		ff.close()
	except (IOError, OSError):
		logMsg("Failed to open and read font file %s." % path)

	if data[:4] == "OTTO": # it is an OTF font, can process file directly
		try:
			ttFont = TTFont(path)
		except (IOError, OSError):
			raise focusFontError("Error opening or reading from font file <%s>." % path)
		except TTLibError:
			raise focusFontError("Error parsing font file <%s>." % path)

		try:
			cffTable = ttFont["CFF "]
		except KeyError:
			raise focusFontError("Error: font is not a CFF font <%s>." % fontFileName)

	else:
	
		# It is not an OTF file.
		if (data[0] == '\1') and (data[1] == '\0'): # CFF file
			fontType = 1
			tempPathCFF = path
		elif not "%" in data:
			#not a PS file either
			logMsg("Font file must be a PS, CFF or OTF  fontfile: %s." % path)
			raise focusFontError("Font file must be PS, CFF or OTF file: %s." % path)
	
		else:  # It is a PS file. Convert to CFF.	
			fontType =  2
			print "Converting Type1 font to temp CFF font file..."
			command="tx  -cff +b -std \"%s\" \"%s\" 2>&1" % (path, tempPathCFF)
			report = FDKUtils.runShellCmd(command)
			if "fatal" in report:
				logMsg("Attempted to convert font %s  from PS to a temporary CFF data file." % path)
				logMsg(report)
				raise focusFontError("Failed to convert PS font %s to a temp CFF font." % path)
		
		# now package the CFF font as an OTF font.
		ff = file(tempPathCFF, "rb")
		data = ff.read()
		ff.close()
		try:
			ttFont = TTFont()
			cffModule = getTableModule('CFF ')
			cffTable = cffModule.table_C_F_F_('CFF ')
			ttFont['CFF '] = cffTable
			cffTable.decompile(data, ttFont)
		except:
			logMsg( "\t%s" %(traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1]))
			logMsg("Attempted to read font %s  as CFF." % path)
			raise focusFontError("Error parsing font file <%s>." % path)

	fontData = CFFFontData(ttFont, path, outFilePath, fontType, logMsg)
	return fontData
예제 #28
0
def checkFile(path, options):
    #    use fontTools library to open font and extract CFF table.
    #    If error, skip font and report error.
    seenChangedGlyph = 0
    fontFileName = os.path.basename(path)
    logMsg("Checking font %s. Start time: %s." % (path, time.asctime()))
    try:
        fontData = openFile(path, options.outFilePath, options.allowChanges)
        fontData.allowDecimalCoords = options.allowDecimalCoords
    except (IOError, OSError):
        logMsg(
            traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
        raise focusFontError("Error opening or reading from font file <%s>." %
                             fontFileName)
    except:
        logMsg(
            traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
        raise focusFontError("Error parsing font file <%s>." % fontFileName)

    #   filter specified list, if any, with font list.
    fontGlyphList = fontData.getGlyphList()
    glyphList = filterGlyphList(options, fontGlyphList, fontFileName)
    if not glyphList:
        raise focusFontError(
            "Error: selected glyph list is empty for font <%s>." %
            fontFileName)

    removeHints = 1
    reportCB = logMsg
    reportText = ""

    # If the user has not specified an em-square, and the font has am em-square other than 1000, supply it.
    if not options.emSquare:
        emSquare = fontData.getUnitsPerEm()
        if emSquare != "1000":
            options.emSquare = emSquare

    arg_string = buildArgString(options)

    dotCount = 0
    seenGlyphCount = 0
    processedGlyphCount = 0
    for name in glyphList:
        seenGlyphCount += 1
        if options.beVerbose:
            logMsg("Checking %s -- ," %
                   (aliasName(name)))  # output message when -v option is used
        else:
            logMsg(".,")
            dotCount += 1
            if dotCount > 40:
                dotCount = 0
                logMsg(
                    "")  # I do this to never have more than 40 dots on a line.
                # This in turn give reasonable performance when calling checkOutlines in a subprocess
                # and getting output with std.readline()

        if os.path.exists(kTempFilepathOut):
            os.remove(kTempFilepathOut)

        # 	Convert to bez format
        bezString, width, hasHints = fontData.convertToBez(
            name, removeHints, options.beVerbose, options.checkAll)
        if bezString == None:
            continue
        processedGlyphCount += 1

        if "mt" not in bezString:
            # skip empty glyphs.
            continue

        # write bez file and run checkoutlinesexe
        fp = open(kTempFilepath, "wt")
        fp.write(bezString)
        fp.close()
        command = "checkoutlinesexe -o %s %s" % (arg_string, kTempFilepath)
        if debug:
            print "calling command", command
        log = FDKUtils.runShellCmd(command)
        # The suffix saying what bez file was written isn't useful here.
        log = re.sub(r"Wrote fixed file.+\s*", "", log)
        if log:
            if not options.beVerbose:
                dotCount = 0
                logMsg("")
                logMsg("Checking %s -- ," % (aliasName(name))
                       )  # output message when -v option is NOT used
                logMsg(log)
            else:
                logMsg(log)
        if options.allowChanges and os.path.exists(kTempFilepathOut):
            fp = open(kTempFilepathOut, "rt")
            bezData = fp.read()
            fp.close()
            if bezData != bezString:
                fontData.updateFromBez(bezData, name, width, options.beVerbose)
                seenChangedGlyph = 1

    if not options.beVerbose:
        logMsg("")
    if seenChangedGlyph:
        # save fontFile.
        fontData.saveChanges()
    else:
        fontData.close()

    if processedGlyphCount != seenGlyphCount:
        logMsg("Skipped %s of %s glyphs." %
               (seenGlyphCount - processedGlyphCount, seenGlyphCount))
    logMsg("Done with font %s. End time: %s." % (path, time.asctime()))
    if debug:
        print "Temp bez file in", kTempFilepath
        print "Temp bez file out", kTempFilepathOut
    else:
        if os.path.exists(kTempFilepathOut):
            os.remove(kTempFilepathOut)
        if os.path.exists(kTempFilepath):
            os.remove(kTempFilepath)
        # remove temp file left over from openFile.
        tempPathCFF = path + kTempCFFSuffix
        if os.path.exists(tempPathCFF):
            os.remove(tempPathCFF)
예제 #29
0
def collectStemsFont(path, options, txPath):
    #    use fontTools library to open font and extract CFF table.
    #    If error, skip font and report error.
    fontFileName = os.path.basename(path)
    logMsg("")
    if options.doAlign:
        logMsg("Collecting alignment zones for font %s. Start time: %s." %
               (path, time.asctime()))
    else:
        logMsg("Collecting stems for font %s. Start time: %s." %
               (path, time.asctime()))

    try:
        fontData = openFile(path)
    except (IOError, OSError):
        logMsg(
            traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
        raise ACFontError("Error opening or reading from font file <%s>." %
                          fontFileName)
    except:
        logMsg(
            traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
        raise ACFontError("Error parsing font file <%s>." % fontFileName)

    #   filter specified list, if any, with font list.
    fontGlyphList = fontData.getGlyphList()
    glyphList = filterGlyphList(options, fontGlyphList, fontFileName)
    if not glyphList:
        raise ACFontError(
            "Error: selected glyph list is empty for font <%s>." %
            fontFileName)

    tempBaseName = os.tempnam()
    tempBez = tempBaseName + ".bez"
    tempReport = tempBez + ".rpt"
    tempFI = tempBaseName + ".fi"

    #    open font plist file, if any. If not, create empty font plist.
    psName = fontData.getPSName()

    #    build alignment zone string
    allow_no_blues = 1
    noFlex = 0
    vCounterGlyphs = hCounterGlyphs = []
    fdGlyphDict, fontDictList = fontData.getfdInfo(psName, path,
                                                   allow_no_blues, noFlex,
                                                   vCounterGlyphs,
                                                   hCounterGlyphs, glyphList)

    if fdGlyphDict == None:
        fdDict = fontDictList[0]
        fp = open(tempFI, "wt")
        fp.write(fdDict.getFontInfo())
        fp.close()
    else:
        if not options.verbose:
            logMsg(
                "Note: Using alternate FDDict global values from fontinfo file for some glyphs. Remove option '-q' to see which dict is used for which glyphs."
            )

    removeHints = 1
    isCID = fontData.isCID()
    lastFDIndex = None
    glyphReports = GlyphReports()

    if not options.verbose:
        dotCount = 0
        curTime = time.time()

    for name in glyphList:
        if name == ".notdef":
            continue

        if options.verbose:
            logMsg("Checking %s." % name)
        else:
            newTime = time.time()
            if (newTime - curTime) > 1:
                print ".",
                sys.stdout.flush()
                curTime = newTime
                dotCount += 1
            if dotCount > 40:
                dotCount = 0
                print ""

        # 	Convert to bez format
        bezString, width, hasHints = fontData.convertToBez(
            name, removeHints, options.verbose)
        if bezString == None:
            continue
        if "mt" not in bezString:
            # skip empty glyphs.
            continue

        # get new fontinfo string if FD array index has changed, as
        # as each FontDict has different alignment zones.
        gid = fontData.getGlyphID(name)
        if isCID:  #
            fdIndex = fontData.getfdIndex(gid)
            if not fdIndex == lastFDIndex:
                lastFDIndex = fdIndex
                fdDict = fontData.getFontInfo(psName, path,
                                              options.allow_no_blues,
                                              options.noFlex,
                                              options.vCounterGlyphs,
                                              options.hCounterGlyphs, fdIndex)
                fp = open(tempFI, "wt")
                fp.write(fdDict.getFontInfo())
                fp.close()
        else:
            if (fdGlyphDict != None):
                try:
                    fdIndex = fdGlyphDict[name][0]
                except KeyError:
                    # use default dict.
                    fdIndex = 0
                if lastFDIndex != fdIndex:
                    lastFDIndex = fdIndex
                    fdDict = fontDictList[fdIndex]
                    fp = open(tempFI, "wt")
                    fp.write(fdDict.getFontInfo())
                    fp.close()

        glyphReports.startGlyphName(name)

        # 	Call auto-hint library on bez string.
        bp = open(tempBez, "wt")
        bp.write(bezString)
        bp.close()

        if os.path.exists(tempReport):
            os.remove(tempReport)
        if options.doAlign:
            doAlign = "-ra"
        else:
            doAlign = "-rs"

        if options.allStems:
            allStems = "-a"
        else:
            allStems = ""

        command = "autohintexe -q %s %s  -f \"%s\" \"%s\" 2>&1" % (
            doAlign, allStems, tempFI, tempBez)
        if options.debug:
            print command
        log = FDKUtils.runShellCmd(command)
        if log:
            print log
            if "number terminator while" in log:
                print tempBez
                sys.exit()

        if os.path.exists(tempReport):
            bp = open(tempReport, "rt")
            report = bp.read()
            bp.close()
            if options.debug:
                print "Wrote AC fontinfo data file to", tempFI
                print "Wrote AC output rpt file to", tempReport
            else:
                os.remove(tempReport)
            report.strip()
            if report:
                glyphReports.addGlyphReport(report)
                if options.debug:
                    rawData.append(report)
        else:
            print "Error - failure in processing outline data"
            report = None

    hStemDict, vStemDict, topZoneDict, bottomZoneDict = glyphReports.getReportDicts(
    )
    if options.reportPath:
        reportPath = options.reportPath
    else:
        reportPath = path
    PrintReports(reportPath, hStemDict, vStemDict, topZoneDict, bottomZoneDict)
    fontData.close()
    logMsg("Done with font %s. End time: %s." % (path, time.asctime()))
예제 #30
0
def openOpenTypeFile(path, outFilePath):
    # If input font is  CFF or PS, build a dummy ttFont in memory..
    # return ttFont, and flag if is a real OTF font Return flag is 0 if OTF, 1 if CFF, and 2 if PS/
    fontType = 0  # OTF
    tempPathCFF = path + kTempCFFSuffix
    try:
        ff = file(path, "rb")
        data = ff.read(10)
        ff.close()
    except (IOError, OSError):
        logMsg("Failed to open and read font file %s." % path)

    if data[:4] == "OTTO":  # it is an OTF font, can process file directly
        try:
            ttFont = TTFont(path)
        except (IOError, OSError):
            raise ACFontError("Error opening or reading from font file <%s>." %
                              path)
        except TTLibError:
            raise ACFontError("Error parsing font file <%s>." % path)

        try:
            cffTable = ttFont["CFF "]
        except KeyError:
            raise ACFontError("Error: font is not a CFF font <%s>." %
                              fontFileName)

    else:

        # It is not an OTF file.
        if (data[0] == '\1') and (data[1] == '\0'):  # CFF file
            fontType = 1
            tempPathCFF = path
        elif not "%" in data:
            #not a PS file either
            logMsg("Font file must be a PS, CFF or OTF  fontfile: %s." % path)
            raise ACFontError("Font file must be PS, CFF or OTF file: %s." %
                              path)

        else:  # It is a PS file. Convert to CFF.
            fontType = 2
            print "Converting Type1 font to temp CFF font file..."
            command = "tx  -cff +b -std \"%s\" \"%s\" 2>&1" % (path,
                                                               tempPathCFF)
            report = FDKUtils.runShellCmd(command)
            if "fatal" in report:
                logMsg(
                    "Attempted to convert font %s  from PS to a temporary CFF data file."
                    % path)
                logMsg(report)
                raise ACFontError(
                    "Failed to convert PS font %s to a temp CFF font." % path)

        # now package the CFF font as an OTF font.
        ff = file(tempPathCFF, "rb")
        data = ff.read()
        ff.close()
        try:
            ttFont = TTFont()
            cffModule = getTableModule('CFF ')
            cffTable = cffModule.table_C_F_F_('CFF ')
            ttFont['CFF '] = cffTable
            cffTable.decompile(data, ttFont)
        except:
            logMsg("\t%s" % (traceback.format_exception_only(
                sys.exc_type, sys.exc_value)[-1]))
            logMsg("Attempted to read font %s  as CFF." % path)
            raise ACFontError("Error parsing font file <%s>." % path)

    fontData = CFFFontData(ttFont, path, outFilePath, fontType, logMsg)
    return fontData
예제 #31
0
파일: autohint.py 프로젝트: NuttShell/afdko
def getOptions():
	global gLogFile
	options = ACOptions()
	i = 1
	numOptions = len(sys.argv)
	while i < numOptions:
		arg = sys.argv[i]
		if options.inputPath:
			raise ACOptionParseError("Option Error: All options must preceed the  input font path <%s>." % arg) 

		if arg == "-h":
			print __help__
			command = "autohintexe -v"
			report = FDKUtils.runShellCmd(command)
			logMsg( report)
			raise ACOptionParseError
		elif arg == "-u":
			print __usage__
			command = "autohintexe -v"
			report = FDKUtils.runShellCmd(command)
			logMsg( report)
			raise ACOptionParseError
		elif arg == "-hfd":
			print __FDDoc__
			raise ACOptionParseError
		elif arg == "-pfd":
			options.printDefaultFDDict = 1
		elif arg == "-pfdl":
			options.printFDDictList = 1
		elif arg == "-hf":
			options.usePlistFile = 1
		elif arg == "-a":
			options.hintAll = 1
		elif arg == "-all":
			options.hintAll = 1
		elif arg == "-r":
			options.rehint = 1
		elif arg == "-q":
			options.verbose = 0
		elif arg == "-c":
			options.allowChanges = 1
		elif arg == "-nf":
			options.noFlex = 1
		elif arg == "-ns":
			options.noHintSub = 1
		elif arg == "-nb":
			options.allow_no_blues = 1
		elif arg in ["-xg", "-g"]:
			if arg == "-xg":
				options.excludeGlyphList = 1
			i = i +1
			glyphString = sys.argv[i]
			if glyphString[0] == "-":
				raise ACOptionParseError("Option Error: it looks like the first item in the glyph list following '-g' is another option.") 
			options.glyphList += parseGlyphListArg(glyphString)
		elif arg in ["-xgf", "-gf"]:
			if arg == "-xgf":
				options.excludeGlyphList = 1
			i = i +1
			filePath = sys.argv[i]
			if filePath[0] == "-":
				raise ACOptionParseError("Option Error: it looks like the the glyph list file following '-gf' is another option.") 
			try:
				gf = file(filePath, "rt")
				glyphString = gf.read()
				gf.close()
			except (IOError,OSError):
				raise ACOptionParseError("Option Error: could not open glyph list file <%s>." %  filePath) 
			options.glyphList += parseGlyphListArg(glyphString)
		elif arg == "-cf":
			i = i +1
			filePath = sys.argv[i]
			if filePath[0] == "-":
				raise ACOptionParseError("Option Error: it looks like the the counter hint glyph list file following '-cf' is another option.") 
			try:
				options.counterHintFile = filePath
				options.hCounterGlyphs, options.vCounterGlyphs = parseCounterHintData(filePath)
			except (IOError,OSError):
				raise ACOptionParseError("Option Error: could not open counter hint glyph list  file <%s>." %  filePath) 
		elif arg == "-logOnly":
			options.logOnly = 1
		elif arg == "-log":
			i = i +1
			options.logFilePath = sys.argv[i]
			gLogFile = open(options.logFilePath, "wt")
		elif arg == "-o":
			i = i +1
			options.outputPath = sys.argv[i]
		elif arg == "-d":
			options.debug = 1
		elif arg == "-decimal":
			options.allowDecimalCoords = True
		elif arg[0] == "-":
			raise ACOptionParseError("Option Error: Unknown option <%s>." %  arg) 
		else:
			options.inputPath = arg
		i  += 1
	if not options.inputPath:
		raise ACOptionParseError("Option Error: You must provide a font file path.") 

	if not os.path.exists(options.inputPath):
		raise ACOptionParseError("Option Error: The input font file path %s' does not exist." % (options.inputPath)) 
	else:
		options.inputPath = options.inputPath.rstrip(os.sep) # might be a UFO font. auto completion in some shells adds a dir separator, which then causes problems with os.path.dirname().

	checkFontinfoFile(options)
	
	if options.logOnly:
		options.verbose = 1
		options.hintAll = 1
		
	return options
예제 #32
0
def openFile(path, txPath):
	# If input font is  CFF or PS, build a dummy ttFont.
	tempPathCFF = None
	cffPath = None

	# If it is CID-keyed font, we need to convert it to a name-keyed font. This is a hack, but I really don't want to add CID support to
	# the very simple-minded PDF library.
	command="%s   -dump -0  \"%s\" 2>&1" % (txPath, path)
	report = FDKUtils.runShellCmd(command)
	if "CIDFontName" in report:
		tfd,tempPath1 = tempfile.mkstemp()
		os.close(tfd)
		command="%s   -t1 -decid -usefd 0  \"%s\" \"%s\" 2>&1" % (txPath, path, tempPath1)
		report = FDKUtils.runShellCmd(command)
		if "fatal" in report:
			logMsg(report)
			logMsg("Failed to convert CID-keyed font %s to a temporary Typ1 data file." % path)

		tfd,tempPathCFF = tempfile.mkstemp()
		os.close(tfd)
		command="%s   -cff +b  \"%s\" \"%s\" 2>&1" % (txPath, tempPath1, tempPathCFF)
		report = FDKUtils.runShellCmd(command)
		if "fatal" in report:
			logMsg(report)
			logMsg("Failed to convert CID-keyed font %s to a temporary CFF data file." % path)
		cffPath = tempPathCFF
		os.remove(tempPath1)
	elif os.path.isdir(path):
		# See if it is a UFO font by truing to dump it.
		command="%s   -dump -0  \"%s\" 2>&1" % (txPath, path)
		report = FDKUtils.runShellCmd(command)
		if not "sup.srcFontType" in report:
			logMsg(report)
			logMsg("Failed to open directory %s as a UFO font." % path)
			
		tfd,tempPathCFF = tempfile.mkstemp()
		os.close(tfd)
		command="%s   -cff +b  \"%s\" \"%s\" 2>&1" % (txPath, path, tempPathCFF)
		report = FDKUtils.runShellCmd(command)
		if "fatal" in report:
			logMsg(report)
			logMsg("Failed to convert ufo font %s to a temporary CFF data file." % path)
		cffPath = tempPathCFF
	else:
		try:
			ff = file(path, "rb")
			data = ff.read(10)
			ff.close()
		except (IOError, OSError):
			import traceback
			traceback.print_exc()
			raise FontError("Failed to open and read font file %s. Check file/directory permissions." % path)
		
		if len(data) < 10:
			raise FontError("Error: font file was zero size: may be a resource fork font, which this program does not process. <%s>." % path)
		if (data[:4] == "OTTO") or (data[:4] == "true") or (data[:4] == "\0\1\0\0"): # it is an OTF/TTF font, can process file directly
			try:
				ttFont = ttLib.TTFont(path)
			except (IOError, OSError):
				raise FontError("Error opening or reading from font file <%s>." % path)
			except TTLibError:
				raise FontError("Error parsing font file 333 <%s>." % path)
	
			if not (ttFont.has_key('CFF ') or ttFont.has_key('glyf')):
				raise FontError("Error: font is not a CFF or TrueType font <%s>." % path)
	
			return ttFont, tempPathCFF
	
		# It is not an OTF file.
		if (data[0] == '\1') and (data[1] == '\0'): # CFF file
			cffPath = path
		elif not "%" in data:
			#not a PS file either
			logMsg("Font file must be a PS, CFF or OTF  fontfile: %s." % path)
			raise FontError("Font file must be PS, CFF or OTF file: %s." % path)
	
		else:  # It is a PS file. Convert to CFF.	
			tfd,tempPathCFF = tempfile.mkstemp()
			os.close(tfd)
			cffPath = tempPathCFF
			command="%s   -cff +b  \"%s\" \"%s\" 2>&1" % (txPath, path, tempPathCFF)
			report = FDKUtils.runShellCmd(command)
			if "fatal" in report:
				logMsg("Attempted to convert font %s  from PS to a temporary CFF data file." % path)
				logMsg(report)
				raise FontError("Failed to convert PS font %s to a temp CFF font." % path)

	# now package the CFF font as an OTF font
	ff = file(cffPath, "rb")
	data = ff.read()
	ff.close()
	try:
		ttFont = ttLib.TTFont()
		cffModule = ttLib.getTableModule('CFF ')
		cffTable = cffModule.table_C_F_F_('CFF ')
		ttFont['CFF '] = cffTable
		cffTable.decompile(data, ttFont)
	except:
		import traceback
		traceback.print_exc()
		logMsg("Attempted to read font %s  as CFF." % path)
		raise FontError("Error parsing font file <%s>." % path)
	return ttFont, tempPathCFF
예제 #33
0
def fixFontDict(tempPath, fdDict):
	
	txtPath = tempPath + ".txt"
	command = "detype1 %s %s 2>&1" % (tempPath, txtPath)
	log = FDKUtils.runShellCmd(command)
	if log:
		print log
	fp = open(txtPath, "rt")
	data = fp.read()
	fp.close()
	
	# fix font name.
	# We always search of it, as it is always present, and we can use the following
	# white space to get the file new line.
	m = re.search(r"(/FontName\s+/\S+\s+def)(\s+)", data)
	newLine = m.group(2)
	if not m:
		raise FontParseError("Failed to find FontName in input font!. %s" % (tempPath))
	if fdDict.FontName:
		target = "/FontName /%s def" % (fdDict.FontName)
		data = data[:m.start(1)] + target +  data[m.end(1):]
	
	# fix em square
	if fdDict.OrigEmSqUnits:
		m = re.search(r"/FontMatrix\s+\[.+?\]\s+def", data)
		if not m:
			raise FontParseError("Failed to find FontMatrix in input font! %s" % (tempPath))
		emUnits = eval(fdDict.OrigEmSqUnits)
		a = 1.0/emUnits
		target = "/FontMatrix [%s 0 0 %s 0 0] def" % ( a, a)
		data = data[:m.start()] + target +  data[m.end():]

	# fix StemSnapH.  Remove StemSnapH if fdDict.StemSnapH is not defined, else set it.
	m = re.search(r"/StemSnapH\s+\[.+?\]\s+def", data)
	if fdDict.DominantH:
		target = "/StemSnapH %s def" % ( fdDict.DominantH)
		data = data[:m.start()] + target +  data[m.end():]
		insertIndex = m.start() + len(target)
	else:
		data = data[:m.start()] + data[m.end():]

	# fix StemSnapV.  Remove StemSnapV entry if fdDict.StemSnapV is not defined, else set it.
	m = re.search(r"/StemSnapV\s+\[.+?\]\s+def", data)
	if fdDict.DominantV:
		target = "/StemSnapV %s def" % ( fdDict.DominantV)
		data = data[:m.start()] + target +  data[m.end():]
		insertIndex = m.start() + len(target)
	else:
		data = data[:m.start()] + data[m.end():]
	
	# LanguageGroup. Remove LanguageGroup entry if fdDict.LanguageGroup is not defined, else set it.
	if fdDict.LanguageGroup:
		m = re.search(r"/LanguageGroup\s+\d+\s+def", data)
		if not m:
			target = "%s/LanguageGroup %s def" % (newLine, fdDict.LanguageGroup)
			data = data[:insertIndex] + data[insertIndex] + target +  data[insertIndex:]
		else:
			data = data[:m.start()] + target +  data[m.end():]
		target = "/LanguageGroup %s def" % (fdDict.LanguageGroup)
	else:
		m = re.search(r"/LanguageGroup\s+\d+\s+def", data)
		if m:
			data = data[:m.start()] +  data[m.end():]
	
	# Fix BlueValues. Must be present.
	m = re.search(r"/BlueValues\s+\[.+?\]\s+def", data)
	if not m:
		raise FontParseError("Failed to find BlueValues in input font! %s" % (tempPath))
	target = "/BlueValues %s def" % (fdDict.BlueValues)
	data = data[:m.start()] + target +  data[m.end():]
	insertIndex = m.start() + len(target)

	# Fix OtherBlues, if present. Remove if there are no OtherBlues entry.
	m = re.search(r"/OtherBlues\s+\[.+?\]\s+def", data)
	if fdDict.OtherBlues:
		if not m:
			target = "%s/OtherBlues %s def" % (newLine, fdDict.OtherBlues)
			data = data[:insertIndex] + target +  data[insertIndex:]
		else:
			target = "/OtherBlues %s def" % (fdDict.OtherBlues)
			data = data[:m.start()] + target +  data[m.end():]
	else:
			data = data[:m.start()] + data[m.end():]
		
	

	fp = open(txtPath, "wt")
	fp.write(data)
	fp.close()
	
	command = "type1 %s %s 2>&1" % (txtPath, tempPath)
	log = FDKUtils.runShellCmd(command)
	if log:
		print log
	
	if not debug:
		os.remove(txtPath)
	return
예제 #34
0
파일: autohint.py 프로젝트: henrich/afdko
def hintFile(options):

	path = options.inputPath
	fontFileName = os.path.basename(path)
	logMsg("Hinting font %s. Start time: %s." % (path, time.asctime()))

	try:
		useHashMap = not options.logOnly # for UFO fonts only. We always use the hash map, unless the user has said to only report issues.
		fontData = openFile(path, options.outputPath, useHashMap)
		fontData.allowDecimalCoords = options.allowDecimalCoords
		if options.writeToDefaultLayer and hasattr(fontData, "setWriteToDefault"): # UFO fonts only
			fontData.setWriteToDefault()
	except (IOError, OSError):
		logMsg( traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
		raise ACFontError("Error opening or reading from font file <%s>." % fontFileName)
	except:
		logMsg( traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
		raise ACFontError("Error parsing font file <%s>." % fontFileName)

	#   filter specified list, if any, with font list.
	fontGlyphList = fontData.getGlyphList()
	glyphList = filterGlyphList(options, fontGlyphList, fontFileName)
	if not glyphList:
		raise ACFontError("Error: selected glyph list is empty for font <%s>." % fontFileName)

	# temp file names for input and output bez files, and for the fontinfo file.
	tempBaseName = os.tempnam()
	tempBez = tempBaseName + ".bez"
	tempBezNew = tempBez + ".new"
	tempFI = tempBaseName + ".fi"
	
	#print "tempBaseName", tempBaseName
	psName = fontData.getPSName()
	
	if (not options.logOnly) and options.usePlistFile:
		fontPlist, fontPlistFilePath, isNewPlistFile = openFontPlistFile(psName, os.path.dirname(path))
		if isNewPlistFile and  not (options.hintAll or options.rehint):
			logMsg("No hint info plist file was found, so all glyphs are unknown to autohint. To hint all glyphs, run autohint again with option -a to hint all glyphs unconditionally.")
			logMsg("Done with font %s. End time: %s." % (path, time.asctime()))
			fontData.close()
			return

	# Check counter glyphs, if any.
	if options.hCounterGlyphs or options.vCounterGlyphs:
		missingList = filter(lambda name: name not in fontGlyphList, options.hCounterGlyphs + options.vCounterGlyphs)
		if missingList:
			logMsg( "\tError: glyph named in counter hint list file '%s' are not in font: %s" % (options.counterHintFile, missingList) )

	#    build alignment zone string
	if (options.printDefaultFDDict):
		logMsg("Showing default FDDict Values:")
		fdDict = fontData.getFontInfo(psName, path, options.allow_no_blues, options.noFlex, options.vCounterGlyphs, options.hCounterGlyphs)
		parseFontInfoString(str(fdDict))
		fontData.close()
		return

	fdGlyphDict, fontDictList = fontData.getfdInfo(psName, path, options.allow_no_blues, options.noFlex, options.vCounterGlyphs, options.hCounterGlyphs, glyphList)

	if options.printFDDictList:
		# Print the user defined FontDicts, and exit.
		if fdGlyphDict:
			logMsg("Showing user-defined FontDict Values:")
			for fi in range(len(fontDictList)):
				fontDict = fontDictList[fi]
				logMsg("")
				logMsg(fontDict.DictName)
				parseFontInfoString(str(fontDict))
				gnameList = []
				itemList = fdGlyphDict.items()
				itemList.sort(cmpFDDictEntries)
				for gName, entry in itemList:
					if entry[0] == fi:
						gnameList.append(gName)
				logMsg("%d glyphs:" % len(gnameList))
				if len(gnameList) > 0:
					gTxt = " ".join(gnameList)
				else:
					gTxt = "None"
				logMsg(gTxt)
		else:
			logMsg("There are no user-defined FontDict Values.")
		tempPathCFF = options.inputPath + kTempCFFSuffix
		removeTempFiles( [tempPathCFF] )
		fontData.close()
		return
		
	if fdGlyphDict == None:
		fdDict = fontDictList[0]
		fp = open(tempFI, "wt")
		fp.write(fdDict.getFontInfo())
		fp.close()
	else:
		if not options.verbose:
			logMsg("Note: Using alternate FDDict global values from fontinfo file for some glyphs. Remove option '-q' to see which dict is used for which glyphs.")


	#    for identifier in glyph-list:
	# 	Get charstring.
	removeHints = 1
	isCID = fontData.isCID()
	lastFDIndex = None
	reportCB = ACreport
	anyGlyphChanged = 0
	pListChanged = 0
	if isCID:
		options.noFlex = 1
		
	if options.verbose:
		verboseArg = ""
	else:
		verboseArg = " -q" 
		dotCount = 0
		curTime = time.time()

	if options.allowChanges:
		suppressEditArg = ""
	else:
		suppressEditArg = " -e"

	if options.noHintSub:
		supressHintSubArg = " -n"
	else:
		supressHintSubArg = ""

	if options.allowDecimalCoords:
		decimalArg = " -d"
	else:
		decimalArg = ""

	dotCount = 0
	seenGlyphCount = 0
	processedGlyphCount = 0
	for name in glyphList:
		prevACIdentifier = None
		seenGlyphCount +=1
			
		# 	Convert to bez format
		bezString, width = fontData.convertToBez(name, removeHints, options.verbose, options.hintAll)
		processedGlyphCount += 1
		if bezString == None:
			continue

		if "mt" not in bezString:
			# skip empty glyphs.
			continue
		# get new fontinfo string if FD array index has changed, as
		# as each FontDict has different alignment zones.
		gid = fontData.getGlyphID(name)
		if isCID: #
			fdIndex = fontData.getfdIndex(gid)
			if not fdIndex == lastFDIndex:
				lastFDIndex = fdIndex
				fdDict = fontData.getFontInfo(psName, path, options.allow_no_blues, options.noFlex, options.vCounterGlyphs, options.hCounterGlyphs, fdIndex)
				fp = open(tempFI, "wt")
				fp.write(fdDict.getFontInfo())
				fp.close()
		else:
			if (fdGlyphDict != None):
				try:
					fdIndex = fdGlyphDict[name][0]
				except KeyError:
					# use default dict.
					fdIndex = 0
				if lastFDIndex != fdIndex:
					lastFDIndex = fdIndex
					fdDict = fontDictList[fdIndex]
					fp = open(tempFI, "wt")
					fp.write(fdDict.getFontInfo())
					fp.close()
			

		# 	Build autohint point list identifier

		oldBezString = ""
		oldHintBezString = ""
		
		if (not options.logOnly) and options.usePlistFile:
			# If the glyph is not in the  plist file, then we skip it unless kReHintUnknown is set.
			# If the glyph is in the plist file and the outline has changed, we hint it. 
			ACidentifier = makeACIdentifier(bezString)
			try:
				(prevACIdentifier, ACtime, oldBezString, oldHintBezString) =  fontPlist[kACIDKey][name]
			except ValueError:
				(prevACIdentifier, ACtime) =  fontPlist[kACIDKey][name]
				oldBezString = oldHintBezString = ""
			except KeyError:
				pListChanged = 1 # Didn't have an entry in tempList file, so we will add one.
				if hasHints and not (options.rehint):
					# Glyphs is hinted, but not referenced in the plist file. Skip it unless options.rehint is se
					if  not isNewPlistFile:
						# Comment only if there is a plist file; otherwise, we'd be complaining for almost every glyph.
						logMsg("%s Skipping glyph - it has hints, but it is not in the hint info plist file." % aliasName(name))
						dotCount = 0
					continue

			if prevACIdentifier and (prevACIdentifier == ACidentifier): # there is an entry in the plist file and it matches what's in the font.
				if hasHints and not options.hintAll:
					continue
			else:
				pListChanged = 1

		if options.verbose:
			if fdGlyphDict:
				logMsg("Hinting %s with fdDict %s." % (aliasName(name), fdDict.DictName) )
			else:
				logMsg("Hinting %s." % aliasName(name))
		else:
			logMsg(".,")
			dotCount += 1
			if dotCount > 40:
				dotCount = 0
				logMsg("") # I do this to never have more than 40 dots on a line.
				# This in turn give reasonable performance when calling autohint in a subprocess
				# and getting output with std.readline()

		# 	Call auto-hint library on bez string.
		bp = open(tempBez, "wt")
		bp.write(bezString)
		bp.close()

		#print "oldBezString", oldBezString
		#print ""
		#print "bezString", bezString
		
		if oldBezString != "" and oldBezString == bezString:
			newBezString = oldHintBezString
		else:
			if os.path.exists(tempBezNew):
				os.remove(tempBezNew)
			command = "autohintexe %s%s%s%s -s .new -f \"%s\" \"%s\"" % (verboseArg, suppressEditArg, supressHintSubArg, decimalArg, tempFI, tempBez)
			if  options.debug:
				print command
			report = FDKUtils.runShellCmd(command)
			if report:
				if not options.verbose:
					logMsg("") # end series of "."
				logMsg(report)
			if os.path.exists(tempBezNew):
				bp = open(tempBezNew, "rt")
				newBezString = bp.read()
				bp.close()
				if options.debug:
					print "Wrote AC fontinfo data file to", tempFI
					print "Wrote AC output bez file to", tempBezNew
				else:
					os.remove(tempBezNew)
			else:
				newBezString = None
			
		if not newBezString:
			if not options.verbose:
				logMsg("")
			logMsg("%s Error - failure in processing outline data." % aliasName(name))
			continue
			
		if not (("ry" in newBezString[:200]) or ("rb" in newBezString[:200]) or ("rm" in newBezString[:200]) or ("rv" in newBezString[:200])):
			print "No hints added!"

		if options.logOnly:
			continue
			
		# 	Convert bez to charstring, and update CFF.
		anyGlyphChanged = 1
		fontData.updateFromBez(newBezString, name, width, options.verbose)

		
		if options.usePlistFile:
			bezString, hasHints, t2Wdth = convertT2GlyphToBez(t2CharString, 1)
			bezString = "%% %s%s%s" % (name, os.linesep, bezString)
			ACidentifier = makeACIdentifier(bezString)
			# add glyph hint entry to plist file
			if options.allowChanges:
				if prevACIdentifier and (prevACIdentifier != ACidentifier):
					logMsg("\t%s Glyph outline changed" % aliasName(name))
					dotCount = 0

			fontPlist[kACIDKey][name] = (ACidentifier, time.asctime(), bezString, newBezString )

	if not options.verbose:
		print "" # print final new line after progress dots.

	if  options.debug:
		print "Wrote input AC bez file to", tempBez
	else:
		tempPathCFF = options.inputPath + kTempCFFSuffix # created when a PS file is opened.
		removeTempFiles( [tempBez, tempBezNew, tempFI, tempPathCFF] )
					
	if not options.logOnly:
		if anyGlyphChanged:
			logMsg("Saving font file with new hints..." + time.asctime())
			fontData.saveChanges()
		else:
			fontData.close()
			if options.usePlistFile:
				if options.rehint:
					logMsg("No new hints. All glyphs had hints that matched the hint record file %s." % (fontPlistFilePath))
				else:
					logMsg("No new hints. All glyphs were already hinted.")
			else:
				logMsg("No glyphs were hinted.")
	if options.usePlistFile and (anyGlyphChanged or pListChanged):
		#  save font plist file.
		fontPlist.write(fontPlistFilePath)
	if processedGlyphCount != seenGlyphCount:
		logMsg("Skipped %s of %s glyphs." % (seenGlyphCount - processedGlyphCount, seenGlyphCount))
	logMsg("Done with font %s. End time: %s." % (path, time.asctime()))
예제 #35
0
파일: ProofPDF.py 프로젝트: NuttShell/afdko
def openFile(path, txPath):
	# If input font is  CFF or PS, build a dummy ttFont.
	tempPathCFF = None
	try:
		ff = file(path, "rb")
		data = ff.read(10)
		ff.close()
	except (IOError, OSError):
		import traceback
		traceback.print_exc()
		raise FontError("Failed to open and read font file %s. Check file/directory permissions." % path)
		
	if len(data) < 10:
		raise FontError("Error: font file was zero size: may be a resource fork font, which this program does not process. <%s>." % path)

	if (data[:4] == "OTTO") or (data[:4] == "true") or (data[:4] == "\0\1\0\0"): # it is an OTF/TTF font, can process file directly
		try:
			ttFont = ttLib.TTFont(path)
		except (IOError, OSError):
			raise FontError("Error opening or reading from font file <%s>." % path)
		except TTLibError:
			raise FontError("Error parsing font file 333 <%s>." % path)

		if not (ttFont.has_key('CFF ') or ttFont.has_key('glyf')):
			raise FontError("Error: font is not a CFF or TrueType font <%s>." % path)

		return ttFont, tempPathCFF

	# It is not an OTF file.
	if (data[0] == '\1') and (data[1] == '\0'): # CFF file
		cffPath = path
	elif not "%" in data:
		#not a PS file either
		logMsg("Font file must be a PS, CFF or OTF  fontfile: %s." % path)
		raise FontError("Font file must be PS, CFF or OTF file: %s." % path)

	else:  # It is a PS file. Convert to CFF.	
		tfd,tempPathCFF = tempfile.mkstemp()
		os.close(tfd)
		cffPath = tempPathCFF
		command="%s   -cff +b  \"%s\" \"%s\" 2>&1" % (txPath, path, tempPathCFF)
		report = FDKUtils.runShellCmd(command)
		if "fatal" in report:
			logMsg("Attempted to convert font %s  from PS to a temporary CFF data file." % path)
			logMsg(report)
			raise FontError("Failed to convert PS font %s to a temp CFF font." % path)

	# now package the CFF font as an OTF font for use by autohint.
	ff = file(cffPath, "rb")
	data = ff.read()
	ff.close()
	try:
		ttFont = ttLib.TTFont()
		cffModule = ttLib.getTableModule('CFF ')
		cffTable = cffModule.table_C_F_F_('CFF ')
		ttFont['CFF '] = cffTable
		cffTable.decompile(data, ttFont)
	except:
		import traceback
		traceback.print_exc()
		logMsg("Attempted to read font %s  as CFF." % path)
		raise FontError("Error parsing font file <%s>." % path)
	return ttFont, tempPathCFF
예제 #36
0
def collectStemsFont(path, options, txPath):
    #    use fontTools library to open font and extract CFF table.
    #    If error, skip font and report error.
    fontFileName = os.path.basename(path)
    logMsg("")
    if options.doAlign:
        logMsg("Collecting alignment zones for font %s. Start time: %s." %
               (path, time.asctime()))
    else:
        logMsg("Collecting stems for font %s. Start time: %s." %
               (path, time.asctime()))

    ttFont, fontType = openFile(path, txPath)
    fontGlyphList = ttFont.getGlyphOrder()

    try:
        cffTable = ttFont["CFF "]
    except KeyError:
        raise ACFontError("Error: font is not a CFF font <%s>." % fontFileName)

    #   filter specified list, if any, with font list.
    glyphList = filterGlyphList(options, fontGlyphList, fontFileName)

    # Never include the notdef in the glyph list.

    if not glyphList:
        raise ACFontError(
            "Error: selected glyph llist is empty for font <%s>." %
            fontFileName)

    tempBaseName = os.tempnam()
    tempBez = tempBaseName + ".bez"
    tempReport = tempBez + ".rpt"
    tempFI = tempBaseName + ".fi"

    #    open font plist file, if any. If not, create empty font plist.
    psName = cffTable.cff.fontNames[0]

    #    build alignment zone string
    topDict = cffTable.cff.topDictIndex[0]
    fontinfo = getFontInfo(topDict, psName, options)
    fp = open(tempFI, "wt")
    fp.write(fontinfo)
    fp.close()

    #    for identifier in glyph-list:
    # 	Get charstring.
    charStrings = topDict.CharStrings
    charStringIndex = charStrings.charStringsIndex
    removeHints = 1
    isCID = hasattr(topDict, "FDSelect")
    lastFDIndex = 0
    glyphReports = GlyphReports()

    if not options.verbose:
        dotCount = 0
        curTime = time.time()

    for name in glyphList:
        if name == ".notdef":
            continue

        if options.verbose:
            logMsg("Checking %s." % name)
        else:
            newTime = time.time()
            if (newTime - curTime) > 1:
                print ".",
                sys.stdout.flush()
                curTime = newTime
                dotCount += 1
            if dotCount > 40:
                dotCount = 0
                print ""

        # get new fontinfo string if FD array index has changed, as
        # as each FontDict has different alignment zones.
        if isCID:
            gid = ttFont.getGlyphID(name)
            fdIndex = topDict.FDSelect[gid]
            if not fdIndex == lastFDIndex:
                lastFDIndex = fdIndex
                fontinfo = getFontInfo(topDict, psName, options, fdIndex)
                fp = open(tempFI, "wt")
                fp.write(fontinfo)
                fp.close()
        else:
            gid = charStrings.charStrings[name]

        glyphReports.startGlyphName(name)

        # 	Convert to bez format
        t2CharString = charStringIndex[gid]
        try:
            bezString, hasHints, t2Wdth = convertT2GlyphToBez(
                t2CharString, removeHints)
            bezString = "%% %s%s" % (name, os.linesep) + bezString
        except SEACError:
            print "Skipping %s; can't process 'seac' composite glyphs." % (
                name)
            continue
        # 	Call auto-hint library on bez string.
        # 	Call auto-hint library on bez string.
        bp = open(tempBez, "wt")
        bp.write(bezString)
        bp.close()

        if os.path.exists(tempReport):
            os.remove(tempReport)
        if options.doAlign:
            doAlign = "-ra"
        else:
            doAlign = "-rs"

        if options.allStems:
            allStems = "-a"
        else:
            allStems = ""

        command = "autohintexe -q %s %s  -f \"%s\" \"%s\"" % (
            doAlign, allStems, tempFI, tempBez)
        if options.debug:
            print command
        log = FDKUtils.runShellCmd(command)
        if log:
            print log

        if os.path.exists(tempReport):
            bp = open(tempReport, "rt")
            report = bp.read()
            bp.close()
            if options.debug:
                print "Wrote AC fontinfo data file to", tempFI
                print "Wrote AC output rpt file to", tempReport
            else:
                os.remove(tempReport)
            report.strip()
            if report:
                glyphReports.addGlyphReport(report)
                if options.debug:
                    rawData.append(report)
        else:
            print "Error - failure in processing outline data"
            report = None

    hStemDict, vStemDict, topZoneDict, bottomZoneDict = glyphReports.getReportDicts(
    )
    if options.reportPath:
        reportPath = options.reportPath
    else:
        reportPath = path
    PrintReports(reportPath, hStemDict, vStemDict, topZoneDict, bottomZoneDict)
    ttFont.close()
    logMsg("Done with font %s. End time: %s." % (path, time.asctime()))
예제 #37
0
파일: ProofPDF.py 프로젝트: brawer/afdko
def openFile(path, txPath):
	# If input font is  CFF or PS, build a dummy ttFont.
	tempPathCFF = None
	cffPath = None

	# If it is CID-keyed font, we need to convert it to a name-keyed font. This is a hack, but I really don't want to add CID support to
	# the very simple-minded PDF library.
	command="%s   -dump -0  \"%s\" 2>&1" % (txPath, path)
	report = FDKUtils.runShellCmd(command)
	if "CIDFontName" in report:
		tfd,tempPath1 = tempfile.mkstemp()
		os.close(tfd)
		command="%s   -t1 -decid -usefd 0  \"%s\" \"%s\" 2>&1" % (txPath, path, tempPath1)
		report = FDKUtils.runShellCmd(command)
		if "fatal" in report:
			logMsg(report)
			logMsg("Failed to convert CID-keyed font %s to a temporary Typ1 data file." % path)

		tfd,tempPathCFF = tempfile.mkstemp()
		os.close(tfd)
		command="%s   -cff +b  \"%s\" \"%s\" 2>&1" % (txPath, tempPath1, tempPathCFF)
		report = FDKUtils.runShellCmd(command)
		if "fatal" in report:
			logMsg(report)
			logMsg("Failed to convert CID-keyed font %s to a temporary CFF data file." % path)
		cffPath = tempPathCFF
		os.remove(tempPath1)
	elif os.path.isdir(path):
		# See if it is a UFO font by truing to dump it.
		command="%s   -dump -0  \"%s\" 2>&1" % (txPath, path)
		report = FDKUtils.runShellCmd(command)
		if not "sup.srcFontType" in report:
			logMsg(report)
			logMsg("Failed to open directory %s as a UFO font." % path)
			
		tfd,tempPathCFF = tempfile.mkstemp()
		os.close(tfd)
		command="%s   -cff +b  \"%s\" \"%s\" 2>&1" % (txPath, path, tempPathCFF)
		report = FDKUtils.runShellCmd(command)
		if "fatal" in report:
			logMsg(report)
			logMsg("Failed to convert ufo font %s to a temporary CFF data file." % path)
		cffPath = tempPathCFF
	else:
		try:
			ff = file(path, "rb")
			data = ff.read(10)
			ff.close()
		except (IOError, OSError):
			import traceback
			traceback.print_exc()
			raise FontError("Failed to open and read font file %s. Check file/directory permissions." % path)
		
		if len(data) < 10:
			raise FontError("Error: font file was zero size: may be a resource fork font, which this program does not process. <%s>." % path)
		if (data[:4] == "OTTO") or (data[:4] == "true") or (data[:4] == "\0\1\0\0"): # it is an OTF/TTF font, can process file directly
			try:
				ttFont = ttLib.TTFont(path)
			except (IOError, OSError):
				raise FontError("Error opening or reading from font file <%s>." % path)
			except TTLibError:
				raise FontError("Error parsing font file 333 <%s>." % path)
	
			if not (ttFont.has_key('CFF ') or ttFont.has_key('glyf')):
				raise FontError("Error: font is not a CFF or TrueType font <%s>." % path)
	
			return ttFont, tempPathCFF
	
		# It is not an OTF file.
		if (data[0] == '\1') and (data[1] == '\0'): # CFF file
			cffPath = path
		elif not "%" in data:
			#not a PS file either
			logMsg("Font file must be a PS, CFF or OTF  fontfile: %s." % path)
			raise FontError("Font file must be PS, CFF or OTF file: %s." % path)
	
		else:  # It is a PS file. Convert to CFF.	
			tfd,tempPathCFF = tempfile.mkstemp()
			os.close(tfd)
			cffPath = tempPathCFF
			command="%s   -cff +b  \"%s\" \"%s\" 2>&1" % (txPath, path, tempPathCFF)
			report = FDKUtils.runShellCmd(command)
			if "fatal" in report:
				logMsg("Attempted to convert font %s  from PS to a temporary CFF data file." % path)
				logMsg(report)
				raise FontError("Failed to convert PS font %s to a temp CFF font." % path)

	# now package the CFF font as an OTF font
	ff = file(cffPath, "rb")
	data = ff.read()
	ff.close()
	try:
		ttFont = ttLib.TTFont()
		cffModule = ttLib.getTableModule('CFF ')
		cffTable = cffModule.table_C_F_F_('CFF ')
		ttFont['CFF '] = cffTable
		cffTable.decompile(data, ttFont)
	except:
		import traceback
		traceback.print_exc()
		logMsg("Attempted to read font %s  as CFF." % path)
		raise FontError("Error parsing font file <%s>." % path)
	return ttFont, tempPathCFF
예제 #38
0
def proofMakePDF(pathList, params, txPath):
	#    use fontTools library to open font and extract CFF table. 
	#    If error, skip font and report error.
	if params.rt_doFontSet:
		pdfFontList = []
		logMsg("")
		logMsg( "Collecting font data from:")
		fontCount = 0
		for path in pathList:
			fontFileName = os.path.basename(path)
			params.rt_filePath = os.path.abspath(path)
			logMsg( "\t%s." % (path))
			try:
				ttFont, tempPathCFF = openFile(path, txPath)
			except FontError:
				print traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1]
				return
			try:
				fontGlyphList = ttFont.getGlyphOrder()
			except FontError:
				print traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1]
				return
		
		
			#   filter specified list, if any, with font list.
			glyphList = filterGlyphList(params, fontGlyphList, fontFileName)
			if not glyphList:
				raise FontError("Error: selected glyph list is empty for font <%s>." % fontFileName)
			params.rt_reporter = logMsg
		
			if ttFont.has_key("CFF "):
				pdfFont = otfPDF.txPDFFont(ttFont, params)
			elif ttFont.has_key("glyf"):
				pdfFont = ttfPDF.txPDFFont(ttFont, params)
			else:
				logMsg( "Quitting. Font type is not recognized. %s.." % (path))
				break
			if tempPathCFF:
				pdfFont.path = tempPathCFF
			pdfFontList.append([glyphList, pdfFont, tempPathCFF])
			
		pdfFilePath = makeFontSetPDF(pdfFontList,  params)
		for entry in pdfFontList:
			tempPathCFF =  entry[2]
			pdfFont = entry[1]
			pdfFont.clientFont.close()
			if tempPathCFF:
				os.remove(tempPathCFF)
		
			
		logMsg( "Wrote proof file %s. End time: %s." % (pdfFilePath, time.asctime()))
		if pdfFilePath and params.openPDFWhenDone:
			if curSystem == "Windows":
				curdir = os.getcwdu()
				basedir, pdfName = os.path.split(pdfFilePath)
				os.chdir(basedir)
				command = "start %s" % (pdfName)
				print command
				FDKUtils.runShellCmdLogging(command)
				os.chdir(curdir)
			elif os.name == "Linux":
				command = "xdg-open \"" + pdfFilePath  + "\"" + " &"
				FDKUtils.runShellCmdLogging(command)
			else:
				command = "open \"" + pdfFilePath  + "\"" + " &"
				FDKUtils.runShellCmdLogging(command)
	else:
		tmpList = []
		for path in pathList:
			fontFileName = os.path.basename(path)
			params.rt_filePath = os.path.abspath(path)
			logMsg("")
			logMsg( "Proofing font %s. Start time: %s." % (path, time.asctime()))
			try:
				ttFont, tempPathCFF = openFile(path, txPath)
				fontGlyphList = ttFont.getGlyphOrder()
			except FontError:
				print traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1]
				return
		
		
			#   filter specified list, if any, with font list.
			params.rt_glyphList = filterGlyphList(params, fontGlyphList, fontFileName)
			if not params.rt_glyphList:
				raise FontError("Error: selected glyph list is empty for font <%s>." % fontFileName)
			params.rt_reporter = logMsg
		
			if ttFont.has_key("CFF "):
				pdfFont = otfPDF.txPDFFont(ttFont, params)
			elif ttFont.has_key("glyf"):
				pdfFont = ttfPDF.txPDFFont(ttFont, params)
			else:
				logMsg( "Quitting. Font type is not recognized. %s.." % (path))
				return
			
			if tempPathCFF:
				pdfFont.path = tempPathCFF
			pdfFilePath = makePDF(pdfFont,  params)
			ttFont.close()
			if tempPathCFF:
				os.remove(tempPathCFF)
				
			logMsg( "Wrote proof file %s. End time: %s." % (pdfFilePath, time.asctime()))
			if pdfFilePath and params.openPDFWhenDone:
				if curSystem == "Windows":
					curdir = os.getcwdu()
					basedir, pdfName = os.path.split(pdfFilePath)
					os.chdir(basedir)
					command = "start %s" % (pdfName)
					print command
					FDKUtils.runShellCmdLogging(command)
					os.chdir(curdir)
				elif curSystem == "Linux":
					command = "xdg-open \"" + pdfFilePath  + "\"" + " &"
					print command
					FDKUtils.runShellCmdLogging(command)
				else:
					command = "open \"" + pdfFilePath  + "\"" + " &"
					FDKUtils.runShellCmdLogging(command)
예제 #39
0
def checkFile(path, options):
	#    use fontTools library to open font and extract CFF table. 
	#    If error, skip font and report error.
	seenChangedGlyph = 0
	fontFileName = os.path.basename(path)
	logMsg("Checking font %s. Start time: %s." % (path, time.asctime()))
	try:
		fontData = openFile(path, options.outFilePath, options.allowChanges)
		fontData.allowDecimalCoords = options.allowDecimalCoords
	except (IOError, OSError):
		logMsg( traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
		raise focusFontError("Error opening or reading from font file <%s>." % fontFileName)
	except:
		logMsg( traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
		raise focusFontError("Error parsing font file <%s>." % fontFileName)

	#   filter specified list, if any, with font list.
	fontGlyphList = fontData.getGlyphList()
	glyphList = filterGlyphList(options, fontGlyphList, fontFileName)
	if not glyphList:
		raise focusFontError("Error: selected glyph list is empty for font <%s>." % fontFileName)


	removeHints = 1
	reportCB = logMsg
	reportText = ""

	# If the user has not specified an em-square, and the font has am em-square other than 1000, supply it.
	if not options.emSquare:
		emSquare = fontData.getUnitsPerEm()
		if emSquare != "1000":
			options.emSquare = emSquare
			
	arg_string = buildArgString(options)
		
	dotCount = 0		
	seenGlyphCount = 0
	processedGlyphCount = 0
	for name in glyphList:
		seenGlyphCount +=1 
		if options.beVerbose:
			logMsg("Checking %s -- ," % ( aliasName(name) )) # output message when -v option is used
		else:
			logMsg(".,")
			dotCount += 1
			if dotCount > 40:
				dotCount = 0
				logMsg("") # I do this to never have more than 40 dots on a line.
				# This in turn give reasonable performance when calling checkOutlines in a subprocess
				# and getting output with std.readline()

		if os.path.exists(kTempFilepathOut):
			os.remove(kTempFilepathOut)
		
		# 	Convert to bez format
		bezString, width, hasHints = fontData.convertToBez(name, removeHints, options.beVerbose, options.checkAll)
		if bezString == None:
			continue
		processedGlyphCount += 1

		if "mt" not in bezString:
			# skip empty glyphs.
			continue
			
		# write bez file and run checkoutlinesexe
		fp = open(kTempFilepath, "wt")
		fp.write(bezString)
		fp.close()
		command = "checkoutlinesexe -o %s %s" % (arg_string, kTempFilepath)
		if debug:
			print "calling command", command
		log = FDKUtils.runShellCmd(command)
		# The suffix saying what bez file was written isn't useful here.
		log = re.sub(r"Wrote fixed file.+\s*", "", log)
		if log:
			if not options.beVerbose:
				dotCount = 0
				logMsg("")
				logMsg("Checking %s -- ," % (aliasName(name))) # output message when -v option is NOT used
				logMsg(log)
			else:
				logMsg(log)
		if  options.allowChanges and os.path.exists(kTempFilepathOut):
			fp = open(kTempFilepathOut, "rt")
			bezData = fp.read()
			fp.close()
			if bezData != bezString:
				fontData.updateFromBez(bezData, name, width, options.beVerbose)
				seenChangedGlyph = 1

	if not options.beVerbose:
		logMsg("")
	if seenChangedGlyph:
		# save fontFile.
		fontData.saveChanges()
	else:
		fontData.close()

	if processedGlyphCount != seenGlyphCount:
		logMsg("Skipped %s of %s glyphs." % (seenGlyphCount - processedGlyphCount, seenGlyphCount))
	logMsg("Done with font %s. End time: %s." % (path, time.asctime()))
	if debug:
		print "Temp bez file in", kTempFilepath
		print "Temp bez file out", kTempFilepathOut
	else:
		if os.path.exists(kTempFilepathOut):
			os.remove(kTempFilepathOut)
		if os.path.exists(kTempFilepath):
			os.remove(kTempFilepath)
		# remove temp file left over from openFile.
		tempPathCFF = path + kTempCFFSuffix
		if os.path.exists(tempPathCFF):
			os.remove(tempPathCFF)
예제 #40
0
파일: ProofPDF.py 프로젝트: zedmar/afdko
def openFile(path, txPath):
    # If input font is  CFF or PS, build a dummy ttFont.
    tempPathCFF = None
    try:
        ff = file(path, "rb")
        data = ff.read(10)
        ff.close()
    except (IOError, OSError):
        import traceback
        traceback.print_exc()
        raise FontError(
            "Failed to open and read font file %s. Check file/directory permissions."
            % path)

    if len(data) < 10:
        raise FontError(
            "Error: font file was zero size: may be a resource fork font, which this program does not process. <%s>."
            % path)

    if (data[:4] == "OTTO") or (data[:4] == "true") or (
            data[:4]
            == "\0\1\0\0"):  # it is an OTF/TTF font, can process file directly
        try:
            ttFont = ttLib.TTFont(path)
        except (IOError, OSError):
            raise FontError("Error opening or reading from font file <%s>." %
                            path)
        except TTLibError:
            raise FontError("Error parsing font file 333 <%s>." % path)

        if not (ttFont.has_key('CFF ') or ttFont.has_key('glyf')):
            raise FontError("Error: font is not a CFF or TrueType font <%s>." %
                            path)

        return ttFont, tempPathCFF

    # It is not an OTF file.
    if (data[0] == '\1') and (data[1] == '\0'):  # CFF file
        cffPath = path
    elif not "%" in data:
        #not a PS file either
        logMsg("Font file must be a PS, CFF or OTF  fontfile: %s." % path)
        raise FontError("Font file must be PS, CFF or OTF file: %s." % path)

    else:  # It is a PS file. Convert to CFF.
        tfd, tempPathCFF = tempfile.mkstemp()
        os.close(tfd)
        cffPath = tempPathCFF
        command = "%s   -cff +b  \"%s\" \"%s\" 2>&1" % (txPath, path,
                                                        tempPathCFF)
        report = FDKUtils.runShellCmd(command)
        if "fatal" in report:
            logMsg(
                "Attempted to convert font %s  from PS to a temporary CFF data file."
                % path)
            logMsg(report)
            raise FontError(
                "Failed to convert PS font %s to a temp CFF font." % path)

    # now package the CFF font as an OTF font for use by autohint.
    ff = file(cffPath, "rb")
    data = ff.read()
    ff.close()
    try:
        ttFont = ttLib.TTFont()
        cffModule = ttLib.getTableModule('CFF ')
        cffTable = cffModule.table_C_F_F_('CFF ')
        ttFont['CFF '] = cffTable
        cffTable.decompile(data, ttFont)
    except:
        import traceback
        traceback.print_exc()
        logMsg("Attempted to read font %s  as CFF." % path)
        raise FontError("Error parsing font file <%s>." % path)
    return ttFont, tempPathCFF
예제 #41
0
파일: autohint.py 프로젝트: henrich/afdko
def getOptions():
	global gLogFile
	options = ACOptions()
	i = 1
	numOptions = len(sys.argv)
	while i < numOptions:
		arg = sys.argv[i]
		if options.inputPath:
			raise ACOptionParseError("Option Error: All options must preceed the  input font path <%s>." % arg) 

		if arg == "-h":
			print __help__
			command = "autohintexe -v"
			report = FDKUtils.runShellCmd(command)
			logMsg( report)
			raise ACOptionParseError
		elif arg == "-u":
			print __usage__
			command = "autohintexe -v"
			report = FDKUtils.runShellCmd(command)
			logMsg( report)
			raise ACOptionParseError
		elif arg == "-hfd":
			print __FDDoc__
			raise ACOptionParseError
		elif arg == "-pfd":
			options.printDefaultFDDict = 1
		elif arg == "-pfdl":
			options.printFDDictList = 1
		elif arg == "-hf":
			options.usePlistFile = 1
		elif arg == "-a":
			options.hintAll = 1
		elif arg == "-all":
			options.hintAll = 1
		elif arg == "-r":
			options.rehint = 1
		elif arg == "-q":
			options.verbose = 0
		elif arg == "-c":
			options.allowChanges = 1
		elif arg == "-nf":
			options.noFlex = 1
		elif arg == "-ns":
			options.noHintSub = 1
		elif arg == "-nb":
			options.allow_no_blues = 1
		elif arg in ["-xg", "-g"]:
			if arg == "-xg":
				options.excludeGlyphList = 1
			i = i +1
			glyphString = sys.argv[i]
			if glyphString[0] == "-":
				raise ACOptionParseError("Option Error: it looks like the first item in the glyph list following '-g' is another option.") 
			options.glyphList += parseGlyphListArg(glyphString)
		elif arg in ["-xgf", "-gf"]:
			if arg == "-xgf":
				options.excludeGlyphList = 1
			i = i +1
			filePath = sys.argv[i]
			if filePath[0] == "-":
				raise ACOptionParseError("Option Error: it looks like the the glyph list file following '-gf' is another option.") 
			try:
				gf = file(filePath, "rt")
				glyphString = gf.read()
				gf.close()
			except (IOError,OSError):
				raise ACOptionParseError("Option Error: could not open glyph list file <%s>." %  filePath) 
			options.glyphList += parseGlyphListArg(glyphString)
		elif arg == "-cf":
			i = i +1
			filePath = sys.argv[i]
			if filePath[0] == "-":
				raise ACOptionParseError("Option Error: it looks like the the counter hint glyph list file following '-cf' is another option.") 
			try:
				options.counterHintFile = filePath
				options.hCounterGlyphs, options.vCounterGlyphs = parseCounterHintData(filePath)
			except (IOError,OSError):
				raise ACOptionParseError("Option Error: could not open counter hint glyph list  file <%s>." %  filePath) 
		elif arg == "-logOnly":
			options.logOnly = 1
		elif arg == "-log":
			i = i +1
			options.logFilePath = sys.argv[i]
			gLogFile = open(options.logFilePath, "wt")
		elif arg == "-o":
			i = i +1
			options.outputPath = sys.argv[i]
		elif arg == "-d":
			options.debug = 1
		elif arg == "-decimal":
			options.allowDecimalCoords = True
		elif arg =="-wd":
			options.writeToDefaultLayer = 1
		elif arg[0] == "-":
			raise ACOptionParseError("Option Error: Unknown option <%s>." %  arg) 
		else:
			options.inputPath = arg
		i  += 1
	if not options.inputPath:
		raise ACOptionParseError("Option Error: You must provide a font file path.") 

	if not os.path.exists(options.inputPath):
		raise ACOptionParseError("Option Error: The input font file path %s' does not exist." % (options.inputPath)) 
	else:
		options.inputPath = options.inputPath.rstrip(os.sep) # might be a UFO font. auto completion in some shells adds a dir separator, which then causes problems with os.path.dirname().

	checkFontinfoFile(options)
	
	if options.logOnly:
		options.verbose = 1
		options.hintAll = 1
		
	return options
예제 #42
0
def openFile(path, txPath):
    # If input font is  CFF or PS, build a dummy ttFont in memory for use by AC.
    # return ttFont, and flag if is a real OTF font Return flag is 0 if OTF, 1 if CFF, and 2 if PS/
    fontType = 0  # OTF
    tempPath = os.path.dirname(path)
    tempPathBase = os.path.join(tempPath, "temp.ac")
    tempPathCFF = tempPathBase + ".cff"
    try:
        ff = file(path, "rb")
        data = ff.read(10)
        ff.close()
    except (IOError, OSError):
        logMsg("Failed to open and read font file %s." % path)

    if data[:4] == "OTTO":  # it is an OTF font, can process file directly
        try:
            ttFont = TTFont(path)
        except (IOError, OSError):
            raise ACFontError("Error opening or reading from font file <%s>." %
                              path)
        except TTLibError:
            raise ACFontError("Error parsing font file <%s>." % path)

        try:
            cffTable = ttFont["CFF "]
        except KeyError:
            raise ACFontError("Error: font is not a CFF font <%s>." %
                              fontFileName)

        return ttFont, fontType

    # It is not an OTF file.
    if (data[0] == '\1') and (data[1] == '\0'):  # CFF file
        fontType = 1
        tempPathCFF = path
    elif not "%" in data:
        #not a PS file either
        logMsg("Font file must be a PS, CFF or OTF  fontfile: %s." % path)
        raise ACFontError("Font file must be PS, CFF or OTF file: %s." % path)

    else:  # It is a PS file. Convert to CFF.
        fontType = 2
        command = "%s   -cff +b  \"%s\" \"%s\" 2>&1" % (txPath, path,
                                                        tempPathCFF)
        report = FDKUtils.runShellCmd(command)
        if "fatal" in report:
            logMsg(
                "Attempted to convert font %s  from PS to a temporary CFF data file."
                % path)
            logMsg(report)
            raise ACFontError(
                "Failed to convert PS font %s to a temp CFF font." % path)

    # now package the CFF font as an OTF font for use by AC.
    ff = file(tempPathCFF, "rb")
    data = ff.read()
    ff.close()
    try:
        ttFont = TTFont()
        cffModule = getTableModule('CFF ')
        cffTable = cffModule.table_C_F_F_('CFF ')
        ttFont['CFF '] = cffTable
        cffTable.decompile(data, ttFont)
    except:
        import traceback
        traceback.print_exc()
        logMsg("Attempted to read font %s  as CFF." % path)
        raise ACFontError("Error parsing font file <%s>." % fontFileName)

    # Delete the temporary temp.ac.cff file
    if os.path.exists(tempPathCFF):
        os.remove(tempPathCFF)

    return ttFont, fontType
예제 #43
0
파일: autohint.py 프로젝트: NuttShell/afdko
def hintFile(options):

	path = options.inputPath
	fontFileName = os.path.basename(path)
	logMsg("Hinting font %s. Start time: %s." % (path, time.asctime()))

	try:
		useHashMap = not options.logOnly # for UFO fonts only. We always use the hash map, unless the user has said to only report issues.
		fontData = openFile(path, options.outputPath, useHashMap)
		fontData.allowDecimalCoords = options.allowDecimalCoords
	except (IOError, OSError):
		logMsg( traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
		raise ACFontError("Error opening or reading from font file <%s>." % fontFileName)
	except:
		logMsg( traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
		raise ACFontError("Error parsing font file <%s>." % fontFileName)

	#   filter specified list, if any, with font list.
	fontGlyphList = fontData.getGlyphList()
	glyphList = filterGlyphList(options, fontGlyphList, fontFileName)
	if not glyphList:
		raise ACFontError("Error: selected glyph list is empty for font <%s>." % fontFileName)

	# temp file names for input and output bez files, and for the fontinfo file.
	tempBaseName = os.tempnam()
	tempBez = tempBaseName + ".bez"
	tempBezNew = tempBez + ".new"
	tempFI = tempBaseName + ".fi"
	
	#print "tempBaseName", tempBaseName
	psName = fontData.getPSName()
	
	if (not options.logOnly) and options.usePlistFile:
		fontPlist, fontPlistFilePath, isNewPlistFile = openFontPlistFile(psName, os.path.dirname(path))
		if isNewPlistFile and  not (options.hintAll or options.rehint):
			logMsg("No hint info plist file was found, so all glyphs are unknown to autohint. To hint all glyphs, run autohint again with option -a to hint all glyphs unconditionally.")
			logMsg("Done with font %s. End time: %s." % (path, time.asctime()))
			fontData.close()
			return

	# Check counter glyphs, if any.
	if options.hCounterGlyphs or options.vCounterGlyphs:
		missingList = filter(lambda name: name not in fontGlyphList, options.hCounterGlyphs + options.vCounterGlyphs)
		if missingList:
			logMsg( "\tError: glyph named in counter hint list file '%s' are not in font: %s" % (options.counterHintFile, missingList) )

	#    build alignment zone string
	if (options.printDefaultFDDict):
		logMsg("Showing default FDDict Values:")
		fdDict = fontData.getFontInfo(psName, path, options.allow_no_blues, options.noFlex, options.vCounterGlyphs, options.hCounterGlyphs)
		parseFontInfoString(str(fdDict))
		fontData.close()
		return

	fdGlyphDict, fontDictList = fontData.getfdInfo(psName, path, options.allow_no_blues, options.noFlex, options.vCounterGlyphs, options.hCounterGlyphs, glyphList)

	if options.printFDDictList:
		# Print the user defined FontDicts, and exit.
		if fdGlyphDict:
			logMsg("Showing user-defined FontDict Values:")
			for fi in range(len(fontDictList)):
				fontDict = fontDictList[fi]
				logMsg("")
				logMsg(fontDict.DictName)
				parseFontInfoString(str(fontDict))
				gnameList = []
				itemList = fdGlyphDict.items()
				itemList.sort(cmpFDDictEntries)
				for gName, entry in itemList:
					if entry[0] == fi:
						gnameList.append(gName)
				logMsg("%d glyphs:" % len(gnameList))
				if len(gnameList) > 0:
					gTxt = " ".join(gnameList)
				else:
					gTxt = "None"
				logMsg(gTxt)
		else:
			logMsg("There are no user-defined FontDict Values.")
		tempPathCFF = options.inputPath + kTempCFFSuffix
		removeTempFiles( [tempPathCFF] )
		fontData.close()
		return
		
	if fdGlyphDict == None:
		fdDict = fontDictList[0]
		fp = open(tempFI, "wt")
		fp.write(fdDict.getFontInfo())
		fp.close()
	else:
		if not options.verbose:
			logMsg("Note: Using alternate FDDict global values from fontinfo file for some glyphs. Remove option '-q' to see which dict is used for which glyphs.")


	#    for identifier in glyph-list:
	# 	Get charstring.
	removeHints = 1
	isCID = fontData.isCID()
	lastFDIndex = None
	reportCB = ACreport
	anyGlyphChanged = 0
	pListChanged = 0
	if isCID:
		options.noFlex = 1
		
	if options.verbose:
		verboseArg = ""
	else:
		verboseArg = " -q" 
		dotCount = 0
		curTime = time.time()

	if options.allowChanges:
		suppressEditArg = ""
	else:
		suppressEditArg = " -e"

	if options.noHintSub:
		supressHintSubArg = " -n"
	else:
		supressHintSubArg = ""

	if options.allowDecimalCoords:
		decimalArg = " -d"
	else:
		decimalArg = ""

	dotCount = 0
	seenGlyphCount = 0
	processedGlyphCount = 0
	for name in glyphList:
		prevACIdentifier = None
		seenGlyphCount +=1
			
		# 	Convert to bez format
		bezString, width = fontData.convertToBez(name, removeHints, options.verbose, options.hintAll)
		processedGlyphCount += 1
		if bezString == None:
			continue

		if "mt" not in bezString:
			# skip empty glyphs.
			continue
		# get new fontinfo string if FD array index has changed, as
		# as each FontDict has different alignment zones.
		gid = fontData.getGlyphID(name)
		if isCID: #
			fdIndex = fontData.getfdIndex(gid)
			if not fdIndex == lastFDIndex:
				lastFDIndex = fdIndex
				fdDict = fontData.getFontInfo(psName, path, options.allow_no_blues, options.noFlex, options.vCounterGlyphs, options.hCounterGlyphs, fdIndex)
				fp = open(tempFI, "wt")
				fp.write(fdDict.getFontInfo())
				fp.close()
		else:
			if (fdGlyphDict != None):
				try:
					fdIndex = fdGlyphDict[name][0]
				except KeyError:
					# use default dict.
					fdIndex = 0
				if lastFDIndex != fdIndex:
					lastFDIndex = fdIndex
					fdDict = fontDictList[fdIndex]
					fp = open(tempFI, "wt")
					fp.write(fdDict.getFontInfo())
					fp.close()
			

		# 	Build autohint point list identifier

		oldBezString = ""
		oldHintBezString = ""
		
		if (not options.logOnly) and options.usePlistFile:
			# If the glyph is not in the  plist file, then we skip it unless kReHintUnknown is set.
			# If the glyph is in the plist file and the outline has changed, we hint it. 
			ACidentifier = makeACIdentifier(bezString)
			try:
				(prevACIdentifier, ACtime, oldBezString, oldHintBezString) =  fontPlist[kACIDKey][name]
			except ValueError:
				(prevACIdentifier, ACtime) =  fontPlist[kACIDKey][name]
				oldBezString = oldHintBezString = ""
			except KeyError:
				pListChanged = 1 # Didn't have an entry in tempList file, so we will add one.
				if hasHints and not (options.rehint):
					# Glyphs is hinted, but not referenced in the plist file. Skip it unless options.rehint is se
					if  not isNewPlistFile:
						# Comment only if there is a plist file; otherwise, we'd be complaining for almost every glyph.
						logMsg("%s Skipping glyph - it has hints, but it is not in the hint info plist file." % aliasName(name))
						dotCount = 0
					continue

			if prevACIdentifier and (prevACIdentifier == ACidentifier): # there is an entry in the plist file and it matches what's in the font.
				if hasHints and not options.hintAll:
					continue
			else:
				pListChanged = 1

		if options.verbose:
			if fdGlyphDict:
				logMsg("Hinting %s with fdDict %s." % (aliasName(name), fdDict.DictName) )
			else:
				logMsg("Hinting %s." % aliasName(name))
		else:
			logMsg(".,")
			dotCount += 1
			if dotCount > 40:
				dotCount = 0
				logMsg("") # I do this to never have more than 40 dots on a line.
				# This in turn give reasonable performance when calling autohint in a subprocess
				# and getting output with std.readline()

		# 	Call auto-hint library on bez string.
		bp = open(tempBez, "wt")
		bp.write(bezString)
		bp.close()

		#print "oldBezString", oldBezString
		#print ""
		#print "bezString", bezString
		
		if oldBezString != "" and oldBezString == bezString:
			newBezString = oldHintBezString
		else:
			if os.path.exists(tempBezNew):
				os.remove(tempBezNew)
			command = "autohintexe %s%s%s%s -s .new -f \"%s\" \"%s\"" % (verboseArg, suppressEditArg, supressHintSubArg, decimalArg, tempFI, tempBez)
			if  options.debug:
				print command
			report = FDKUtils.runShellCmd(command)
			if report:
				if not options.verbose:
					logMsg("") # end series of "."
				logMsg(report)
			if os.path.exists(tempBezNew):
				bp = open(tempBezNew, "rt")
				newBezString = bp.read()
				bp.close()
				if options.debug:
					print "Wrote AC fontinfo data file to", tempFI
					print "Wrote AC output bez file to", tempBezNew
				else:
					os.remove(tempBezNew)
			else:
				newBezString = None
			
		if not newBezString:
			if not options.verbose:
				logMsg("")
			logMsg("%s Error - failure in processing outline data." % aliasName(name))
			continue
			
		if not (("ry" in newBezString[:200]) or ("rb" in newBezString[:200]) or ("rm" in newBezString[:200]) or ("rv" in newBezString[:200])):
			print "No hints added!"

		if options.logOnly:
			continue
			
		# 	Convert bez to charstring, and update CFF.
		anyGlyphChanged = 1
		fontData.updateFromBez(newBezString, name, width, options.verbose)

		
		if options.usePlistFile:
			bezString, hasHints, t2Wdth = convertT2GlyphToBez(t2CharString, 1)
			bezString = "%% %s%s%s" % (name, os.linesep, bezString)
			ACidentifier = makeACIdentifier(bezString)
			# add glyph hint entry to plist file
			if options.allowChanges:
				if prevACIdentifier and (prevACIdentifier != ACidentifier):
					logMsg("\t%s Glyph outline changed" % aliasName(name))
					dotCount = 0

			fontPlist[kACIDKey][name] = (ACidentifier, time.asctime(), bezString, newBezString )

	if not options.verbose:
		print "" # print final new line after progress dots.

	if  options.debug:
		print "Wrote input AC bez file to", tempBez
	else:
		tempPathCFF = options.inputPath + kTempCFFSuffix # created when a PS file is opened.
		removeTempFiles( [tempBez, tempBezNew, tempFI, tempPathCFF] )
					
	if not options.logOnly:
		if anyGlyphChanged:
			logMsg("Saving font file with new hints..." + time.asctime())
			fontData.saveChanges()
		else:
			fontData.close()
			if options.usePlistFile:
				if options.rehint:
					logMsg("No new hints. All glyphs had hints that matched the hint record file %s." % (fontPlistFilePath))
				else:
					logMsg("No new hints. All glyphs were already hinted.")
			else:
				logMsg("No glyphs were hinted.")
	if options.usePlistFile and (anyGlyphChanged or pListChanged):
		#  save font plist file.
		fontPlist.write(fontPlistFilePath)
	if processedGlyphCount != seenGlyphCount:
		logMsg("Skipped %s of %s glyphs." % (seenGlyphCount - processedGlyphCount, seenGlyphCount))
	logMsg("Done with font %s. End time: %s." % (path, time.asctime()))
예제 #44
0
파일: StemHist.py 프로젝트: blakejia/afdko
def collectStemsFont(path, options, txPath):
	#    use fontTools library to open font and extract CFF table. 
	#    If error, skip font and report error.
	fontFileName = os.path.basename(path)
	logMsg("")
	if options.doAlign:
		logMsg( "Collecting alignment zones for font %s. Start time: %s." % (path, time.asctime()))
	else:
		logMsg( "Collecting stems for font %s. Start time: %s." % (path, time.asctime()))

	try:
		fontData = openFile(path)
	except (IOError, OSError):
		logMsg( traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
		raise ACFontError("Error opening or reading from font file <%s>." % fontFileName)
	except:
		logMsg( traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
		raise ACFontError("Error parsing font file <%s>." % fontFileName)

	#   filter specified list, if any, with font list.
	fontGlyphList = fontData.getGlyphList()
	glyphList = filterGlyphList(options, fontGlyphList, fontFileName)
	if not glyphList:
		raise ACFontError("Error: selected glyph list is empty for font <%s>." % fontFileName)

	tempBaseName = os.tempnam()
	tempBez = tempBaseName + ".bez"
	tempReport = tempBez + ".rpt"
	tempFI = tempBaseName + ".fi"
	
	#    open font plist file, if any. If not, create empty font plist.
	psName = fontData.getPSName()
	
	#    build alignment zone string
	allow_no_blues =  1
	noFlex = 0
	vCounterGlyphs = hCounterGlyphs = []
	fdGlyphDict, fontDictList = fontData.getfdInfo(psName, path, allow_no_blues, noFlex, vCounterGlyphs, hCounterGlyphs, glyphList)

	if fdGlyphDict == None:
		fdDict = fontDictList[0]
		fp = open(tempFI, "wt")
		fp.write(fdDict.getFontInfo())
		fp.close()
	else:
		if not options.verbose:
			logMsg("Note: Using alternate FDDict global values from fontinfo file for some glyphs. Remove option '-q' to see which dict is used for which glyphs.")

	removeHints = 1
	isCID = fontData.isCID()
	lastFDIndex = None
	glyphReports = GlyphReports()

	if not options.verbose:
		dotCount = 0
		curTime = time.time()

	for name in glyphList:
		if name == ".notdef":
			continue

		if options.verbose:
			logMsg("Checking %s." %name)
		else:
			newTime = time.time()
			if (newTime - curTime) > 1:
				print ".",
				sys.stdout.flush()
				curTime = newTime
				dotCount +=1
			if dotCount > 40:
				dotCount = 0
				print ""

		# 	Convert to bez format
		bezString, width, hasHints = fontData.convertToBez(name, removeHints, options.verbose)
		if bezString == None:
			continue
		if "mt" not in bezString:
			# skip empty glyphs.
			continue

		# get new fontinfo string if FD array index has changed, as
		# as each FontDict has different alignment zones.
		gid = fontData.getGlyphID(name)
		if isCID: #
			fdIndex = fontData.getfdIndex(gid)
			if not fdIndex == lastFDIndex:
				lastFDIndex = fdIndex
				fdDict = fontData.getFontInfo(psName, path, options.allow_no_blues, options.noFlex, options.vCounterGlyphs, options.hCounterGlyphs, fdIndex)
				fp = open(tempFI, "wt")
				fp.write(fdDict.getFontInfo())
				fp.close()
		else:
			if (fdGlyphDict != None):
				try:
					fdIndex = fdGlyphDict[name][0]
				except KeyError:
					# use default dict.
					fdIndex = 0
				if lastFDIndex != fdIndex:
					lastFDIndex = fdIndex
					fdDict = fontDictList[fdIndex]
					fp = open(tempFI, "wt")
					fp.write(fdDict.getFontInfo())
					fp.close()
		
		glyphReports.startGlyphName(name)
		

		# 	Call auto-hint library on bez string.
		bp = open(tempBez, "wt")
		bp.write(bezString)
		bp.close()

		if os.path.exists(tempReport):
			os.remove(tempReport)
		if options.doAlign:
			doAlign = "-ra"
		else:
			doAlign = "-rs"
			
		if options.allStems:
			allStems = "-a"
		else:
			allStems = ""
			
		command = "autohintexe -q %s %s  -f \"%s\" \"%s\" 2>&1" % (doAlign, allStems, tempFI, tempBez)
		if options.debug:
			print command
		log = FDKUtils.runShellCmd(command)
		if log:
			print log
			if "number terminator while" in log:
				print tempBez
				sys.exit()
 
		if os.path.exists(tempReport):
			bp = open(tempReport, "rt")
			report = bp.read()
			bp.close()
			print "report <%s>" % (report)
			if options.debug:
				print "Wrote AC fontinfo data file to", tempFI
				print "Wrote AC output rpt file to", tempReport
			else:
				os.remove(tempReport)
			report.strip()
			if report:
				glyphReports.addGlyphReport(report)
				if options.debug:
					rawData.append(report)
		else:
			print "Error - failure in processing outline data"
			report = None
			
	hStemDict, vStemDict,topZoneDict, bottomZoneDict = glyphReports.getReportDicts()
	if options.reportPath:
		reportPath = options.reportPath
	else:
		reportPath = path
	PrintReports(reportPath, hStemDict, vStemDict,topZoneDict, bottomZoneDict)
	fontData.close()
	logMsg( "Done with font %s. End time: %s." % (path, time.asctime()))
예제 #45
0
def checkFile(path, options, txPath):
    #    use fontTools library to open font and extract CFF table.
    #    If error, skip font and report error.
    seenChangedGlyph = 0
    fontFileName = os.path.basename(path)
    logMsg("Checking font %s. Start time: %s." % (path, time.asctime()))
    try:
        ttFont, fontType = openFile(path, txPath)
        fontGlyphList = ttFont.getGlyphOrder()
    except (IOError, OSError):
        logMsg(
            traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
        raise focusFontError("Error opening or reading from font file <%s>." %
                             fontFileName)
    except:
        logMsg(
            traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1])
        raise focusFontError("Error parsing font file <%s>." % fontFileName)

    try:
        cffTable = ttFont["CFF "]
        topDict = cffTable.cff.topDictIndex[0]
    except KeyError:
        raise focusFontError("Error: font is not a CFF font <%s>." %
                             fontFileName)

    #   filter specified list, if any, with font list.
    glyphList = filterGlyphList(options, fontGlyphList, fontFileName)
    if not glyphList:
        raise focusFontError(
            "Error: selected glyph list is empty for font <%s>." %
            fontFileName)

    #    for identifier in glyph-list:
    # 	Get charstring.
    charStrings = topDict.CharStrings
    charStringIndex = charStrings.charStringsIndex
    removeHints = 1
    isCID = hasattr(topDict, "FDSelect")
    lastFDIndex = 0
    reportCB = logMsg
    reportText = ""

    # If the user has not specified an em-square, and the font has am em-square other than 1000, supply it.
    if not options.emSquare:
        if hasattr(topDict, "FontMatrix"):
            matrix = topDict.FontMatrix
            emSquare = "%s" % (int(round(1.0 / matrix[0])))
            if emSquare != "1000":
                options.emSquare = emSquare

    arg_string = buildArgString(options)

    dotCount = 0
    for name in glyphList:
        if options.beVerbose:
            logMsg("Checking %s -- ," %
                   (aliasName(name)))  # output message when -v option is used
        else:
            logMsg(".,")
            dotCount += 1
            if dotCount > 40:
                dotCount = 0
                logMsg(
                    "")  # I do this to never have more than 40 dots on a line.
                # This in turn give reasonable performance when calling checkOutlines in a subprocess
                # and getting output with std.readline()

        if os.path.exists(kTempFilepathOut):
            os.remove(kTempFilepathOut)

        # 	Convert to bez format
        gid = charStrings.charStrings[name]
        t2CharString = charStringIndex[gid]
        try:
            bezString, hasHints, t2Wdth = convertT2GlyphToBez(
                t2CharString, removeHints)
        except SEACError:
            if not options.beVerbose:
                dotCount = 0
                logMsg("")  # end series of "."
                logMsg("Checking %s -- ," % (aliasName(name))
                       )  # output message when SEAC glyph is found
            logMsg("Skipping %s: can't process SEAC composite glyphs." %
                   (aliasName(name)))
            continue  # skip SEAC composite glyphs.
        fp = open(kTempFilepath, "wt")
        fp.write(bezString)
        fp.close()
        command = "outlineCheck -o %s %s" % (arg_string, kTempFilepath)
        if debug:
            print "calling command", command
        log = FDKUtils.runShellCmd(command)
        # The suffix saying what bez file was written isn't useful here.
        log = re.sub(r"Wrote fixed file.+\s*", "", log)
        if log:
            if not options.beVerbose:
                dotCount = 0
                logMsg("")
                logMsg("Checking %s -- ," % (aliasName(name))
                       )  # output message when -v option is NOT used
                logMsg(log)
            else:
                logMsg(log)
        if options.allowChanges and os.path.exists(kTempFilepathOut):
            fp = open(kTempFilepathOut, "rt")
            bezData = fp.read()
            fp.close()
            if bezData != bezString:
                t2Program = [t2Wdth] + convertBezToT2(bezData)
                if t2Program:
                    t2CharString.program = t2Program
                else:
                    if not options.beVerbose:
                        dotCount = 0
                        logMsg("")  # end series of "."
                        logMsg("Checking %s -- ," % (aliasName(name)))
                    logMsg("Skipping %s: error in processing fixed outline." %
                           (aliasName(name)))
            seenChangedGlyph = 1

    if not options.beVerbose:
        logMsg("")
    if seenChangedGlyph:
        # save fontFile.
        logMsg("Writing changed file %s" % (options.outFilePath))
        saveFontFile(ttFont, path, options.outFilePath, fontType, txPath)

    logMsg("Done with font %s. End time: %s." % (path, time.asctime()))
    if debug:
        print "Temp bez file in", kTempFilepath
        print "Temp bez file out", kTempFilepathOut
    else:
        if os.path.exists(kTempFilepathOut):
            os.remove(kTempFilepathOut)
        if os.path.exists(kTempFilepath):
            os.remove(kTempFilepath)
        # remove temp file left over from openFile.
        tempPathCFF = path + kTempCFFSuffix
        if os.path.exists(tempPathCFF):
            os.remove(tempPathCFF)
예제 #46
0
파일: ProofPDF.py 프로젝트: brawer/afdko
def proofMakePDF(pathList, params, txPath):
	#    use fontTools library to open font and extract CFF table. 
	#    If error, skip font and report error.
	if params.rt_doFontSet:
		pdfFontList = []
		logMsg("")
		logMsg( "Collecting font data from:")
		fontCount = 0
		for path in pathList:
			fontFileName = os.path.basename(path)
			params.rt_filePath = os.path.abspath(path)
			logMsg( "\t%s." % (path))
			try:
				ttFont, tempPathCFF = openFile(path, txPath)
			except FontError:
				print traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1]
				return
			try:
				fontGlyphList = ttFont.getGlyphOrder()
			except FontError:
				print traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1]
				return
		
		
			#   filter specified list, if any, with font list.
			glyphList = filterGlyphList(params, fontGlyphList, fontFileName)
			if not glyphList:
				raise FontError("Error: selected glyph list is empty for font <%s>." % fontFileName)
			params.rt_reporter = logMsg
		
			if ttFont.has_key("CFF "):
				pdfFont = otfPDF.txPDFFont(ttFont, params)
			elif ttFont.has_key("glyf"):
				pdfFont = ttfPDF.txPDFFont(ttFont, params)
			else:
				logMsg( "Quitting. Font type is not recognized. %s.." % (path))
				break
			if tempPathCFF:
				pdfFont.path = tempPathCFF
			pdfFontList.append([glyphList, pdfFont, tempPathCFF])
			
		pdfFilePath = makeFontSetPDF(pdfFontList,  params)
		for entry in pdfFontList:
			tempPathCFF =  entry[2]
			pdfFont = entry[1]
			pdfFont.clientFont.close()
			if tempPathCFF:
				os.remove(tempPathCFF)
		
			
		logMsg( "Wrote proof file %s. End time: %s." % (pdfFilePath, time.asctime()))
		if pdfFilePath and params.openPDFWhenDone:
			if curSystem == "Windows":
				curdir = os.getcwdu()
				basedir, pdfName = os.path.split(pdfFilePath)
				os.chdir(basedir)
				command = "start %s" % (pdfName)
				print command
				FDKUtils.runShellCmdLogging(command)
				os.chdir(curdir)
			elif os.name == "Linux":
				command = "xdg-open \"" + pdfFilePath  + "\"" + " &"
				FDKUtils.runShellCmdLogging(command)
			else:
				command = "open \"" + pdfFilePath  + "\"" + " &"
				FDKUtils.runShellCmdLogging(command)
	else:
		tmpList = []
		for path in pathList:
			fontFileName = os.path.basename(path)
			params.rt_filePath = os.path.abspath(path)
			logMsg("")
			logMsg( "Proofing font %s. Start time: %s." % (path, time.asctime()))
			try:
				ttFont, tempPathCFF = openFile(path, txPath)
				fontGlyphList = ttFont.getGlyphOrder()
			except FontError:
				print traceback.format_exception_only(sys.exc_type, sys.exc_value)[-1]
				return
		
		
			#   filter specified list, if any, with font list.
			params.rt_glyphList = filterGlyphList(params, fontGlyphList, fontFileName)
			if not params.rt_glyphList:
				raise FontError("Error: selected glyph list is empty for font <%s>." % fontFileName)
			params.rt_reporter = logMsg
		
			if ttFont.has_key("CFF "):
				pdfFont = otfPDF.txPDFFont(ttFont, params)
			elif ttFont.has_key("glyf"):
				pdfFont = ttfPDF.txPDFFont(ttFont, params)
			else:
				logMsg( "Quitting. Font type is not recognized. %s.." % (path))
				return
			
			if tempPathCFF:
				pdfFont.path = tempPathCFF
			pdfFilePath = makePDF(pdfFont,  params)
			ttFont.close()
			if tempPathCFF:
				os.remove(tempPathCFF)
				
			logMsg( "Wrote proof file %s. End time: %s." % (pdfFilePath, time.asctime()))
			if pdfFilePath and params.openPDFWhenDone:
				if curSystem == "Windows":
					curdir = os.getcwdu()
					basedir, pdfName = os.path.split(pdfFilePath)
					os.chdir(basedir)
					command = "start %s" % (pdfName)
					print command
					FDKUtils.runShellCmdLogging(command)
					os.chdir(curdir)
				elif curSystem == "Linux":
					command = "xdg-open \"" + pdfFilePath  + "\"" + " &"
					print command
					FDKUtils.runShellCmdLogging(command)
				else:
					command = "open \"" + pdfFilePath  + "\"" + " &"
					FDKUtils.runShellCmdLogging(command)
예제 #47
0
def fixFontDict(tempPath, fdDict):

    txtPath = tempPath + ".txt"
    command = "detype1 %s %s 2>&1" % (tempPath, txtPath)
    log = FDKUtils.runShellCmd(command)
    if log:
        print log
    fp = open(txtPath, "rt")
    data = fp.read()
    fp.close()

    # fix font name.
    # We always search of it, as it is always present, and we can use the following
    # white space to get the file new line.
    m = re.search(r"(/FontName\s+/\S+\s+def)(\s+)", data)
    newLine = m.group(2)
    if not m:
        raise FontParseError("Failed to find FontName in input font!. %s" %
                             (tempPath))
    if fdDict.FontName:
        target = "/FontName /%s def" % (fdDict.FontName)
        data = data[:m.start(1)] + target + data[m.end(1):]

    # fix em square
    if fdDict.OrigEmSqUnits:
        m = re.search(r"/FontMatrix\s+\[.+?\]\s+def", data)
        if not m:
            raise FontParseError(
                "Failed to find FontMatrix in input font! %s" % (tempPath))
        emUnits = eval(fdDict.OrigEmSqUnits)
        a = 1.0 / emUnits
        target = "/FontMatrix [%s 0 0 %s 0 0] def" % (a, a)
        data = data[:m.start()] + target + data[m.end():]

    # fix StemSnapH.  Remove StemSnapH if fdDict.StemSnapH is not defined, else set it.
    m = re.search(r"/StemSnapH\s+\[.+?\]\s+def", data)
    if fdDict.DominantH:
        target = "/StemSnapH %s def" % (fdDict.DominantH)
        data = data[:m.start()] + target + data[m.end():]
        insertIndex = m.start() + len(target)
    else:
        data = data[:m.start()] + data[m.end():]

    # fix StemSnapV.  Remove StemSnapV entry if fdDict.StemSnapV is not defined, else set it.
    m = re.search(r"/StemSnapV\s+\[.+?\]\s+def", data)
    if fdDict.DominantV:
        target = "/StemSnapV %s def" % (fdDict.DominantV)
        data = data[:m.start()] + target + data[m.end():]
        insertIndex = m.start() + len(target)
    else:
        data = data[:m.start()] + data[m.end():]

    # LanguageGroup. Remove LanguageGroup entry if fdDict.LanguageGroup is not defined, else set it.
    if fdDict.LanguageGroup:
        m = re.search(r"/LanguageGroup\s+\d+\s+def", data)
        if not m:
            target = "%s/LanguageGroup %s def" % (newLine,
                                                  fdDict.LanguageGroup)
            data = data[:insertIndex] + data[insertIndex] + target + data[
                insertIndex:]
        else:
            data = data[:m.start()] + target + data[m.end():]
        target = "/LanguageGroup %s def" % (fdDict.LanguageGroup)
    else:
        m = re.search(r"/LanguageGroup\s+\d+\s+def", data)
        if m:
            data = data[:m.start()] + data[m.end():]

    # Fix BlueValues. Must be present.
    m = re.search(r"/BlueValues\s+\[.+?\]\s+def", data)
    if not m:
        raise FontParseError("Failed to find BlueValues in input font! %s" %
                             (tempPath))
    target = "/BlueValues %s def" % (fdDict.BlueValues)
    data = data[:m.start()] + target + data[m.end():]
    insertIndex = m.start() + len(target)

    # Fix OtherBlues, if present. Remove if there are no OtherBlues entry.
    m = re.search(r"/OtherBlues\s+\[.+?\]\s+def", data)
    if fdDict.OtherBlues:
        if not m:
            target = "%s/OtherBlues %s def" % (newLine, fdDict.OtherBlues)
            data = data[:insertIndex] + target + data[insertIndex:]
        else:
            target = "/OtherBlues %s def" % (fdDict.OtherBlues)
            data = data[:m.start()] + target + data[m.end():]
    else:
        data = data[:m.start()] + data[m.end():]

    fp = open(txtPath, "wt")
    fp.write(data)
    fp.close()

    command = "type1 %s %s 2>&1" % (txtPath, tempPath)
    log = FDKUtils.runShellCmd(command)
    if log:
        print log

    if not debug:
        os.remove(txtPath)
    return