Example #1
0
def test_source_date_epoch():
    os.environ["SOURCE_DATE_EPOCH"] = "150687315"
    assert timestampNow() + epoch_diff == 150687315

    # Check that malformed value fail, any better way?
    os.environ["SOURCE_DATE_EPOCH"] = "ABCDEFGHI"
    with pytest.raises(ValueError):
        timestampNow()

    del os.environ["SOURCE_DATE_EPOCH"]
    assert timestampNow() + epoch_diff != 150687315
Example #2
0
def test_source_date_epoch():
    os.environ["SOURCE_DATE_EPOCH"] = "150687315"
    assert timestampNow() + epoch_diff == 150687315

    # Check that malformed value fail, any better way?
    os.environ["SOURCE_DATE_EPOCH"] = "ABCDEFGHI"
    with pytest.raises(ValueError):
        timestampNow()

    del os.environ["SOURCE_DATE_EPOCH"]
    assert timestampNow() + epoch_diff != 150687315
Example #3
0
 def compile(self, ttFont):
     if ttFont.recalcBBoxes:
         # For TT-flavored fonts, xMin, yMin, xMax and yMax are set in table__m_a_x_p.recalc().
         if 'CFF ' in ttFont:
             topDict = ttFont['CFF '].cff.topDictIndex[0]
             self.xMin, self.yMin, self.xMax, self.yMax = intRect(
                 topDict.FontBBox)
         elif 'CFF2' in ttFont:
             topDict = ttFont['CFF2'].cff.topDictIndex[0]
             charStrings = topDict.CharStrings
             fontBBox = None
             for charString in charStrings.values():
                 bounds = charString.calcBounds(charStrings)
                 if bounds is not None:
                     if fontBBox is not None:
                         fontBBox = unionRect(fontBBox, bounds)
                     else:
                         fontBBox = bounds
             if fontBBox is not None:
                 self.xMin, self.yMin, self.xMax, self.yMax = intRect(
                     fontBBox)
     if ttFont.recalcTimestamp:
         self.modified = timestampNow()
     data = sstruct.pack(headFormat, self)
     return data
Example #4
0
 def compile(self, ttFont):
     if ttFont.recalcBBoxes:
         # For TT-flavored fonts, xMin, yMin, xMax and yMax are set in table__m_a_x_p.recalc().
         if 'CFF ' in ttFont:
             topDict = ttFont['CFF '].cff.topDictIndex[0]
             self.xMin, self.yMin, self.xMax, self.yMax = topDict.FontBBox
     if ttFont.recalcTimestamp:
         self.modified = timestampNow()
     data = sstruct.pack(headFormat, self)
     return data
Example #5
0
	def compile(self, ttFont):
		if ttFont.recalcBBoxes:
			# For TT-flavored fonts, xMin, yMin, xMax and yMax are set in table__m_a_x_p.recalc().
			if 'CFF ' in ttFont:
				topDict = ttFont['CFF '].cff.topDictIndex[0]
				self.xMin, self.yMin, self.xMax, self.yMax = topDict.FontBBox
		if ttFont.recalcTimestamp:
			self.modified = timestampNow()
		data = sstruct.pack(headFormat, self)
		return data
Example #6
0
def test_date_parsing_with_locale():
    l = locale.getlocale(locale.LC_TIME)
    try:
        locale.setlocale(locale.LC_TIME, 'de_DE.utf8')
    except locale.Error:
        pytest.skip("Locale de_DE not available")

    try:
        assert timestampFromString(timestampToString(timestampNow()))
    finally:
        locale.setlocale(locale.LC_TIME, l)
Example #7
0
def current_time(lst):
	return timestampNow()
Example #8
0
	def compile(self, ttFont):
		if ttFont.recalcTimestamp:
			self.modified = timestampNow()
		data = sstruct.pack(headFormat, self)
		return data
Example #9
0
def current_time(lst):
	return timestampNow()
Example #10
0
 def compile(self, ttFont):
     if ttFont.recalcTimestamp:
         self.modified = timestampNow()
     data = sstruct.pack(headFormat, self)
     return data
Example #11
0
def main(configfilepath):
	cfg = Config(configfilepath)
	f = cfg.toBitmapFont()
	otf = ttLib.TTFont()
	otf.importXML(cfg.templateTTXpath, quiet=True)

	dw, dh = cfg.outlineCfg["dotsize_x"], cfg.outlineCfg["dotsize_y"]

	glyphOrder = []
	otf.setGlyphOrder(glyphOrder)

	cff = otf["CFF "].cff
	cffTopDict = cff.topDictIndex[0]
	cffCharStrings = cffTopDict.CharStrings.charStrings = {}
	cffSubrs = cffTopDict.Private.Subrs
	cffSubrs.items = []

	counts = Counter(g.bitmap.advanceWidth for g in f.glyphs).most_common(2)
	defaultWidthX = cffTopDict.Private.defaultWidthX = counts[0][0] * dw
	nominalWidthX = cffTopDict.Private.nominalWidthX = counts[-1][0] * dw

	hmtxTable = otf["hmtx"]
	hmtxTable.metrics = {}
	if "vmtx" in otf:
		vmtxTable = otf["vmtx"]
		vmtxTable.metrics = {}
	else:
		vmtxTable = None
	if "VORG" in otf:
		vorgTable = otf["VORG"]
		vorgTable.VOriginRecords = {}
		counts = Counter(g.bitmap.voriginy for g in f.glyphs).most_common(1)
		vorgTable.defaultVertOriginY = int(counts[0][0] * dh)
	else:
		vorgTable = None

	vertBearingX = -int(cfg.fontinfo.settings["vertdescent"])

	INFINITY = float("inf")

	bitmap = cfg.generateBitmap
	if bitmap:
		bst = otf["EBLC"].strikes[0].bitmapSizeTable
		eblcIndexSubTables = otf["EBLC"].strikes[0].indexSubTables = []
		ebdtGlyphDict = otf["EBDT"].strikeData[0] = {}

		bst.hori.minOriginSB  = +INFINITY
		bst.hori.minAdvanceSB = +INFINITY
		bst.hori.maxBeforeBL  = -INFINITY
		bst.hori.minAfterBL   = +INFINITY

		bst.vert.minOriginSB  = +INFINITY
		bst.vert.minAdvanceSB = +INFINITY
		bst.vert.maxBeforeBL  = -INFINITY
		bst.vert.minAfterBL   = +INFINITY
	else:
		if "EBLC" in otf:
			del otf["EBLC"]
		if "EBDT" in otf:
			del otf["EBDT"]

	cmap = otf["cmap"]

	fontBBX = [+INFINITY, +INFINITY, -INFINITY, -INFINITY]
	maxAW = maxAH = 0
	minRSB = minTSB = minBSB = +INFINITY
	maxYExtent = -INFINITY

	shape = cfg.shape()

	subrs = shape.getSubroutines(dw, dh)
	subrl = len(subrs)
	if subrl < 1240:
		bias = 107
	elif subrl < 33900:
		bias = 1131
	else:
		bias = 32768

	subrns = range(-bias, subrl - bias)

	for subr in subrs:
		charstring = T2CharString()
		charstring.fromXML("CharString", {}, subr + " return")
		cffSubrs.append(charstring)

	curIndexSubTable = None

	for i, g in enumerate(f.glyphs):
		glyphOrder.append(g.name)
		if g.codepoint != -1:
			addcmap(cmap, g.codepoint, g.name, i)

		aw = g.bitmap.advanceWidth * dw
		ah = g.bitmap.advanceHeight * dh
		if aw != defaultWidthX:
			w = "{} ".format(_intorfloat(aw - nominalWidthX))
		else:
			w = ""
		charstring = T2CharString()
		charstring.fromXML("CharString", {}, w + shape.bitmap2charstring(g.bitmap, dw, dh, subrns) + " endchar")
		cffCharStrings[g.name] = charstring

		bbx = shape.getGlyphBBX(g.bitmap, dw, dh)
		hmtxTable[g.name] = (int(aw), int(bbx[0]))
		vorgy = g.bitmap.voriginy * dh
		if vmtxTable is not None:
			vmtxTable[g.name] = (int(ah), int(vorgy - bbx[3]))
		if vorgTable is not None:
			vorgTable[g.name] = int(vorgy)
		fontBBX = [
			min(fontBBX[0], bbx[0]),
			min(fontBBX[1], bbx[1]),
			max(fontBBX[2], bbx[2]),
			max(fontBBX[3], bbx[3])
		]
		maxAW = max(maxAW, aw)
		maxAH = max(maxAH, ah)
		minRSB = min(minRSB, aw - bbx[2])
		minTSB = min(minTSB, vorgy - bbx[3])
		minBSB = min(minBSB, bbx[1] - vorgy + ah)
		maxYExtent = max(maxYExtent, vorgy - bbx[1])

		if bitmap:
			if i + 1 < len(f.glyphs) and g.bitmap.hasSameMetrics(f.glyphs[i + 1].bitmap):
				if curIndexSubTable is not None and curIndexSubTable.indexFormat == 2:
					nextIndexSubTable = curIndexSubTable
				else:
					curIndexSubTable = eblc_sub_table_classes[2](None, otf)
					curIndexSubTable.indexFormat = 2
					curIndexSubTable.imageFormat = 5
					curIndexSubTable.firstGlyphIndex = i
					curIndexSubTable.names = []
					eblcIndexSubTables.append(curIndexSubTable)

					curIndexSubTable.imageSize = g.bitmap.getImageDataSize()
					curIndexSubTable.metrics = getBitmapMetrics(g.bitmap, vertBearingX)
					updatesbitLineMetrics(curIndexSubTable.metrics, bst)

					nextIndexSubTable = curIndexSubTable
			else:
				if curIndexSubTable is None:
					curIndexSubTable = eblc_sub_table_classes[1](None, otf)
					curIndexSubTable.indexFormat = 1
					curIndexSubTable.imageFormat = 7
					curIndexSubTable.firstGlyphIndex = i
					curIndexSubTable.names = []
					eblcIndexSubTables.append(curIndexSubTable)

					nextIndexSubTable = curIndexSubTable
				elif curIndexSubTable.indexFormat == 1:
					nextIndexSubTable = curIndexSubTable
				else:
					nextIndexSubTable = None

			curIndexSubTable.lastGlyphIndex = i

			if curIndexSubTable.indexFormat == 2:
				ebdtBitmap = ebdt_bitmap_classes[5](None, otf)
			else:
				ebdtBitmap = ebdt_bitmap_classes[7](None, otf)
				ebdtBitmap.metrics = getBitmapMetrics(g.bitmap, vertBearingX)
				updatesbitLineMetrics(ebdtBitmap.metrics, bst)

			ebdtBitmap.imageData = g.bitmap.toImageData()

			ebdtGlyphDict[g.name] = ebdtBitmap
			curIndexSubTable.names.append(g.name)

			curIndexSubTable = nextIndexSubTable

	if fontBBX[0] == +INFINITY:
		fontBBX = [0, 0, 0, 0]
		maxAW = 0
		maxAH = 0
		minRSB = 0
		minTSB = 0
		minBSB = 0
		maxYExtent = 0

	ascent = cfg.fontinfo.settings["ascent"]
	descent = cfg.fontinfo.settings["descent"]

	headTable = otf["head"]
	headTable.unitsPerEm = int((ascent + descent) * dh)
	headTable.created = headTable.modified = timestampNow()
	headTable.xMin, headTable.yMin, headTable.xMax, headTable.yMax = [int(v) for v in fontBBX]
	headTable.lowestRecPPEM = int(ascent + descent)

	os_2Table = otf["OS/2"]
	os_2Table.xAvgCharWidth = f.getXAvgCharWidth(dw=dw)
	os_2Table.ulUnicodeRange1, os_2Table.ulUnicodeRange2, os_2Table.ulUnicodeRange3, os_2Table.ulUnicodeRange4 = f.getOS2ulUnicodeRanges()
	os_2Table.sTypoAscender  = int(ascent * dh)
	os_2Table.sTypoDescender = -int(descent * dh)
	os_2Table.usWinAscent  = max(os_2Table.usWinAscent,  int(fontBBX[3]))
	os_2Table.usWinDescent = max(os_2Table.usWinDescent, int(-fontBBX[1]))
	# TODO(kurgm)  OS/2.ulCodePageRange1,2
	os_2Table.sxHeight = int(cfg.fontinfo.settings["x-height"] * dh)
	os_2Table.sCapHeight = int(ascent * dh)

	if cfg.fontinfo.settings["bold"]:
		headTable.macStyle |=  0b1
		os_2Table.usWeightClass = 700
		os_2Table.fsSelection |=   0b100000
		os_2Table.fsSelection &= ~0b1000000

	if cfg.fontinfo.settings["italic"]:
		headTable.macStyle |= 0b10
		os_2Table.fsSelection |=        0b1
		os_2Table.fsSelection &= ~0b1000000

	hheaTable = otf["hhea"]
	hheaTable.ascent = int(fontBBX[3])
	hheaTable.descent = -int(fontBBX[1])
	hheaTable.advanceWidthMax = int(maxAW)
	hheaTable.minLeftSideBearing = int(fontBBX[0])
	hheaTable.minRightSideBearing = int(minRSB)
	hheaTable.xMaxExtent = int(fontBBX[2])
	hheaTable.numberOfHMetrics = len(f.glyphs)

	nameTable = otf["name"]
	for namerecords in cfg.fontinfo.names:
		for platformID, platEncID, langID in zip(namerecords.platformID, namerecords.platEncID, namerecords.langID):
			for nameID, string in namerecords.records.items():
				nameRecord = nameTable.getName(nameID, platformID, platEncID, langID)
				if nameRecord is None:
					nameRecord = NameRecord()
					nameTable.names.append(nameRecord)
					nameRecord.nameID = nameID
					nameRecord.platformID = platformID
					nameRecord.platEncID = platEncID
					nameRecord.langID = langID
				nameRecord.string = string.encode(nameRecord.getEncoding())

	cffNames = f.fontinfo.getCFFNames()
	cff.fontNames[0] = cffNames[6]  # 6 = PostScript name
	if 5 in cffNames:  # 5 = Version
		cffTopDict.version = cffNames[5]
	if 0 in cffNames:  # 0 = Copyright
		cffTopDict.Copyright = cffNames[0]
	if 4 in cffNames:  # 4 = Full name
		cffTopDict.FullName = cffNames[4]
	if 1 in cffNames:  # 1 = Font Family
		cffTopDict.FamilyName = cffNames[1]

	otf["post"].isFixedPitch = cffTopDict.isFixedPitch = f.isFixedPitch()
	mtxValue = 1.0 / ((ascent + descent) * dh)
	cffTopDict.FontMatrix = [mtxValue, 0, 0, mtxValue, 0, 0]
	cffTopDict.FontBBox = fontBBX

	if "vhea" in otf:
		vheaTable = otf["vhea"]
		vheaTable.ascent = int(cfg.fontinfo.settings["vertascent"] * dw)
		vheaTable.descent = -int(cfg.fontinfo.settings["vertdescent"] * dw)
		vheaTable.advanceHeightMax = int(maxAH)
		vheaTable.minTopSideBearing = int(minTSB)
		vheaTable.minBottomSideBearing = int(minBSB)
		vheaTable.yMaxExtent = int(maxYExtent)
		vheaTable.numberOfVMetrics = len(f.glyphs)

	if bitmap:
		bst.hori.ascender = int(ascent)
		bst.hori.descender = -int(descent)
		bst.hori.widthMax = int(maxAW / dw)
		if bst.hori.minOriginSB == +INFINITY:
			bst.hori.minOriginSB  = 0
			bst.hori.minAdvanceSB = 0
			bst.hori.maxBeforeBL  = 0
			bst.hori.minAfterBL   = 0

		bst.vert.ascender  =  int(cfg.fontinfo.settings["vertascent"])
		bst.vert.descender = -int(cfg.fontinfo.settings["vertdescent"])
		bst.vert.widthMax = int(maxAH / dh)
		if bst.vert.minOriginSB == +INFINITY:
			bst.vert.minOriginSB  = 0
			bst.vert.minAdvanceSB = 0
			bst.vert.maxBeforeBL  = 0
			bst.vert.minAfterBL   = 0

		bst.startGlyphIndex = 0
		bst.endGlyphIndex = len(f.glyphs) - 1
		bst.ppemY = int(ascent + descent)
		bst.ppemX = int((ascent + descent) * dh / dw)

	for path in cfg.templateTTX2:
		otf.importXML(path, quiet=True)

	otf.save(cfg.outputTo)
import os
import json

from fontTools.ttLib import TTFont, sfnt
from fontTools.misc.timeTools import timestampNow
sfnt.USE_ZOPFLI = True

if len(sys.argv) < 2:
    print "Usage: %s <font file>" % sys.argv[0]
    sys.exit(1)

font_file = sys.argv[1]
font_name = os.path.splitext(os.path.basename(font_file))[0]

# now or SOURCE_DATE_EPOCH, if present
timestamp = timestampNow()

font = TTFont(font_file, recalcBBoxes=False, recalcTimestamp=False)

font['head'].created = timestamp
font['head'].modified = timestamp

# remove fontforge timestamps
if 'FFTM' in font:
    del font['FFTM']

# remove redundant GDEF table
if 'GDEF' in font:
    del font['GDEF']

# remove Macintosh table
Example #13
0
from fontTools.ttLib import TTFont, sfnt
from fontTools.misc.timeTools import timestampNow
sfnt.USE_ZOPFLI = True

if len(sys.argv) < 2:
    print "Usage: %s <font file>" % sys.argv[0]
    sys.exit(1)

font_file = sys.argv[1]
font_name = os.path.splitext(os.path.basename(font_file))[0]

font = TTFont(font_file, recalcBBoxes=False, recalcTimestamp=False)

# set created/modified timestamp to now or SOURCE_DATE_EPOCH, if present
font['head'].created = timestampNow()
font['head'].modified = timestampNow()

# remove fontforge timestamps
if 'FFTM' in font:
    del font['FFTM']

# remove redundant GDEF table
if 'GDEF' in font:
    del font['GDEF']

# set font version from package.json
with open(os.path.join(os.path.dirname(__file__),
                       '../../../../package.json')) as f:
    version = json.load(f)['version']