Example #1
0
def test():
    font0 = fontforge.open('fonts/gbsn00lp.ttf')

    c0 = fontforge.nameFromUnicode(ord(u'艹'))
    c1 = fontforge.nameFromUnicode(ord(u'五'))
    cy = fontforge.nameFromUnicode(ord(u'\uE000'))

    g0 = font0[c0]
    g1 = font0[c1]

    l0 = g0.layers[1]
    l1 = g1.layers[1]

    l0.transform(psMat.scale(1,0.9))
    l0.transform(psMat.translate(0,250))
    l1.transform(psMat.scale(1, 0.5))
    l1.transform(psMat.translate(0,-104))
    #l1.transform(psMat.rotate(1.7))

    g0.layers[1] =  l0 + l1

    font0.selection.select(c0)
    font0.copy()
    font0.selection.select(cy)
    font0.paste()


    font0.generate('output/out.ttf')
Example #2
0
def fit_glyph_box(glyph, percent):
	'''Scale a font to nearly fit a square.'''
	bounding = glyph.boundingBox() # xmin, ymin, xmax, ymax
	gwidth = (bounding[2] - bounding[0])
	gheight = (bounding[3] - bounding[1])
	if not gwidth or not gheight:
		return
	if 0.64*max(gwidth, gheight) < min(gwidth, gheight):
		if gwidth > gheight:
			rate = ((gwidth - gheight)*percent + gwidth)/gwidth
			matrix = psMat.scale(1,rate)
		else:
			rate = ((gheight - gwidth)*percent + gheight)/gheight
			matrix = psMat.scale(rate,1)
		glyph.transform(matrix)
    def trim_spacing(self, xtrim, orig_width=None):
        "trims xtrim points around each glyph of font"
        if orig_width is None:
            orig_width = self._get_width()
        for sym in self.font:
            glyph = self.font[sym]
            if glyph.width == orig_width:
                rbearing = int(math.floor(max(0, glyph.right_side_bearing)))
                lbearing = int(math.floor(max(0, glyph.left_side_bearing)))
                if lbearing + rbearing == orig_width:
                    glyph.width = orig_width - 2 * xtrim
                else:
                    glyph_trim = min(xtrim, lbearing, rbearing)
                    glyph.transform(psMat.translate(glyph_trim, 0))
                    glyph.width = orig_width
                    glyph.transform(psMat.translate(-2 * glyph_trim, 0))

                    glyph_width = glyph.width
                    to_shrink = 2 * (xtrim - glyph_trim)

                    if to_shrink > 0:
                        print "%d out of %d points could not be trimmed on %s, scaling" \
                                % (to_shrink/2, xtrim, sym)
                        xratio = float(glyph_width - to_shrink)/ glyph_width
                        glyph.transform(psMat.scale(xratio, 1))
def rescale_font(infont_path, outfont_path):
    def calc_bbox(glyphs):
        def get_outer_bbox(a, b):
            x = min(a[0], b[0])
            y = min(a[1], b[1])
            w = max(a[0] + a[2], b[0] + b[2]) - x
            h = max(a[1] + a[3], b[1] + b[3]) - y
            return (x, y, w, h)
        return reduce(get_outer_bbox, glyphs)

    font = fontforge.open(infont_path)

    #ScaleToEm(800, 200);
    font.ascent = 800
    font.descent = 200

    #bbox=GetFontBoundingBox()
    bbox = calc_bbox([g.boundingBox() for g in font.glyphs()])
    #print "bbox=", bbox

    #SelectAll();
    font.selection.all()

    #Move(-bbox[0], -bbox[1]);
    #Scale(100*1000/(bbox[3]-bbox[1]), 0, 0);
    #Move(0, -200);
    matrix1 = psMat.translate(-bbox[0], -bbox[1])
    matrix2 = psMat.scale(1000.0/(bbox[3]-bbox[1]))
    matrix3 = psMat.translate(0, -200)
    transform_matrix = psMat.compose(psMat.compose(matrix1, matrix2), matrix3)
    font.transform(transform_matrix)

    font.generate(outfont_path)
Example #5
0
 def scale(self, glyph):
     if glyph.width > 0:
         source_cells_width = glyph.width / self.avg_width
         scale = 1.0 / (1.15 ** max(0, source_cells_width - 1))
         # if glyph.unicode == 10239:
         #     print("\n\n====\n" + "\n".join("{}: {}".format(attr, str(getattr(glyph, attr))) for attr in dir(glyph)))
         matrix = psMat.scale(scale, 1)
         glyph.transform(matrix)
         GlyphScaler.set_width(glyph, self.cell_width)
 def scale(self, ratio, orig_width=None):
     "scale vertically and horizontally to the same ratio"
     if orig_width is None:
         orig_width = self._get_width()
     if ratio != 1:
         for sym in self.font:
             glyph = self.font[sym]
             if glyph.width == orig_width: 
                 glyph.transform(psMat.scale(ratio, ratio))
 def horiz_condense(self, xratio, orig_width=None):
     "condense the font horizontally to the given xratio"
     if orig_width is None:
         orig_width = self._get_width()
     if xratio != 1:
         for sym in self.font:
             glyph = self.font[sym]
             if glyph.width == orig_width: 
                 glyph.transform(psMat.scale(xratio, 1))
Example #8
0
	def patch(self):
		for target_font in self.target_fonts:
			source_font = self.source_font
			target_font_em_original = target_font.em
			target_font.em = 2048
			target_font.encoding = 'ISO10646'

			# Rename font
			if self.rename_font:
				target_font.familyname += ' for Powerline and Tmux'
				target_font.fullname += ' for Powerline and Tmux'
				fontname, style = re.match("^([^-]*)(?:(-.*))?$", target_font.fontname).groups()
				target_font.fontname = fontname + 'ForPowerlineAndTmux'
				if style is not None:
					target_font.fontname += style
				target_font.appendSFNTName('English (US)', 'Preferred Family', target_font.familyname)
				target_font.appendSFNTName('English (US)', 'Compatible Full', target_font.fullname)

			source_bb = source_font['block'].boundingBox()
			target_bb = [0, 0, 0, 0]
			target_font_width = 0

			# Find the biggest char width and height in the Latin-1 extended range and the box drawing range
			# This isn't ideal, but it works fairly well - some fonts may need tuning after patching
			for cp in range(0x00, 0x17f) + range(0x2500, 0x2600):
				try:
					bbox = target_font[cp].boundingBox()
				except TypeError:
					continue
				if not target_font_width:
					target_font_width = target_font[cp].width
				if bbox[0] < target_bb[0]:
					target_bb[0] = bbox[0]
				if bbox[1] < target_bb[1]:
					target_bb[1] = bbox[1]
				if bbox[2] > target_bb[2]:
					target_bb[2] = bbox[2]
				if bbox[3] > target_bb[3]:
					target_bb[3] = bbox[3]

			# Find source and target size difference for scaling
			x_ratio = (target_bb[2] - target_bb[0]) / (source_bb[2] - source_bb[0])
			y_ratio = (target_bb[3] - target_bb[1]) / (source_bb[3] - source_bb[1])
			scale = psMat.scale(x_ratio, y_ratio)

			# Find source and target midpoints for translating
			x_diff = target_bb[0] - source_bb[0]
			y_diff = target_bb[1] - source_bb[1]
			translate = psMat.translate(x_diff, y_diff)
			transform = psMat.compose(scale, translate)
			sys.stderr.write("Source: %i %i %i %i\n" % (source_bb[0], source_bb[1], source_bb[2], source_bb[3]))
			sys.stderr.write("Target: %i %i %i %i\n" % (target_bb[0], target_bb[1], target_bb[2], target_bb[3]))
			sys.stderr.write("Offset: %.2f %.2f, Ratio: %.2f %.2f\n" % (x_diff, y_diff, x_ratio, y_ratio))
Example #9
0
def circle_at(center, size=1.0):
    """Create a Fontforge contour, in the shape of a circle, centered at
    the given point. Second parameter, optional, is the radius of the circle
    in em units. If not specified, the radius will default to 1."""
    x = ux(center)
    y = uy(center)
    # psMat is a fontforge module to help in creating transformation matrices
    matrix = psMat.translate(x,y)
    if size != 1.0:
        matrix = psMat.compose(psMat.scale(size), matrix)
    unitcircle = fontforge.unitShape(0)
    unitcircle.transform(matrix)
    return unitcircle
def apply_rescale(glyph, origin, scale):
    """Rescale glyph"""
    # move scale origin point to (0, 0)
    sx, sy = origin
    translate_matrix = psMat.translate(-sx, -sy)
    glyph.transform(translate_matrix)

    # scale around (0, 0)
    scale_matrix = psMat.scale(scale)
    glyph.transform(scale_matrix)

    # move scale origin point back to its old position
    translate_matrix = psMat.translate(origin)
    glyph.transform(translate_matrix)
Example #11
0
def fit_glyph_plus(glyph, em, percent, wavg, havg):
	'''Scale a glyph horizontally to fit the width.'''
	bounding = glyph.boundingBox() # xmin, ymin, xmax, ymax
	gwidth = (bounding[2] - bounding[0])
	gheight = (bounding[3] - bounding[1])
	if not gwidth or not gheight:
		return
	rate = (em-min(wavg-gwidth, havg-gheight)*0.01)*percent/max(gwidth, gheight)
	if gwidth < 0.95*wavg and gheight < 0.95*havg:
		rate = (em-min(wavg-gwidth, havg-gheight)*0.6)*percent/max(gwidth, gheight)
	#print gwidth, rate, em
	if rate*max(gwidth, gheight) > em:
		rate = em*percent/max(gwidth, gheight)
	matrix = psMat.scale(rate)
	glyph.transform(matrix)
Example #12
0
def set_vbearings_line(line):
    splitted = line.split()
    ch, method = splitted[0:2]
    h2v_shift = splitted[2:]
    c = get_glyph_by_name(ch)
    f.selection.select(c)
    f.copy()
    tag = 'vert'
    name = c.glyphname
    tagged_name = "%s.%s" % (name, tag)
    n = get_glyph_by_name(tagged_name)
    f.selection.select(n)
    alt_path = "../../../splitted/%s/%s/vert/u%04X.svg" % (
        weight, mod, c.unicode)
    if os.path.exists(alt_path):
        n.clear()
        n.importOutlines(alt_path, ('removeoverlap', 'correctdir'))
    else:
        f.paste()
        if method.find('R') >= 0:
            rot = psMat.compose(
                psMat.translate(-em / 2, -ascent + em / 2),
                psMat.compose(psMat.rotate(-math.pi / 2),
                psMat.translate(em / 2, ascent - em / 2)))
            n.transform(rot)
            if method.find('F') >= 0:
                flip = psMat.compose(
                    psMat.translate(-em / 2, -ascent + em / 2),
                    psMat.compose(psMat.scale(-1, 1),
                    psMat.translate(em / 2, ascent - em / 2)))
                n.transform(flip)
        elif method == 'S':
            position = weights_position[weight] * 2
            x, y = h2v_shift[position:position + 2]
            sht = psMat.translate(int(x), int(y))
            n.transform(sht)
    n.width = em
    n.vwidth = em
    if not (tag in alt_glyphs):
        alt_glyphs[tag] = []
    alt_glyphs[tag].append((name, tagged_name))
Example #13
0
#!/usr/bin/env fontforge

import fontforge, psMat
from sys import argv, stderr
from os import system
from math import radians

if len(argv) < 4:
	stderr.write("Usage: "+argv[0]+" skew-flag infile outfile\n")
	quit(1)

fontforge.setPrefs('CoverageFormatsAllowed', 1)

font = fontforge.open(argv[2])
for glyph in font.glyphs():
	if glyph.isWorthOutputting():
		width = glyph.width
		glyph.transform(psMat.translate(-font.em / 2, 0))
		glyph.transform(psMat.scale(0.8, 1.0))
		if int(argv[1]):
			glyph.transform(psMat.rotate(radians(90)))
			glyph.transform(psMat.skew(radians(-4)))
			glyph.transform(psMat.rotate(radians(-90)))
		glyph.transform(psMat.translate(font.em / 2, 0))
		glyph.width = width
font.save(argv[3])
font.close()
Example #14
0
print "Loading base file %s..." % sys.argv[1]
BaseFont = fontforge.open(sys.argv[1])

BaseFont.selection.none()
for glyph in BaseFont.glyphs():
    if glyph.isWorthOutputting():
        if isJGlyphP(glyph):
            glyph.unlinkRef()
        if isJGlyph(glyph):
            BaseFont.selection.select(("more",), glyph)

WidthE = BaseFont["ahiragana"].width
WidthV = BaseFont["ahiragana"].vwidth

print "Rescaling..."
BaseFont.transform(psMat.scale(1.2))
BaseFont.transform(psMat.translate(0, -50))

WidthJ = BaseFont["ahiragana"].width
WidthA = BaseFont["A"].width

BaseFont.selection.none()
for glyph in BaseFont.glyphs():
    if glyph.isWorthOutputting():
        if not isJGlyph(glyph):
            BaseFont.selection.select(("more",), glyph)

print "Moving..."
BaseFont.transform(psMat.translate(float(WidthJ - WidthE) / 2.0, 0.0))
for glyph in BaseFont.selection.byGlyphs:
    if glyph.width >= WidthE:
Example #15
0
def generate(italic_deg=0,
             italic_name="",
             condensed_scale=1,
             condensed_name="",
             auto_hint=False,
             manual_hints=False,
             auto_instr=False,
             auto_kern=False,
             auto_width=False,
             no_remove_overlap=False,
             no_add_extrema=False,
             generate_super_and_subscripts=True,
             generate_super_and_subscripts_method=3,
             font_name="RoutedGothic",
             family_name="Routed Gothic",
             weight_name="Regular",
             font_file_basename=FONT_FILE_BASENAME):

    font = fontforge.open(SOURCE_FILENAME)

    if generate_super_and_subscripts:

        for ss in SUPERSCRIPTS:
            sscp = codepoint(ss['codepoint'])
            ssof = codepoint(ss['of'])
            make_superscript(font, ssof, sscp)

        for ss in SUBSCRIPTS:
            sscp = codepoint(ss['codepoint'])
            ssof = codepoint(ss['of'])
            make_subscript(font, ssof, sscp)

        super_digit_glyphs = [font[cp] for cp in SUPERSCRIPT_DIGIT_CODEPOINTS]
        fractionlinewidth = max([g.width for g in super_digit_glyphs
                                 ]) + FRACTION_LINE_EXTRA_WIDTH

        fractionline = font.createChar(CODEPOINT_FRACTION_LINE)
        pen = fractionline.glyphPen()
        pen.moveTo((STROKE_WIDTH / 2 + FRACTION_LINE_BEARING,
                    SUPERSUBSCRIPT_FRACTION_LINE))
        pen.lineTo(
            (fractionlinewidth - STROKE_WIDTH / 2 - FRACTION_LINE_BEARING,
             SUPERSUBSCRIPT_FRACTION_LINE))
        pen.endPath()  # leave path open
        pen = None  # finalize
        fractionline.width = fractionlinewidth

        for vf in VULGAR_FRACTIONS:
            numerator = vf['numerator']
            denominator = vf['denominator']
            fraction = vf['codepoint']

            numerator = superscript_codepoint(numerator)
            denominator = subscript_codepoint(denominator)
            fraction = codepoint(fraction)
            make_vulgar_fraction(font, numerator, denominator, fraction)

    if auto_kern:
        for lookupName in font.gpos_lookups:
            for subtableName in font.getLookupSubtables(lookupName):
                if font.isKerningClass(subtableName):
                    font.removeLookupSubtable(subtableName)

    # condense kerning pairs if needed

    if (condensed_scale != 1) and not auto_kern:
        for lookupName in font.gpos_lookups:
            for subtableName in font.getLookupSubtables(lookupName):
                if font.isKerningClass(subtableName):
                    kc = font.getKerningClass(subtableName)
                    offsets = kc[2]
                    newOffsets = [o * condensed_scale for o in offsets]
                    font.alterKerningClass(subtableName, kc[0], kc[1],
                                           newOffsets)

    condensed_transform = psMat.scale(condensed_scale, 1)

    if condensed_scale != 1:
        font.selection.all()
        font.transform(condensed_transform)

    for glyph in font.glyphs():
        if manual_hints:
            glyph.manualHints = True
        else:
            glyph.manualHints = False
        if italic_deg:
            width = glyph.width
            for name in glyph.layers:
                layer = glyph.layers[name]
                layer.transform(italic_transform(italic_deg))
                glyph.layers[name] = layer
                glyph.width = width
            glyph.anchorPoints = [
                anchor_point_transform(p, italic_transform(italic_deg))
                for p in glyph.anchorPoints
            ]

        glyph.round()
        glyph.stroke("circular", STROKE_WIDTH, "round", "round")
        if not no_remove_overlap:
            glyph.removeOverlap()
        if not no_add_extrema:
            glyph.addExtrema()

    if auto_width:
        font.autoWidth(AUTO_WIDTH, -1024, 1024)

    # call build() on glyphs that reference two glyphs if anchor
    # points would be used
    for glyph in font.glyphs():
        built = False
        if len(glyph.references) == 2:
            glyphname1 = glyph.references[0][0]
            glyphname2 = glyph.references[1][0]
            g1 = font[glyphname1]
            g2 = font[glyphname2]
            g1_base_aps = tuple(
                [ap[0] for ap in g1.anchorPoints if ap[1] == "base"])
            g1_mark_aps = tuple(
                [ap[0] for ap in g1.anchorPoints if ap[1] == "mark"])
            g2_base_aps = tuple(
                [ap[0] for ap in g2.anchorPoints if ap[1] == "base"])
            g2_mark_aps = tuple(
                [ap[0] for ap in g2.anchorPoints if ap[1] == "mark"])
            i1 = intersect(g1_base_aps, g2_mark_aps)
            i2 = intersect(g2_base_aps, g1_mark_aps)
            if len(i1) or len(i2):
                glyph.build()
                built = True
        if not built:
            if italic_deg:
                glyph.references = [
                    reference_transform(r, glyph, italic_deg)
                    for r in glyph.references
                ]

    for glyph in font.glyphs():
        if auto_hint:
            glyph.autoHint()
        if auto_instr:
            glyph.autoInstr()

    font.strokedfont = False

    if auto_kern:
        font.selection.all()
        font.addLookup("autoKern", "gpos_pair", (),
                       (("liga", (("latn", ("dflt")), )), ))
        font.addKerningClass("autoKern", "autoKern", 288, 16, False, True)

    font.fontname = font_name
    font.familyname = family_name
    font.fullname = family_name
    font.weight = weight_name
    font.italicangle = italic_deg
    basename = font_file_basename

    if condensed_scale != 1:
        # separate family names for condensed variants.  don't
        # remember why.
        font.familyname = font.familyname + " " + condensed_name.replace(
            "-", " ")

        font.fontname = font.fontname + condensed_name.replace(
            "-", "").replace(" ", "")
        font.fullname = font.fullname + " " + condensed_name.replace("-", " ")

        basename = basename + "-" + condensed_name.lower().replace(" ", "-")

    if italic_deg:
        font.fontname = font.fontname + "-" + italic_name.replace(" ", "-")
        font.fullname = font.fullname + " " + italic_name.replace("-", " ")

        basename = basename + "-" + italic_name.lower().replace(" ", "-")

        font.italicangle = -ITALIC_ANGLE_DEG

    sfd_filename = DIST_SFD_DIRECTORY + "/" + basename + ".sfd"
    ttf_filename = DIST_TTF_DIRECTORY + "/" + basename + ".ttf"

    sfd_dir = os.path.dirname(sfd_filename)
    ttf_dir = os.path.dirname(ttf_filename)
    if not os.path.exists(sfd_dir):
        print "makedirs " + sfd_dir
        os.makedirs(sfd_dir)
    if not os.path.exists(ttf_dir):
        print "makedirs " + ttf_dir
        os.makedirs(ttf_dir)

    print "Saving " + sfd_filename + " ..."
    font.save(sfd_filename)
    print "Saving " + ttf_filename + " ..."
    font.generate(ttf_filename, flags=("no-hints", "omit-instructions"))

    font.close()
Example #16
0
						int(nm[0], 16 if nm[0][0:2] == '0x' else 10),
						strid,
						nm[1]
						])

addSfntNames(args.sfnt_name)
addSfntNames(args.sfnt_family_name, 1)
addSfntNames(args.sfnt_full_name, 4)
addSfntNames(args.sfnt_weight, 2)
for nomen in sfnt:
	font.appendSFNTName(nomen[0], nomen[1], nomen[2])

for glyph in glyphsWorthOutputting(font):
	if args.action == 'scale':
		glyph.transform(
			psMat.scale(args.width / glyph.width, 1.0),
			('partialRefs', 'round'))
	elif args.action == 'pad':
		glyph.transform(
			psMat.translate((args.width - glyph.width) / 2, 0),
			('partialRefs', 'round'))
		glyph.width = int(args.width)
	if args.skew is not None:
		glyph.transform(
			psMat.skew(radians(args.skew)),
			('partialRefs', 'round'))

if args.merge_with is not None:
	for fileName in args.merge_with:
		font2 = fontforge.open(fileName)
		font.encoding = font2.encoding
Example #17
0
if (len(sys.argv) < 3):
  print 'Usage: %s source-file target-file' % sys.argv[0]
  quit(1)

print 'Loading base file %s...' % sys.argv[1]
BaseFont = fontforge.open(sys.argv[1])

BaseFont.selection.none()
for glyph in BaseFont.glyphs():
  if glyph.isWorthOutputting():
    if isJGlyphP(glyph):
      glyph.unlinkRef()
    if isJGlyph(glyph):
      BaseFont.selection.select(("more",), glyph)

print 'Rescaling J...'
BaseFont.transform(psMat.scale(1.28206))
BaseFont.transform(psMat.translate(0,-120))

BaseFont.selection.none()
for glyph in BaseFont.glyphs():
  if glyph.isWorthOutputting():
    if not isJGlyph(glyph):
      BaseFont.selection.select(("more",), glyph)

print 'Rescaling E...'
BaseFont.transform(psMat.scale(1.28206))

print 'Saving target file %s...' % sys.argv[2]
BaseFont.save(sys.argv[2])
Example #18
0
def calculate_matrix(scale):
    if scale == 1.0:
        return None
    else:
        return psMat.scale(scale)
Example #19
0
#!/home/rakesh/pdf2htmlEX/fontforge-pdf2htmlEX/fontforgeexe/fontforge
#Needs: fonts/StrokeTests.sfd

import os
import fontforge
import psMat

stroketests = os.path.join("/home/rakesh/pdf2htmlEX/fontforge-pdf2htmlEX/tests", "fonts", "StrokeTests.sfd")

print "triangle"
font=fontforge.open(stroketests)
font.selection.all()
triangle=fontforge.unitShape(3).transform(psMat.scale(25))
font.stroke("polygonal",triangle)
font.close()

print "square"
font=fontforge.open(stroketests)
font.selection.all()
square=fontforge.unitShape(4).transform(psMat.scale(25))
font.stroke("polygonal",square)
font.close()

print "pentagon"
font=fontforge.open(stroketests)
font.selection.all()
pent=fontforge.unitShape(5).transform(psMat.scale(25))
font.stroke("polygonal",pent)
font.close()

print "circular"
def patch_one_font(source_font, target_font, rename_font=True):
    target_font_em_original = target_font.em
    target_font.em = 2048
    target_font.encoding = 'ISO10646'

    # Rename font
    if rename_font:
        target_font.familyname += ' for Powerline'
        target_font.fullname += ' for Powerline'
        fontname, style = FONT_NAME_RE.match(target_font.fontname).groups()
        target_font.fontname = fontname + 'ForPowerline'
        if style is not None:
            target_font.fontname += style
        target_font.appendSFNTName('English (US)', 'Preferred Family',
                                   target_font.familyname)
        target_font.appendSFNTName('English (US)', 'Compatible Full',
                                   target_font.fullname)

    source_bb = source_font['block'].boundingBox()
    target_bb = [0, 0, 0, 0]
    target_font_width = 0

    # Find the biggest char width and height in the Latin-1 extended range and
    # the box drawing range This isn't ideal, but it works fairly well - some
    # fonts may need tuning after patching.
    for cp in chain(range(0x00, 0x17f), range(0x2500, 0x2600)):
        try:
            bbox = target_font[cp].boundingBox()
        except TypeError:
            continue
        if not target_font_width:
            target_font_width = target_font[cp].width
        if bbox[0] < target_bb[0]:
            target_bb[0] = bbox[0]
        if bbox[1] < target_bb[1]:
            target_bb[1] = bbox[1]
        if bbox[2] > target_bb[2]:
            target_bb[2] = bbox[2]
        if bbox[3] > target_bb[3]:
            target_bb[3] = bbox[3]

    # Find source and target size difference for scaling
    x_ratio = (target_bb[2] - target_bb[0]) / (source_bb[2] - source_bb[0])
    y_ratio = (target_bb[3] - target_bb[1]) / (source_bb[3] - source_bb[1])
    scale = psMat.scale(x_ratio, y_ratio)

    # Find source and target midpoints for translating
    x_diff = target_bb[0] - source_bb[0]
    y_diff = target_bb[1] - source_bb[1]
    translate = psMat.translate(x_diff, y_diff)
    transform = psMat.compose(scale, translate)

    # Create new glyphs from symbol font
    for source_glyph in source_font.glyphs():
        if source_glyph == source_font['block']:
            # Skip the symbol font block glyph
            continue

        # Select and copy symbol from its encoding point
        source_font.selection.select(source_glyph.encoding)
        source_font.copy()

        # Select and paste symbol to its unicode code point
        target_font.selection.select(source_glyph.unicode)
        target_font.paste()

        # Transform the glyph
        target_font.transform(transform)

        # Reset the font's glyph width so it's still considered monospaced
        target_font[source_glyph.unicode].width = target_font_width

    target_font.em = target_font_em_original

    # FIXME: Menlo and Meslo font do have these substitutes, but U+FB01 and
    #        U+FB02 still do not show up for fi and fl.
    if 0xFB01 in target_font:
        target_font[0xFB01].removePosSub('*')  # fi ligature
    if 0xFB02 in target_font:
        target_font[0xFB02].removePosSub('*')  # fl ligature

    # Generate patched font
    extension = os.path.splitext(target_font.path)[1]
    if extension.lower() not in ['.ttf', '.otf']:
        # Default to OpenType if input is not TrueType/OpenType
        extension = '.otf'
    target_font.generate('{0}{1}'.format(target_font.fullname, extension))
Example #21
0
    def merge_one(self, ctx):
        self.log.debug('"%s" merging...', ctx.filename)
        font = fontforge.open(ctx.filename)
        unicode_range = ctx.unicode_range
        glyph_scale = ctx.scale
        ext_start = 0
        ext_end = 0
        if len(unicode_range) >= 1:
            ext_start = int(unicode_range[0], 16)
        if len(unicode_range) >= 2:
            ext_end = int(unicode_range[1], 16)
        base_start = ext_start
        remap_start_point = ctx.remap_start_point
        if remap_start_point is not None:
            base_start = int(remap_start_point, 16)
        base_font_height = get_height(self.base_font)
        font_height = get_height(font)

        # scale transform
        scale_ratio_x = round(float(self.base_font.em) / font.em, 3)
        scale_ratio_y = round(float(base_font_height) / font_height, 3)
        scale = psMat.scale(scale_ratio_x * glyph_scale, scale_ratio_y * glyph_scale)
        if ext_start is 0:
            font.selection.all()
        else:
            font.selection.select(('ranges', 'unicode'), ext_start, ext_end)

        # copy and transform glyphs
        for glyph in list(font.selection.byGlyphs):
            index = base_start + (glyph.encoding - ext_start)
            font.selection.select(glyph.encoding)
            font.copy()
            self.base_font.selection.select(index)
            self.base_font.paste()
            _glyph = self.base_font[index]
            _glyph.transform(scale)
            _glyph.glyphname = glyph.glyphname
            info = get_glyph_size_info(_glyph)
            move_x = 0
            move_y = 0
            if self.hints.ascent < info.ymax:
                move_y = self.hints.ascent - info.ymax
            if glyph_scale < 1.0 and ctx.adjust_position:
                move_x += info.width * (1.0 - glyph_scale) / 2.0
                move_y -= info.height * (1.0 - glyph_scale) / 2.0
            info = get_glyph_size_info(_glyph)
            if info.width + move_x < self.base_font.em:
                _glyph.left_side_bearing += move_x
            hint = self.get_hint(info.width)
            if hint.glyph_width < info.width and ctx.adjust_position:
                delta = info.width - hint.glyph_width
                move_x += 1.0 - (delta / hint.glyph_width)
            _glyph.transform(psMat.translate(move_x, move_y))
            _glyph.width = hint.glyph_width
            _glyph.vwidth = hint.glyph_vwidth

        # add copyright
        if font.copyright and font.copyright not in self.base_font.copyright:
            self.base_font.copyright += '\n' + font.copyright
        font.close()
        self.log.debug('"%s" merged.', ctx.filename)
Example #22
0
        "teema2luuva", "teema2luuvar", "teema3luuva", "teema3luuvar",
        "teema4luuva", "teema4luuvar", "capteema1luuva", "capteema1luuvar",
        "capteema2luuva", "capteema2luuvar", "capteema3luuva",
        "capteema3luuvar", "capteema4luuva", "capteema4luuvar"):
    font[char].unlinkThisGlyph()
    font[char].clear()
#end for

# Clear the bitmaps (native script command ClearBackground();).
# This does not work at the moment. Bug?
for char in font:
    font[char].layers[0] = fontforge.layer()

font.selection.all()
font.removeOverlap()
font.transform(psMat.scale(1.25))  # Should match scale factor in tracing.mf
font.addExtrema()
font.simplify(2, ("removesingletonpoints"), 0, 0, 5000)
font.round()
font.simplify(2, ("ignoreextrema"), 0, 0, 5000)
font.addExtrema()
font.round()
font.simplify(2, ("setstarttoextremum"), 0, 0, 5000)

font.mergeFonts("numerals.sfd")
font.encoding = "unicode"
font.encoding = "compacted"

# Older versions of grcompiler can't handle version=4 (fixed in SVN rev. 1105)
font.os2_version = 3
Example #23
0
# Remove previous data
from subprocess import call
call(["rm", "-rf", "./dist"])
call(["mkdir", "./dist"])
call(["mkdir", "./dist/css"])
call(["mkdir", "./dist/fonts"])
call([
    "cp", "./fontawesome/css/font-awesome.css", "./dist/css/font-awesome.css"
])

# Load font
font = fontforge.open('fontawesome/fonts/fontawesome-webfont.ttf')

# and now the automated process

a = psMat.scale(0.6)
a2 = psMat.scale(0.6)
cur_unicode = start_char

icon_list = []


# Detects if the next unicode character is a blacklisted one
def next_unicode(cur_unicode):
    new_unicode = cur_unicode + 1
    while new_unicode in range(
            0xfe00, 0xfe10) or new_unicode == 0xfeff or new_unicode in range(
                0xf000, 0xf2ff):
        new_unicode = new_unicode + 1
    return new_unicode
Example #24
0
import fontforge
import sys
import os
import struct
import psMat

src = fontforge.open("Myriad-CnSemibold.ttf")

src.fontname = "Myriad-UcnSemibold"
src.fullname = "Myriad Ultra-Condensed Semibold"
src.copyright = "As free as Myriad-CnSemibold."
src.version = "001.200"
src.em = 1024;

cnd = psMat.scale(0.7,1)
src.selection.all()
for glyph in src.selection.byGlyphs:
   glyph.transform(cnd)
src.generate("Myriad-UcnSemibold.ttf")

src = fontforge.open("FreeSans.ttf")

src.fontname = "FreeSansCn"
src.fullname = "Free Sans Condensed"
src.copyright = "As free as Free Sans."
src.version = "001.200"
src.em = 1024;

cnd = psMat.scale(0.7,1)
src.selection.all()
Example #25
0
def mergeLatin(font, feafile, italic=False, glyphs=None, quran=False):
    styles = {"Regular": "Roman",
              "Slanted": "Italic",
              "Bold": "Bold",
              "BoldSlanted": "BoldItalic"}

    style = styles[font.fontname.split("-")[1]]

    latinfile = "Crimson-%s.sfd" %style

    tmpfont = mkstemp(suffix=os.path.basename(latinfile))[1]
    latinfont = fontforge.open("sources/crimson/%s" %latinfile)

    validateGlyphs(latinfont) # to flatten nested refs mainly

    if glyphs:
        latinglyphs = list(glyphs)
    else:
        # collect latin glyphs we want to keep
        latinglyphs = []

        # we want all glyphs in latin0-9 encodings
        for i in range(0, 9):
            latinfont.encoding = 'latin%d' %i
            for glyph in latinfont.glyphs("encoding"):
                if glyph.encoding <= 255:
                    if glyph.glyphname not in latinglyphs:
                        latinglyphs.append(glyph.glyphname)
                elif glyph.unicode != -1 and glyph.unicode <= 0x017F:
                    # keep also Unicode Latin Extended-A block
                    if glyph.glyphname not in latinglyphs:
                        latinglyphs.append(glyph.glyphname)
                elif glyph.unicode == -1 and '.prop' in glyph.glyphname:
                    # proportional digits
                    latinglyphs.append(glyph.glyphname)

        # keep ligatures too
        ligatures = ("f_b", "f_f_b",
                     "f_h", "f_f_h",
                     "f_i", "f_f_i",
                     "f_j", "f_f_j",
                     "f_k", "f_f_k",
                     "f_l", "f_f_l",
                     "f_f")

        # and Arabic romanisation characters
        romanisation = ("uni02BC", "uni02BE", "uni02BE", "amacron", "uni02BE",
                "amacron", "eacute", "uni1E6F", "ccedilla", "uni1E6F", "gcaron",
                "ycircumflex", "uni1E29", "uni1E25", "uni1E2B", "uni1E96",
                "uni1E0F", "dcroat", "scaron", "scedilla", "uni1E63", "uni1E11",
                "uni1E0D", "uni1E6D", "uni1E93", "dcroat", "uni02BB", "uni02BF",
                "rcaron", "grave", "gdotaccent", "gbreve", "umacron", "imacron",
                "amacron", "amacron", "uni02BE", "amacron", "uni02BE",
                "acircumflex", "amacron", "uni1E97", "tbar", "aacute", "amacron",
                "ygrave", "agrave", "uni02BE", "aacute", "Amacron", "Amacron",
                "Eacute", "uni1E6E", "Ccedilla", "uni1E6E", "Gcaron",
                "Ycircumflex", "uni1E28", "uni1E24", "uni1E2A", "uni1E0E",
                "Dcroat", "Scaron", "Scedilla", "uni1E62", "uni1E10", "uni1E0C",
                "uni1E6C", "uni1E92", "Dcroat", "Rcaron", "Gdotaccent", "Gbreve",
                "Umacron", "Imacron", "Amacron", "Amacron", "Amacron",
                "Acircumflex", "Amacron", "Tbar", "Aacute", "Amacron", "Ygrave",
                "Agrave", "Aacute")

        # and some typographic characters
        typographic = ("uni2010", "uni2011", "figuredash", "endash", "emdash",
                "uni2015", "quoteleft", "quoteright", "quotesinglbase",
                "quotereversed", "quotedblleft", "quotedblright", "quotedblbase",
                "uni201F", "dagger", "daggerdbl", "bullet", "onedotenleader",
                "ellipsis", "uni202F", "perthousand", "minute", "second",
                "uni2038", "guilsinglleft", "guilsinglright", "uni203E",
                "fraction", "i.TRK", "minus", "uni2213", "radical", "uni2042")

        for l in (ligatures, romanisation, typographic):
            for name in l:
                if name not in latinglyphs:
                    latinglyphs.append(name)

    if not quran:
        # we want our ring above and below in Quran font only
        for name in ("uni030A", "uni0325"):
            font[name].clear()

        latinglyphs += buildComposition(latinfont, latinglyphs)
    subsetFont(latinfont, latinglyphs)

    digits = ("zero", "one", "two", "three", "four", "five", "six", "seven",
              "eight", "nine")

    # common characters that can be used in Arabic and Latin need to be handled
    # carefully in the slanted font so that right leaning italic is used with
    # Latin, and left leaning slanted is used with Arabic, using ltra and rtla
    # features respectively, for less OpenType savvy apps we make the default
    # upright so it works reasonably with bot scripts
    if italic:
        if "Bold" in style:
            upright = fontforge.open("sources/crimson/Crimson-Bold.sfd")
        else:
            upright = fontforge.open("sources/crimson/Crimson-Roman.sfd")

        shared = ("exclam", "quotedbl", "numbersign", "dollar", "percent",
                  "quotesingle", "asterisk", "plus", "colon", "semicolon",
                  "less", "equal", "greater", "question", "at", "asciicircum",
                  "exclamdown", "section", "copyright", "logicalnot", "registered",
                  "plusminus", "uni00B2", "uni00B3", "paragraph", "uni00B9",
                  "ordmasculine", "onequarter", "onehalf", "threequarters",
                  "questiondown", "quoteleft", "quoteright", "quotesinglbase",
                  "quotereversed", "quotedblleft", "quotedblright",
                  "quotedblbase", "uni201F", "dagger", "daggerdbl",
                  "perthousand", "minute", "second", "guilsinglleft",
                  "guilsinglright", "fraction", "uni2213")

        for name in shared:
            glyph = latinfont[name]
            glyph.clear()
            upright.selection.select(name)
            upright.copy()
            latinfont.createChar(upright[name].encoding, name)
            latinfont.selection.select(name)
            latinfont.paste()

        for name in digits:
            glyph = latinfont[name]
            glyph.glyphname += '.ltr'
            glyph.unicode = -1
            upright.selection.select(name)
            upright.copy()
            latinfont.createChar(upright[name].encoding, name)
            latinfont.selection.select(name)
            latinfont.paste()

            rtl = latinfont.createChar(-1, name + ".rtl")
            rtl.addReference(name, italic)
            rtl.useRefsMetrics(name)

        for name in digits:
            pname = name + ".prop"
            upright.selection.select(pname)
            upright.copy()
            latinfont.createChar(-1, pname)
            latinfont.selection.select(pname)
            latinfont.paste()

        for name in digits:
            pname = name + ".prop"
            rtl = latinfont.createChar(-1, name + ".rtl" + ".prop")
            rtl.addReference(pname, italic)
            rtl.useRefsMetrics(pname)

    # copy kerning classes
    kern_lookups = {}
    if not quran:
        for lookup in latinfont.gpos_lookups:
            kern_lookups[lookup] = {}
            kern_lookups[lookup]["subtables"] = []
            kern_lookups[lookup]["type"], kern_lookups[lookup]["flags"] = latinfont.getLookupInfo(lookup)[:2]
            for subtable in latinfont.getLookupSubtables(lookup):
                if latinfont.isKerningClass(subtable):
                    kern_lookups[lookup]["subtables"].append((subtable, latinfont.getKerningClass(subtable)))

    for lookup in latinfont.gpos_lookups:
        latinfont.removeLookup(lookup)

    for lookup in latinfont.gsub_lookups:
        latinfont.removeLookup(lookup)

    latinfont.save(tmpfont)
    latinfont.close()

    font.mergeFonts(tmpfont)
    os.remove(tmpfont)

    if not quran:
        buildComposition(font, latinglyphs)

    # add Latin small and medium digits
    for name in digits:
        if italic:
            # they are only used in Arabic contexts, so always reference the
            # italic rtl variant
            refname = name +".rtl"
        else:
            refname = name
        small = font.createChar(-1, name + ".small")
        small.clear()
        small.addReference(refname, psMat.scale(0.6))
        small.transform(psMat.translate(0, -40))
        small.width = 600
        centerGlyph(small)

        medium = font.createChar(-1, name + ".medium")
        medium.clear()
        medium.addReference(refname, psMat.scale(0.8))
        medium.transform(psMat.translate(0, 50))
        medium.width = 900
        centerGlyph(medium)

    for lookup in kern_lookups:
        font.addLookup(lookup,
                kern_lookups[lookup]["type"],
                kern_lookups[lookup]["flags"],
                (('kern', script_lang),)
                )

        for subtable in kern_lookups[lookup]["subtables"]:
            first = []
            second = []
            offsets = subtable[1][2]

            # drop non-existing glyphs
            for new_klasses, klasses in ((first, subtable[1][0]), (second, subtable[1][1])):
                for klass in klasses:
                    new_klass = []
                    if klass:
                        for name in klass:
                            if name in font:
                                new_klass.append(name)
                    new_klasses.append(new_klass)

            # if either of the classes is empty, don’t bother with the subtable
            if any(first) and any(second):
                font.addKerningClass(lookup, subtable[0], first, second, offsets)
Example #26
0
def build_font(_f, emoji):
    log('Generating %s ...' % _f.get('weight_name'))
    hack = fontforge.open('./sourceFonts/%s' % _f.get('hack'))
    hack = remove_glyph_from_hack(hack)
    cica = fontforge.open('./sourceFonts/%s' % _f.get('mgen_plus'))
    nerd = fontforge.open('./sourceFonts/nerd.ttf')

    for g in hack.glyphs():
        g.transform((0.42, 0, 0, 0.42, 0, 0))
        if _f.get('hack_weight_reduce') != 0:
            # g.changeWeight(_f.get('hack_weight_reduce'), 'auto', 0, 0, 'auto')
            g.stroke("circular", _f.get('hack_weight_reduce'), 'butt', 'round',
                     'removeexternal')
        g = align_to_center(g)
    hack = modify_m(hack, _f.get('weight_name'))

    alternate_expands = [
        0x306e,
    ]

    if _f.get('mgen_weight_add') != 0:
        for g in cica.glyphs():
            # g.changeWeight(_f.get('mgen_weight_add'), 'auto', 0, 0, 'auto')
            g.stroke("caligraphic", _f.get('mgen_weight_add'),
                     _f.get('mgen_weight_add'), 45, 'removeinternal')
            # g.stroke("circular", _f.get('mgen_weight_add'), 'butt', 'round', 'removeinternal')

    ignoring_center = [
        0x3001,
        0x3002,
        0x3008,
        0x3009,
        0x300a,
        0x300b,
        0x300c,
        0x300d,
        0x300e,
        0x300f,
        0x3010,
        0x3011,
        0x3014,
        0x3015,
        0x3016,
        0x3017,
        0x3018,
        0x3019,
        0x301a,
        0x301b,
        0x301d,
        0x301e,
        0x3099,
        0x309a,
        0x309b,
        0x309c,
    ]
    for g in cica.glyphs():
        g.transform((0.91, 0, 0, 0.91, 0, 0))
        full_half_threshold = 700
        if _f.get('italic'):
            g.transform(psMat.skew(0.25))
            skew_amount = g.font.ascent * 0.91 * 0.25
            g.width = g.width + skew_amount
            full_half_threshold += skew_amount
        if g.width > full_half_threshold:
            width = 1024
        else:
            width = 512
        g.transform(psMat.translate((width - g.width) / 2, 0))
        g.width = width
        if g.encoding in ignoring_center:
            pass
        else:
            g = align_to_center(g)

    for g in hack.glyphs():
        if g.isWorthOutputting:
            if _f.get('italic'):
                g.transform(psMat.skew(0.25))
            if g.encoding >= 0x2500 and g.encoding <= 0x25af:
                g.transform(
                    psMat.compose(psMat.scale(1.024, 1.024),
                                  psMat.translate(0, -30)))
                g = align_to_center(g)
            hack.selection.select(g.encoding)
            hack.copy()
            cica.selection.select(g.encoding)
            cica.paste()

    for g in nerd.glyphs():
        if g.encoding < 0xe0a0 or g.encoding > 0xf4ff:
            continue
        g = modify_nerd(g)
        nerd.selection.select(g.encoding)
        nerd.copy()
        cica.selection.select(g.encoding)
        cica.paste()

    cica = fix_box_drawings(cica)
    cica = zenkaku_space(cica)
    cica = zero(cica)
    cica = modify_WM(cica)
    cica = vertical_line_to_broken_bar(cica)
    cica = emdash_to_broken_dash(cica)
    cica = add_gopher(cica)
    if emoji:
        cica = add_notoemoji(cica)
    cica = add_smalltriangle(cica)
    cica = add_dejavu(cica, _f)
    cica = resize_supersub(cica)

    cica.ascent = ASCENT
    cica.descent = DESCENT
    cica.upos = 45
    cica.fontname = _f.get('family')
    cica.familyname = _f.get('family')
    cica.fullname = _f.get('name')
    cica.weight = _f.get('weight_name')
    cica = set_os2_values(cica, _f)
    cica.appendSFNTName(0x411, 0, COPYRIGHT)
    cica.appendSFNTName(0x411, 1, _f.get('family'))
    cica.appendSFNTName(0x411, 2, _f.get('style_name'))
    # cica.appendSFNTName(0x411,3, "")
    cica.appendSFNTName(0x411, 4, _f.get('name'))
    cica.appendSFNTName(0x411, 5, "Version " + VERSION)
    cica.appendSFNTName(0x411, 6,
                        _f.get('family') + "-" + _f.get('weight_name'))
    # cica.appendSFNTName(0x411,7, "")
    # cica.appendSFNTName(0x411,8, "")
    # cica.appendSFNTName(0x411,9, "")
    # cica.appendSFNTName(0x411,10, "")
    # cica.appendSFNTName(0x411,11, "")
    # cica.appendSFNTName(0x411,12, "")
    cica.appendSFNTName(0x411, 13, LICENSE)
    # cica.appendSFNTName(0x411,14, "")
    # cica.appendSFNTName(0x411,15, "")
    cica.appendSFNTName(0x411, 16, _f.get('family'))
    cica.appendSFNTName(0x411, 17, _f.get('style_name'))
    cica.appendSFNTName(0x409, 0, COPYRIGHT)
    cica.appendSFNTName(0x409, 1, _f.get('family'))
    cica.appendSFNTName(0x409, 2, _f.get('style_name'))
    cica.appendSFNTName(
        0x409, 3,
        VERSION + ";" + _f.get('family') + "-" + _f.get('style_name'))
    cica.appendSFNTName(0x409, 4, _f.get('name'))
    cica.appendSFNTName(0x409, 5, "Version " + VERSION)
    cica.appendSFNTName(0x409, 6, _f.get('name'))
    # cica.appendSFNTName(0x409,7, "")
    # cica.appendSFNTName(0x409,8, "")
    # cica.appendSFNTName(0x409,9, "")
    # cica.appendSFNTName(0x409,10, "")
    # cica.appendSFNTName(0x409,11, "")
    # cica.appendSFNTName(0x409,12, "")
    cica.appendSFNTName(0x409, 13, LICENSE)
    # cica.appendSFNTName(0x409,14, "")
    # cica.appendSFNTName(0x409,15, "")
    cica.appendSFNTName(0x409, 16, _f.get('family'))
    cica.appendSFNTName(0x409, 17, _f.get('style_name'))
    if emoji:
        fontpath = './dist/%s' % _f.get('filename')
    else:
        fontpath = './dist/noemoji/%s' % _f.get('filename')

    cica.generate(fontpath)

    cica.close()
    hack.close()
    nerd.close()
Example #27
0
def main(aArgs):

    ############################################################################
    # Open the font
    print("Opening file %s... " % aArgs.input, end="")
    try:
        font = fontforge.open(aArgs.input)
    except EnvironmentError:
        print("Failed!")
        exit(1)
    print("Done")
    print("")

    tolerance = font.em / 50

    ############################################################################
    # Ensure that the font has glyphs for all the ASCII characters.
    print("Testing Basic Latin Unicode Block... ")
    for u in range(0x20, 0x7F):
        print("Testing U+%2X... " % u, end="")
        if u not in font:
            print("Failed")
            warnMissingGlyph(u)
        else:
            print("Done")
    print("")

    ############################################################################
    # Test the "use typo metrics" bit
    print("Testing OS/2 version... ", end="")
    if font.os2_version and font.os2_version < 4:
        print("Failed")
        print("Warning: OS/2 version does not support USE_TYPO_METRICS!",
              file=sys.stderr)
    else:
        print("Done")

    print("Testing USE_TYPO_METRICS... ", end="")
    if not font.os2_use_typo_metrics:
        print("Failed")
        print("Warning: USE_TYPO_METRICS set to false in the OS/2 table!",
              file=sys.stderr)
    else:
        print("Done")
    print("")

    ############################################################################
    # Ensure that the MathConstants table exists.
    print("Testing MathConstants table... ", end="")
    if not font.math.exists():
        print("Not found!")
        print("Creating a new MathConstants table... Done")
        # Dummy read operation to force the creation of the table.
        font.math.ScriptPercentScaleDown
    else:
        print("Done")
    print("")

    # ScriptPercentScaleDown
    # Suggested value: 80%

    # ScriptScriptPercentScaleDown
    # Suggested value: 60%

    # DelimitedSubFormulaMinHeight
    # Suggested value: normal line height x 1.5

    # DisplayOperatorMinHeight
    print("Testing DisplayOperatorMinHeight... ")
    if font.math.DisplayOperatorMinHeight == 0:
        print("Error: DisplayOperatorMinHeight is set to 0!", file=sys.stderr)
        if 0x4F in font:
            # use the height of the letter 'O'
            box = font[0x4F].boundingBox()
            suggestedValue = (box[3] - box[1]) * \
                             kLargeOpMinDisplayOperatorFactor
            print("Setting DisplayOperatorMinHeight to %d." % suggestedValue)
            font.math.DisplayOperatorMinHeight = suggestedValue
    for c in kLargeOperators:
        # Verify that the DisplayOperatorMinHeight ensure that the size of
        # operator will really be increased in display mode.
        if c not in font:
            continue
        print("Testing large operator U+%04X... " % c, end="")
        glyph = font[c]
        box = glyph.boundingBox()
        baseHeight = box[3] - box[1]
        print("Done")
        if (font.math.DisplayOperatorMinHeight <
                kLargeOpMinDisplayOperatorFactor * baseHeight):
            print(
                "Warning: DisplayOperatorMinHeight is less than %f times the base height of U+%04X."
                % (kLargeOpMinDisplayOperatorFactor, c),
                file=sys.stderr)
    print("")

    # MathLeading

    # AxisHeight
    # Note: FontForge defaults to zero.
    # See https://github.com/fontforge/fontforge/pull/2242
    if 0x2B in font:
        plusBoundingBox = font[0x2B].boundingBox()
        suggestedValue = (plusBoundingBox[1] + plusBoundingBox[3]) / 2
    else:
        suggestedValue = 0
    print("Testing AxisHeight... ", end="")
    if font.math.AxisHeight == 0:
        print("Failed")
        print("Error: AxisHeight is set to 0!", file=sys.stderr)
        if suggestedValue > 0:
            print("Setting AxisHeight to %d." % suggestedValue)
            font.math.AxisHeight = suggestedValue
    else:
        print("Done")
        if (suggestedValue > 0
                and (abs(font.math.AxisHeight - suggestedValue) > tolerance)):
            print("Warning: AxisHeight is set to %d while the center of the\
plus sign is %d." % (font.math.AxisHeight, suggestedValue),
                  file=sys.stderr)
    print("")

    # AccentBaseHeight
    # FlattenedAccentBaseHeight
    # SubscriptShiftDown
    # SubscriptTopMax
    # SubscriptBaselineDropMin
    # SuperscriptShiftUp
    # SuperscriptShiftUpCramped
    # SuperscriptBottomMin
    # SuperscriptBaselineDropMax
    # SubSuperscriptGapMin
    # SuperscriptBottomMaxWithSubscript
    # SpaceAfterScript
    # UpperLimitGapMin
    # UpperLimitBaselineRiseMin
    # LowerLimitGapMin
    # LowerLimitBaselineDropMin
    # StackTopShiftUp
    # StackTopDisplayStyleShiftUp
    # StackBottomShiftDown
    # StackBottomDisplayStyleShiftDown
    # StackGapMin
    # StackDisplayStyleGapMin
    # StretchStackTopShiftUp
    # StretchStackBottomShiftDown
    # StretchStackGapAboveMin
    # StretchStackGapBelowMin
    # FractionNumeratorShiftUp
    # FractionNumeratorDisplayStyleShiftUp
    # FractionDenominatorShiftDown
    # FractionDenominatorDisplayShiftDown
    # FractionNumeratorGapMin
    # FractionNumDisplayStyleGapMin

    # FractionRuleThickness
    # Suggested value: default rule thickness
    print("Testing FractionRuleThickness... ", end="")
    if font.math.FractionRuleThickness == 0:
        print("Failed")
        print("Error: FractionRuleThickness is set to 0!", file=sys.stderr)
        print("Setting FractionRuleThickness to %d." % font.uwidth)
        font.math.FractionRuleThickness = font.uwidth
    else:
        print("Done")
    print("")

    # FractionDenominatorGapMin
    # FractionDenomDisplayStyleGapMin
    # SkewedFractionHorizontalGap
    # SkewedFractionVerticalGap
    # OverbarVerticalGap

    # OverbarRuleThickness
    # Suggested value: default rule thickness
    print("Testing OverbarRuleThickness... ", end="")
    if font.math.OverbarRuleThickness == 0:
        print("Failed")
        print("Error: OverbarRuleThickness is set to 0!", file=sys.stderr)
        print("Setting OverBarRuleThickness to %d." % font.uwidth)
        font.math.OverbarRuleThickness = font.uwidth
    else:
        print("Done")
    print("")

    # OverbarExtraAscender
    # UnderbarVerticalGap

    # UnderbarRuleThickness
    print("Testing UnderbarRuleThickness... ", end="")
    if font.math.UnderbarRuleThickness == 0:
        print("Failed")
        print("Error: UnderbarRuleThickness is set to 0!", file=sys.stderr)
        print("Setting OverBarRuleThickness to %d." % font.uwidth)
        font.math.UnderbarRuleThickness = font.uwidth
    else:
        print("Done")
    print("")

    # UnderbarExtraDescender
    # RadicalVerticalGap

    # RadicalDisplayStyleVerticalGap
    # Suggested value: default rule thickness + 1/4 x-height
    # Note: FontForge defaults to zero.
    # See https://github.com/fontforge/fontforge/pull/2224
    print("Testing RadicalDisplayStyleVerticalGap... ", end="")
    suggestedValue = font.uwidth + font.xHeight / 4
    if font.math.RadicalDisplayStyleVerticalGap == 0:
        print("Failed")
        print("Error: RadicalDisplayStyleVerticalGap is set to 0!",
              file=sys.stderr)
        print("Setting RadicalDisplayStyleVerticalGap to %d." % suggestedValue)
        font.math.RadicalDisplayStyleVerticalGap = suggestedValue
    else:
        print("Done")
    print("")

    # RadicalRuleThickness
    # Suggested value: default rule thickness
    # Note: FontForge defaults to zero.
    # See https://github.com/fontforge/fontforge/pull/2224
    print("Testing RadicalRuleThickness... ", end="")
    if font.math.RadicalRuleThickness == 0:
        print("Failed")
        print("Error: RadicalRuleThickness is set to 0!", file=sys.stderr)
        print("Setting RadicalRuleThickness to %d." % font.uwidth)
        font.math.RadicalRuleThickness = font.uwidth
    else:
        print("Done")
    print("")

    # RadicalExtraAscender
    # RadicalKernBeforeDegree
    # RadicalKernAfterDegree
    # RadicalDegreeBottomRaisePercent

    ############################################################################
    # Verify whether the MathVariant table has appropriate data for some basic
    # unicode constructions.
    print("Testing Unicode Constructions in the MathVariant table...")
    for c in kUnicodeConstructions:

        codePoint = c[0]
        isVertical = c[1]
        variants = c[2]
        parts = c[3]
        if variants is None and parts is None:
            raise ("no data provided for glyph U+%04X" % codePoint)
            continue

        # Verify whether the character is present.
        print("Testing base glyph for U+%04X... " % codePoint, end="")
        if codePoint not in font:
            print("Failed")
            warnMissingGlyph(codePoint)
            continue
        print("Done")
        glyph = font[codePoint]

        # Verify whether the variants are available.
        if variants is not None:
            print("Testing variants for U+%04X... " % codePoint, end="")
            v = None
            if isVertical:
                v = glyph.verticalVariants
            else:
                v = glyph.horizontalVariants
            if v is not None:
                print("Done")
            else:
                print("Failed")
                print("Warning: missing variants for operator U+%04X!" %
                      codePoint,
                      file=sys.stderr)
                print("Setting variants for operator U+%04X... " % codePoint,
                      end="")
                # FIXME: Is it really necessary to specify the base glyph?
                # This is done in Latin Modern but not XITS.
                v = "%s " % font[codePoint].glyphname
                allGlyphsAvailable = True
                for u in variants:
                    if u not in font:
                        warnMissingGlyph(u)
                        allGlyphsAvailable = False
                        break
                    v += "%s " % font[u].glyphname
                if not allGlyphsAvailable:
                    print("Failed")
                else:
                    # Set the variants
                    if isVertical:
                        glyph.verticalVariants = v
                    else:
                        glyph.horizontalVariants = v
                    print("Done")

        # Verify whether the components are available.
        if parts is not None:
            print("Testing components for U+%04X... " % codePoint, end="")
            components = None
            if isVertical:
                components = glyph.verticalComponents
            else:
                components = glyph.horizontalComponents
            if components:
                print("Done")
            else:
                print("Failed")
                print("Warning: missing components for operator U+%04X!" %
                      codePoint,
                      file=sys.stderr)
                print("Setting components for operator U+%04X... " % codePoint,
                      end="")

                # Verify that all parts are available
                allGlyphsAvailable = True
                components = []
                overlap = font.math.MinConnectorOverlap
                i = 0
                for p in parts:
                    if p[0] not in font:
                        warnMissingGlyph(p[0])
                        allGlyphsAvailable = False
                        break
                    if i == 0:
                        startConnectorLength = 0
                    else:
                        startConnectorLength = overlap
                    if i == len(parts) - 1:
                        endConnectorLength = 0
                    else:
                        endConnectorLength = overlap
                    boundingBox = font[p[0]].boundingBox()
                    if isVertical:
                        fullAdvance = int(boundingBox[3] - boundingBox[1])
                    else:
                        fullAdvance = int(boundingBox[2] - boundingBox[0])
                    components.append(
                        (font[p[0]].glyphname, p[1], startConnectorLength,
                         endConnectorLength, fullAdvance))
                    i = i + 1

                if not allGlyphsAvailable:
                    print("Failed")
                else:
                    # Set the components.
                    # Note: this makes FontForge crash.
                    # See https://github.com/fontforge/fontforge/pull/2225
                    components = tuple(components)
                    if isVertical:
                        glyph.verticalComponents = components
                    else:
                        glyph.horizontalComponents = components
                    print("Done")
    print("")

    ############################################################################
    # Verify whether the MathVariant table has appropriate data for large
    # operators.
    print("Testing large operators in the MathVariant table...")
    for c in kLargeOperators:

        # Verify whether the character is present.
        print("Testing base glyph for large operator U+%04X... " % c, end="")
        if c not in font:
            print("Failed")
            warnMissingGlyph(c)
            continue
        print("Done")
        glyph = font[c]

        # Verify variants
        print("Testing variants for large operator U+%04X... " % c, end="")
        if glyph.verticalVariants is not None:
            # Verify whether DisplayOperatorMinHeight can be satisfied.
            variants = glyph.verticalVariants.split(" ")
            hasDisplaySize = False
            for v in variants:
                if v in font:
                    box = font[v].boundingBox()
                    height = box[3] - box[1]
                    if font.math.DisplayOperatorMinHeight <= height:
                        hasDisplaySize = True
                        break
            if hasDisplaySize:
                print("Done")
            else:
                print("Failed")
                print(
                    "Warning: U+%04X does not have any size variant of height at least DisplayOperatorMinHeight"
                    % c,
                    file=sys.stderr)
        else:
            print("Failed")
            print("Setting variants for operator U+%04X... " % c, end="")
            # Add a glyph for the operator in display mode
            baseGlyphName = font[c].glyphname
            displayGlyphName = "%s.display" % baseGlyphName
            g = font.createChar(-1, displayGlyphName)
            font.selection.select(baseGlyphName)
            font.copy()
            font.selection.select(displayGlyphName)
            font.paste()
            g.transform(psMat.scale(kLargeOpDisplayOperatorFactor),
                        ("round", ))
            # FIXME: Is it really necessary to specify the base glyph?
            # This is done in Latin Modern but not XITS.
            glyph.verticalVariants = "%s %s" % (baseGlyphName,
                                                displayGlyphName)
            print("Done")
    print("")

    ############################################################################
    # Verify whether integrals have italic correction
    print("Testing italic correction for integrals...")
    for c in kLargeOpIntegrals:
        if c not in font:
            continue
        print("Testing italic correction for operator U+%04X..." % c)

        # Get the list of variants, including the base size
        variants = font[c].verticalVariants.split(" ")
        baseGlyphName = font[c].glyphname
        if variants[0] != baseGlyphName:
            variants.insert(0, baseGlyphName)

        # Test italic correction for each variant
        for v in variants:
            if v in font:
                testItalicCorrection(font[v])
    print("")

    ############################################################################
    # Testing Prescripted Operators / ssty tables
    print("Testing Prescripted Operators / ssty tables...")
    for c in kPreScriptedOperators:
        testSSTY(font, c)
    print("")

    ############################################################################
    # Testing Mathematical Alphanumeric Characters
    testMathVariants(font, "bold", ((0x1D400, 0x1D433), (0x1D6A8, 0x1D6E1),
                                    (0x1D7CA, 0x1D7CB), (0x1D7CE, 0x1D7D7)),
                     aArgs.bold)

    testMathVariants(font, "italic",
                     ((0x1D434, 0x1D454), (0x210E, ), (0x1D456, 0x1D467),
                      (0x1D6A4, 0x1D6A5), (0x1D6E2, 0x1D6D6)), aArgs.italic)

    testMathVariants(font, "bold-italic",
                     ((0x1D468, 0x1D49B), (0x1D71C, 0x1D755)),
                     aArgs.bold_italic)

    testMathVariants(font, "script",
                     ((0x1D49C, ), (0x212C, ), (0x1D49E, 0x1D49F),
                      (0x2130, 0x2131), (0x1D4A2, ), (0x210B, ), (0x2110, ),
                      (0x1D4A5, 0x1D4A6), (0x2112, ), (0x2133, ),
                      (0x1D4A9, 0x1D4AC), (0x211B, ), (0x1D4AE, 0x1D4B9),
                      (0x212F, ), (0x1D4BB, ), (0x210A, ), (0x1D4BD, 0x1D4C3),
                      (0x2134, ), (0x1D4C5, 0x1D4CF)), None)

    testMathVariants(font, "bold-script", ((0x1D4D0, 0x1D503), ), None)

    testMathVariants(font, "fraktur",
                     ((0x1D504, 0x1D505), (0x212D, ), (0x1D507, 0x1D50A),
                      (0x210C, ), (0x2111, ), (0x1D50D, 0x1D514), (0x211C, ),
                      (0x1D516, 0x1D51C), (0x2128, ), (0x1D51E, 0x1D537)),
                     None)

    testMathVariants(font, "bold-fraktur", ((0x1D56C, 0x1D59F), ), None)

    testMathVariants(font, "sans-serif",
                     ((0x1D5A0, 0x1D5D3), (0x1D7E2, 0x1D7EB)),
                     aArgs.sans_serif)

    testMathVariants(font, "sans-serif-bold",
                     ((0x1D5D4, 0x1D607), (0x1D756, 0x1D78F),
                      (0x1D7EC, 0x1D7F5)), aArgs.sans_serif_bold)

    testMathVariants(font, "sans-serif-italic", ((0x1D608, 0x1D63B), ),
                     aArgs.sans_serif_italic)

    testMathVariants(font, "sans-serif-bold-italic",
                     ((0x1D63C, 0x1D66F), (0x1D790, 0x1D7C9)),
                     aArgs.sans_serif_bold_italic)

    testMathVariants(font, "monospace",
                     ((0x1D670, 0x1D6A3), (0x1D7F6, 0x1D7FF)), aArgs.monospace)

    testMathVariants(font, "double-struck",
                     ((0x1D538, 0x1D539), (0x2102, ), (0x1D53B, 0x1D53E),
                      (0x210D, ), (0x1D540, 0x1D544), (0x2115, ), (0x1D546, ),
                      (0x2119, 0x211A), (0x211D, ), (0x1D54A, 0x1D550),
                      (0x2124, ), (0x1D552, 0x1D56B), (0x1D7D8, 0x1D7E1),
                      (0x1EEA1, 0x1EEA3), (0x1EEA5, 0x1EEA9),
                      (0x1EEAB, 0x1EEBB)), None)

    testMathVariants(font, "initial",
                     ((0x1EE21, 0x1EE22), (0x1EE24, ), (0x1EE27, ),
                      (0x1EE29, 0x1EE32), (0x1EE34, 0x1EE37), (0x1EE39, ),
                      (0x1EE3B, )), None)

    testMathVariants(font, "tailed",
                     ((0x1EE42, ), (0x1EE47, ), (0x1EE49, ), (0x1EE4B, ),
                      (0x1EE4D, 0x1EE4F), (0x1EE51, 0x1EE52), (0x1EE54, ),
                      (0x1EE57, ), (0x1EE59, ), (0x1EE5B, ), (0x1EE5D, ),
                      (0x1EE5F, )), None)

    testMathVariants(font, "looped", ((0x1EE80, 0x1EE89), (0x1EE8B, 0x1EE9B)),
                     None)

    testMathVariants(font, "stretched",
                     ((0x1EE61, 0x1EE62), (0x1EE64, ), (0x1EE67, 0x1EE6A),
                      (0x1EE6C, 0x1EE72), (0x1EE74, 0x1EE77),
                      (0x1EE79, 0x1EE7C), (0x1EE7E, )), None)
    ############################################################################
    if aArgs.output:
        # Output the modified font.
        output = "%s.fixed.sfd" % aArgs.input
        print("Saving file %s... " % output, end="")
        font.save(output)
        print("Done")
    font.close()
Example #28
0
	def patch(self):
		for target_font in self.target_fonts:
			source_font = self.source_font
			target_font_em_original = target_font.em
			target_font.em = 2048
			target_font.encoding = 'ISO10646'

			# Rename font
			if self.rename_font:
				target_font.familyname += ' for Powerline'
				target_font.fullname += ' for Powerline'
				target_font.fontname += 'ForPowerline'
				target_font.appendSFNTName('English (US)', 'Preferred Family', target_font.familyname)
				target_font.appendSFNTName('English (US)', 'Compatible Full', target_font.fullname)

			source_bb = source_font['block'].boundingBox()
			target_bb = [0, 0, 0, 0]
			target_font_width = 0

			# Find the biggest char width and height in the Latin-1 extended range and the box drawing range
			# This isn't ideal, but it works fairly well - some fonts may need tuning after patching
			for cp in range(0x00, 0x17f) + range(0x2500, 0x2600):
				try:
					bbox = target_font[cp].boundingBox()
				except TypeError:
					continue
				if not target_font_width:
					target_font_width = target_font[cp].width
				if bbox[0] < target_bb[0]:
					target_bb[0] = bbox[0]
				if bbox[1] < target_bb[1]:
					target_bb[1] = bbox[1]
				if bbox[2] > target_bb[2]:
					target_bb[2] = bbox[2]
				if bbox[3] > target_bb[3]:
					target_bb[3] = bbox[3]

			# Find source and target size difference for scaling
			x_ratio = (target_bb[2] - target_bb[0]) / (source_bb[2] - source_bb[0])
			y_ratio = (target_bb[3] - target_bb[1]) / (source_bb[3] - source_bb[1])
			scale = psMat.scale(x_ratio, y_ratio)

			# Find source and target midpoints for translating
			x_diff = target_bb[0] - source_bb[0]
			y_diff = target_bb[1] - source_bb[1]
			translate = psMat.translate(x_diff, y_diff)
			transform = psMat.compose(scale, translate)

			# Create new glyphs from symbol font
			for source_glyph in source_font.glyphs():
				if source_glyph == source_font['block']:
					# Skip the symbol font block glyph
					continue

				# Select and copy symbol from its encoding point
				source_font.selection.select(source_glyph.encoding)
				source_font.copy()

				# Select and paste symbol to its unicode code point
				target_font.selection.select(source_glyph.unicode)
				target_font.paste()

				# Transform the glyph
				target_font.transform(transform)

				# Reset the font's glyph width so it's still considered monospaced
				target_font[source_glyph.unicode].width = target_font_width

			target_font.em = target_font_em_original

			# Generate patched font
			target_font.generate('{0}.otf'.format(target_font.fullname))
Example #29
0
def script(font, felipa):
    vratio = 681 / 754
    adjust = {
        # majuscule
        "𝒜": compose(mat.scale(0.9, 1), mat.translate(50, 0)),
        "𝒟": mat.translate(-20),
        "ℋ": mat.scale(0.87, 1),
        "ℐ": mat.translate(30),
        "𝒥": mat.translate(50),
        "𝒦": mat.scale(0.93, 1),
        "ℳ": mat.scale(0.72, 1),
        "𝒩": mat.scale(0.9, 1),
        "ℛ": mat.scale(0.95, 1),
        "𝒮": mat.translate(50, 0),
        "𝒰": mat.scale(0.9, 1),
        "𝒱": mat.scale(0.9, 1),
        "𝒲": mat.scale(0.67, 1),
        "𝒳": mat.scale(0.85, 1),
        "𝒴": compose(mat.scale(0.95, 1), mat.translate(-15, 0)),
        # miniscule
        "𝒻": mat.translate(100, 0),
        "𝒾": mat.translate(100, 0),
        "𝒿": mat.translate(100, 0),
        "𝓂": compose(mat.translate(-90, 0), mat.scale(0.98, 1)),
        "𝓅": mat.translate(40, 0),
        "𝓆": mat.translate(40, 0),
        "𝓇": mat.translate(40, 0),
        "𝓈": mat.translate(40, 0),
        "𝓉": mat.translate(40, 0),
        "𝓋": mat.translate(40, 0),
        "𝓍": mat.translate(40, 0),
        "𝓏": mat.translate(40, 0),
    }
    # majuscule
    dst = "𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℳ𝒩𝒪𝒫𝒬ℛ𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵"
    src = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    for i in range(0, len(dst)):
        felipa.selection.select(("singletons", ), ord(src[i]))
        felipa.copy()
        font.selection.select(("singletons", ), ord(dst[i]))
        font.paste()
        glyph = font[ord(dst[i])]
        xform = mat.scale(vratio)
        if dst[i] in adjust:
            xform = mat.compose(xform, adjust[dst[i]])
        glyph.transform(xform, ("round", ))
        glyph.width, glyph.vwidth = monosize
    # miniscule
    dst = "𝒶𝒷𝒸𝒹ℯ𝒻ℊ𝒽𝒾𝒿𝓀𝓁𝓂𝓃ℴ𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏"
    src = "abcdefghijklmnopqrstuvwxyz"
    for i in range(0, len(dst)):
        felipa.selection.select(("singletons", ), ord(src[i]))
        felipa.copy()
        font.selection.select(("singletons", ), ord(dst[i]))
        font.paste()
        glyph = font[ord(dst[i])]
        xform = mat.scale(vratio)
        if dst[i] in adjust:
            xform = mat.compose(xform, adjust[dst[i]])
        xform = mat.compose(xform, mat.translate(60, 0))
        glyph.transform(xform, ("round", ))
        glyph.width, glyph.vwidth = monosize
import psMat
from sys import argv, stderr
from GlyphComment import getfield

fontforge.setPrefs('CoverageFormatsAllowed', 1)

if len(argv) < 4:
	stderr.write("Usage: "+argv[0]+" ratio infile outfile\n")
	quit(1)

widthScale = None
widthList = {}
try:
	widthScale = float(argv[1])
except ValueError:
	import csv
	reader = csv.reader(open(argv[1]), delimiter='\t')
	for data in reader:
		widthList[data[0]] = float(data[3])

font = fontforge.open(argv[2])
for glyph in font.glyphs():
	if glyph.isWorthOutputting():
		kagename = getfield(glyph, "Kage")
		glyphWidth = glyph.width
		glyphScale = widthList[kagename] if kagename in widthList else widthScale
		if glyphScale != 1.0:
			glyph.transform(psMat.scale(glyphScale, 1.0), ("partialRefs", "round"))
		glyph.width = glyphWidth
font.save(argv[3])
Example #31
0
def fraktur(font, unifracktur):
    unifracktur.selection.select(("singletons", ), "i", "j", "u")
    unifracktur.unlinkReferences()
    dst = "𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ"
    src = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    vratio = 683 / 1471
    scale = [
        0.9,  # A
        0.8,  # B
        1.0,  # C
        0.9,  # D
        1.0,  # E
        0.95,  # F
        0.95,  # G
        0.95,  # H
        1.0,  # I
        1.0,  # J
        0.85,  # K
        1.0,  # L
        0.65,  # M
        0.8,  # N
        1.0,  # O
        0.8,  # P
        0.93,  # Q
        0.82,  # R
        0.95,  # S
        0.95,  # T
        1.0,  # U
        0.85,  # V
        0.65,  # W
        1.0,  # X
        0.83,  # Y
        1.0,  # Z
    ]

    adjust = {
        '𝔣': mat.translate(220, 0),
        '𝔦': mat.translate(-100, 0),
        '𝔧': mat.translate(-455, 0),
        '𝔩': mat.translate(1970, 0),
        '𝔰': mat.translate(-65, 0),
        '𝔵': mat.translate(200, 0),
    }
    # majuscule
    for i in range(0, len(dst)):
        unifracktur.selection.select(("singletons", ), ord(src[i]))
        unifracktur.copy()
        font.selection.select(("singletons", ), ord(dst[i]))
        font.paste()
        glyph = font[ord(dst[i])]
        xform = compose(
            mat.scale(vratio),
            mat.scale(scale[i], 1),
        )
        glyph.transform(xform, ("round", ))
        xform = moveToCenter(glyph)
        if dst[i] in adjust:
            xform = mat.compose(xform, adjust[dst[i]])
        glyph.transform(xform, ("round", ))
        glyph.width, glyph.vwidth = monosize
    # miniscule
    dst = "𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷"
    src = "abcdefghijklmnopqrstuvwxyz"
    for i in range(0, len(dst)):
        unifracktur.selection.select(("singletons", ), ord(src[i]))
        unifracktur.copy()
        font.selection.select(("singletons", ), ord(dst[i]))
        font.paste()
        glyph = font[ord(dst[i])]
        xform = mat.scale(vratio)
        glyph.transform(xform, ("round", ))
        xform = moveToMonoNoSquash(glyph)
        if dst[i] in adjust:
            xform = mat.compose(xform, adjust[dst[i]])
        glyph.transform(xform, ("round", ))
        # FIXME iju
        glyph.width, glyph.vwidth = monosize
Example #32
0
def copy_glyphs(glyphs, source_font, target_font, new_font, new_suffix,
                overwrite):
    target_font_em_original = target_font.em
    target_font.em = 2048
    target_font.encoding = 'ISO10646'

    # Rename font
    target_font.familyname += new_suffix
    target_font.fullname += new_suffix
    fontname, style = re.match("^([^-]*)(?:(-.*))?$",
                               target_font.fontname).groups()
    target_font.fontname = fontname + new_suffix.replace(' ', '')
    if style is not None:
        target_font.fontname += style
    target_font.appendSFNTName('English (US)', 'Preferred Family',
                               target_font.familyname)
    target_font.appendSFNTName('English (US)', 'Compatible Full',
                               target_font.fullname)

    # range(0x00, 0x17f) + range(0x2500, 0x2600):
    ipdb.set_trace()
    source_bb = source_font['block'].boundingBox()
    target_bb = [0, 0, 0, 0]
    target_font_width = 0

    # Find the biggest char width and height in the Latin-1 extended range and the box drawing range
    # This isn't ideal, but it works fairly well - some fonts may need tuning after patching
    for cp in range(0x00, 0x17f) + range(0x2500, 0x2600):
        try:
            bbox = target_font[cp].boundingBox()
        except TypeError:
            continue
        if not target_font_width:
            target_font_width = target_font[cp].width
        if bbox[0] < target_bb[0]:
            target_bb[0] = bbox[0]
        if bbox[1] < target_bb[1]:
            target_bb[1] = bbox[1]
        if bbox[2] > target_bb[2]:
            target_bb[2] = bbox[2]
        if bbox[3] > target_bb[3]:
            target_bb[3] = bbox[3]

    # Find source and target size difference for scaling
    x_ratio = (target_bb[2] - target_bb[0]) / (source_bb[2] - source_bb[0])
    y_ratio = (target_bb[3] - target_bb[1]) / (source_bb[3] - source_bb[1])
    scale = psMat.scale(x_ratio, y_ratio)

    # Find source and target midpoints for translating
    x_diff = target_bb[0] - source_bb[0]
    y_diff = target_bb[1] - source_bb[1]
    translate = psMat.translate(x_diff, y_diff)
    transform = psMat.compose(scale, translate)
    sys.stderr.write("Source: %i %i %i %i\n" % (source_bb[0], source_bb[1], source_bb[2], source_bb[3]))
    sys.stderr.write("Target: %i %i %i %i\n" % (target_bb[0], target_bb[1], target_bb[2], target_bb[3]))
    sys.stderr.write("Offset: %.2f %.2f, Ratio: %.2f %.2f\n" % (x_diff, y_diff, x_ratio, y_ratio))
    # print(scale)
    # print(translate)
    # print(transform)

    # Create new glyphs from symbol font
    for source_glyph in source_font.glyphs():
        if source_glyph == source_font['block']:
            # Skip the symbol font block glyph
            continue

        # Select and copy symbol from its encoding point
        source_font.selection.select(source_glyph.encoding)
        source_font.copy()

        # Select and paste symbol to its unicode code point
        target_font.selection.select(source_glyph.unicode)
        target_font.paste()

        # Transform the glyph
        target_font.transform(transform)

        # Reset the font's glyph width so it's still considered monospaced
        target_font[source_glyph.unicode].width = target_font_width

    target_font.em = target_font_em_original

    # Generate patched font
    extension = os.path.splitext(target_font.path)[1]
    if extension.lower() not in ['.ttf', '.otf']:
        # Default to OpenType if input is not TrueType/OpenType
        extension = '.otf'
    target_font.generate('{0}{1}'.format(target_font.fullname, extension))
Example #33
0
def arrows(font, dejavu):
    sideArrs = "←→↔↚↛↮" \
             + "⇐⇒⇔⇍⇏⇎" \
             + "↜↝↭⇜⇝" \
             + "↞↠↼⇀" \
             + "⇤⇥⟜⊸⧟" \
             + "↢↣↩↪↤↦" \
             + "⤆⤇" \
             + "⤙⤚⤛⤜"
    tallArrs = "↑↓↕⇑⇓⇕" \
             + "↟↡↾⇂" \
             + "⤒⤓⫯⫰↥↧"
    for c in sideArrs:
        if ord(c) in dejavu:
            dejavu.selection.select(("singletons", ), ord(c))
            dejavu.copy()
            font.selection.select(("singletons", ), ord(c))
            font.paste()
            glyph = font[ord(c)]
            xform = mat.scale(monosize[0] / glyph.width)
            glyph.transform(xform, ('round', ))
            xFront, _, xBack, _ = glyph.layers[1].boundingBox()
            xform = aroundCentroid(
                glyph, mat.scale(glyph.width / (xBack - xFront + 20)))
            # xform = mat.translate(10 - xFront)
            glyph.transform(xform, ('round', ))
            glyph.width, glyph.vwidth = monosize
    for c in tallArrs:
        if ord(c) in dejavu:
            dejavu.selection.select(("singletons", ), ord(c))
            dejavu.copy()
            font.selection.select(("singletons", ), ord(c))
            font.paste()
            glyph = font[ord(c)]
            _, yBot, _, yTop = glyph.layers[1].boundingBox()
            xform = mat.scale(monosize[0] / (yTop - yBot))
            glyph.transform(xform, ('round', ))
            xform = moveToCenter(glyph)
            glyph.transform(xform, ('round', ))
            glyph.width, glyph.vwidth = monosize
    glyph = mvGlyph(font, font, '⫯', '⊸')
    xform = aroundCentroid(glyph, mat.rotate(math.pi / 2))
    glyph.transform(xform, ('round', ))
    glyph = mvGlyph(font, font, '⫰', '⫯')
    xform = aroundCentroid(glyph, mat.scale(1, -1))
    glyph.transform(xform, ('round', ))
    glyph = mvGlyph(font, font, '⤓', '⤒')
    xform = aroundCentroid(glyph, mat.scale(1, -1))
    glyph.transform(xform, ('round', ))
    glyph.width, glyph.vwidth = monosize
    glyph = mvGlyph(font, font, '⤆', '⤇')
    xform = aroundCentroid(glyph, mat.scale(-1, 1))
    glyph.transform(xform, ('round', ))
    glyph = mvGlyph(font, font, '⤙', '⤚')
    xform = aroundCentroid(glyph, mat.scale(-1, 1))
    glyph.transform(xform, ('round', ))
    glyph.width, glyph.vwidth = monosize
    glyph = mvGlyph(font, font, '⤛', '⤜')
    xform = aroundCentroid(glyph, mat.scale(-1, 1))
    glyph.transform(xform, ('round', ))
    glyph.width, glyph.vwidth = monosize
Example #34
0
def modify_iconsfordevs(_g):
    _g.transform(psMat.compose(psMat.scale(2), psMat.translate(0, -126)))
    _g.width = 1024
    _g = align_to_center(_g)
    return _g
Example #35
0
base_font.generate("otf/"+base_font.fontname+".otf")

base_font.printSample("fontdisplay", 24, "", "specimens/"+base_font.fontname+".pdf")

print("Generated regular")

base_font.close()

## condensed

base_font = fontforge.open("sfd/14seg-gen.sfd")

base_font.selection.all()

matrix = psMat.scale(0.5, 1.0)

base_font.transform(matrix)

base_font.fullname = "LCD Display: 14 Segment (Condensed)"

base_font.fontname = "LCD14Condensed"

base_font.os2_width = 3 # Condensed

base_font.save("sfd/14seg-condensed.sfd")

base_font.generate("otf/"+base_font.fontname+".otf")

base_font.printSample("fontdisplay", 24, "", "specimens/"+base_font.fontname+".pdf")
Example #36
0
    
# Create new font, set some properties.
dst  = fontforge.font()
dst.fontname = "MSyms"
dst.familyname = "MusicalSymbolsForPlaytab"
dst.fullname = "Musical Symbols For Playtab"
dst.copyright = "Free as a bird"
dst.version = "000.100"
dst.em = 1000;

# Next slot for glyphs.
ind = 33;

# Copy glyphs from MusicSymbols.
src = fontforge.open("MusicSymbols.ttf")
gcopy( "Sharp",   0x0023 )
gcopy( "Flat",    0x0062 )
gcopy( "Natural", 0x006e )
gcopy( "Same2",   0x00d4 )

stretch = psMat.scale( 1, 1.2 )

# Copy glyphs from TimesRoman.
src = fontforge.open("../../../.fonts/TimesNewRomanPSMT.ttf")
gcopy( "Dim",     0x006f, stretch )
gcopy( "HDim",    0x00f8, stretch )
gcopy( "Major",   0x0394 )

# Generate new font.
dst.generate("new.pfa")
Example #37
0
import fontforge
import sys
import os
import struct
import psMat

src = fontforge.open("Myriad-CnSemibold.ttf")

src.fontname = "Myriad-UcnSemibold"
src.fullname = "Myriad Ultra-Condensed Semibold"
src.copyright = "As free as Myriad-CnSemibold."
src.version = "001.200"
src.em = 1024

cnd = psMat.scale(0.7, 1)
src.selection.all()
for glyph in src.selection.byGlyphs:
    glyph.transform(cnd)
src.generate("Myriad-UcnSemibold.ttf")

src = fontforge.open("FreeSans.ttf")

src.fontname = "FreeSansCn"
src.fullname = "Free Sans Condensed"
src.copyright = "As free as Free Sans."
src.version = "001.200"
src.em = 1024

cnd = psMat.scale(0.7, 1)
src.selection.all()
Example #38
0
def squish_layer(layer, squish):
    layer = layer.dup()
    mat = psMat.scale(squish, 1.0)
    layer.transform(mat)
    return layer
Example #39
0
def add_dejavu(_f, conf):
    dejavu = None
    weight_name = conf.get('weight_name')
    if weight_name == "Regular":
        dejavu = fontforge.open('./sourceFonts/DejaVuSansMono.ttf')
    elif weight_name == "Bold":
        dejavu = fontforge.open('./sourceFonts/DejaVuSansMono-Bold.ttf')

    for g in dejavu.glyphs():
        g.transform(
            psMat.compose(psMat.scale(0.45, 0.45), psMat.translate(-21, 0)))
        g.width = 512

    _f.importLookups(dejavu, dejavu.gpos_lookups)

    # 0x0300 - 0x036f - Combining Diacritical Marks
    for g in dejavu.glyphs():
        if g.encoding < 0x0300 or g.encoding > 0x036f:
            continue
        else:
            if len(g.references) > 0:
                anchorPoints = g.anchorPoints
                g.anchorPoints = ()
                g.transform(psMat.scale(2.22, 2.22))
                g.transform(psMat.translate(50, 0))
                g.width = 512
                g.anchorPoints = anchorPoints

            if g.encoding <= 0x0304:
                anchorPoints = g.anchorPoints
                g.anchorPoints = ()
                g.transform(psMat.scale(1.2, 1.2))
                g.transform(psMat.translate(-100, -60))
                g.width = 512
                g.anchorPoints = anchorPoints
            elif g.encoding == 0x0305:
                g.transform(psMat.translate(0, -60))
            elif g.encoding <= 0x0315:
                g.transform(psMat.translate(0, 0))
            elif g.encoding <= 0x0317:
                g.transform(psMat.translate(0, 302))
            elif g.encoding <= 0x0319:
                g.transform(psMat.translate(0, 200))
            elif g.encoding <= 0x031b:
                g.transform(psMat.translate(0, -60))
            elif g.encoding <= 0x031c:
                g.transform(psMat.translate(0, 22))
            elif g.encoding <= 0x031f:
                g.transform(psMat.translate(0, 141))
            elif g.encoding <= 0x0332:
                g.transform(psMat.translate(0, 90))
            elif g.encoding == 0x0333:
                g.transform(
                    psMat.compose(psMat.scale(0.9, 0.9),
                                  psMat.translate(-415, 29)))
                g.width = 512
            elif g.encoding <= 0x0338:
                g.transform(psMat.translate(0, 0))
            elif g.encoding <= 0x033c:
                g.transform(psMat.translate(0, 138))
            else:
                g.transform(psMat.translate(0, 0))
            dejavu.selection.select(g.encoding)
            dejavu.copy()
            _f.selection.select(g.encoding)
            _f.paste()
    # 0x0370 - 0x03ff - GREEK
    for g in dejavu.glyphs():
        if g.encoding < 0x0370 or g.encoding > 0x03ff:
            continue
        else:
            if len(g.references) == 0:
                bb = g.boundingBox()
                g.anchorPoints = (('Anchor-7', 'mark', 256, bb[3] + 20), )
                dejavu.selection.select(g.encoding)
                dejavu.copy()
                _f.selection.select(g.encoding)
                _f.paste()
    # 0x2100 - 0x214f Letterlike Symbols
    for g in dejavu.glyphs():
        if g.encoding < 0x2100 or g.encoding > 0x214f or g.encoding == 0x2122:
            continue
        else:
            if len(g.references) == 0:
                dejavu.selection.select(g.encoding)
                dejavu.copy()
                _f.selection.select(g.encoding)
                _f.paste()
    # 0x2150 - 0x218f Number Forms
    for g in dejavu.glyphs():
        if g.encoding < 0x2150 or g.encoding > 0x218f:
            continue
        else:
            if len(g.references) == 0:
                dejavu.selection.select(g.encoding)
                dejavu.copy()
                _f.selection.select(g.encoding)
                _f.paste()
    # 0x2190 - 0x21ff Arrows
    for g in dejavu.glyphs():
        if g.encoding < 0x2190 or g.encoding > 0x21ff:
            continue
        else:
            if len(g.references) == 0:
                dejavu.selection.select(g.encoding)
                dejavu.copy()
                _f.selection.select(g.encoding)
                _f.paste()
    # 0x2200 - 0x22ff Mathematical Operators
    for g in dejavu.glyphs():
        if g.encoding < 0x2200 or g.encoding > 0x22ff:
            continue
        else:
            if len(g.references) == 0:
                dejavu.selection.select(g.encoding)
                dejavu.copy()
                _f.selection.select(g.encoding)
                _f.paste()
    # 0x2300 - 0x23ff Miscellaneous Technical
    for g in dejavu.glyphs():
        if g.encoding < 0x2300 or g.encoding > 0x23ff:
            continue
        else:
            if len(g.references) == 0:
                dejavu.selection.select(g.encoding)
                dejavu.copy()
                _f.selection.select(g.encoding)
                _f.paste()
    dejavu.close()
    return _f
Example #40
0
base_font.generate("otf/" + base_font.fontname + ".otf")

base_font.printSample("fontdisplay", 24, "",
                      "specimens/" + base_font.fontname + ".pdf")

print("Generated regular")

base_font.close()

## condensed

base_font = fontforge.open("sfd/14seg-gen.sfd")

base_font.selection.all()

matrix = psMat.scale(0.5, 1.0)

base_font.transform(matrix)

base_font.fullname = "LCD Display: 14 Segment (Condensed)"

base_font.fontname = "LCD14Condensed"

base_font.os2_width = 3  # Condensed

base_font.save("sfd/14seg-condensed.sfd")

base_font.generate("otf/" + base_font.fontname + ".otf")

base_font.printSample("fontdisplay", 24, "",
                      "specimens/" + base_font.fontname + ".pdf")
Example #41
0
def makeQuran(infile, outfile, feafile, version):
    font = makeDesktop(infile, outfile, feafile, version, False, False)

    # fix metadata
    font.fontname = font.fontname.replace("-Regular", "Quran-Regular")
    font.familyname += " Quran"
    font.fullname += " Quran"

    digits = ("zero", "one", "two", "three", "four", "five", "six",
              "seven", "eight", "nine")

    mergeLatin(font, feafile, glyphs=digits, quran=True)

    punct = ("period", "guillemotleft", "guillemotright", "braceleft", "bar",
             "braceright", "bracketleft", "bracketright", "parenleft",
             "parenright", "slash", "backslash")

    for name in punct:
        if name+".ara" in font:
            glyph = font[name+".ara"]
            glyph.glyphname = name
            glyph.unicode = fontforge.unicodeFromName(name)

    # abuse U+065C as a below form of U+06EC, for Qaloon
    dotabove = font["uni06EC"]
    dotbelow = font["uni065C"]
    delta = dotbelow.boundingBox()[-1] - dotabove.boundingBox()[-1]
    dotbelow.references = []
    dotbelow.addReference(dotabove.glyphname, psMat.translate(0, delta))
    dotbelow.addAnchorPoint("TashkilTashkilBelow", "basemark", 220, dotbelow.boundingBox()[1] - 100)

    # scale some vowel marks and dots down a bit
    font["uni0651"].transform(psMat.scale(0.8))
    for mark in ("uni064B", "uni064C", "uni064E", "uni064F", "uni06E1"):
        font[mark].transform(psMat.scale(0.9))

    for dot in ("TwoDots.a", "ThreeDots.a", "vTwoDots.a"):
        font[dot].transform(psMat.scale(0.9))

    quran_glyphs = []

    # create dummy glyphs used for some coding hacks
    for i in range(1, 11):
        dummy = font.createChar(-1, "dummy%s" %i)
        dummy.width = 0
        quran_glyphs.append(dummy.glyphname)

    mergeFeatures(font, feafile)

    quran_glyphs += digits
    quran_glyphs += punct
    quran_glyphs += ("space",
            "uni060C", "uni0615", "uni0617", "uni0618", "uni0619", "uni061A",
            "uni061B", "uni061E", "uni061F", "uni0621", "uni0622", "uni0623",
            "uni0624", "uni0625", "uni0626", "uni0627", "uni0628", "uni0629",
            "uni062A", "uni062B", "uni062C", "uni062D", "uni062E", "uni062F",
            "uni0630", "uni0631", "uni0632", "uni0633", "uni0634", "uni0635",
            "uni0636", "uni0637", "uni0638", "uni0639", "uni063A", "uni0640",
            "uni0641", "uni0642", "uni0643", "uni0644", "uni0645", "uni0646",
            "uni0647", "uni0648", "uni0649", "uni064A", "uni064B", "uni064C",
            "uni064D", "uni064E", "uni064F", "uni0650", "uni0651", "uni0652",
            "uni0653", "uni0654", "uni0655", "uni0656", "uni0657", "uni0658",
            "uni065C", "uni0660", "uni0661", "uni0662", "uni0663", "uni0664",
            "uni0665", "uni0666", "uni0667", "uni0668", "uni0669", "uni066E",
            "uni066F", "uni06A1", "uni06BA", "uni0670", "uni0671", "uni067A",
            "uni06CC", "uni06D6", "uni06D7", "uni06D8", "uni06D9", "uni06DA",
            "uni06DB", "uni06DC", "uni06DD", "uni06DE", "uni06DF", "uni06E0",
            "uni06E1", "uni06E2", "uni06E3", "uni06E4", "uni06E5", "uni06E6",
            "uni06E7", "uni06E8", "uni06E9", "uni06EA", "uni06EB", "uni06EC",
            "uni06ED", "uni06F0", "uni06F1", "uni06F2", "uni06F3", "uni06F4",
            "uni06F5", "uni06F6", "uni06F7", "uni06F8", "uni06F9", "uni08F0",
            "uni08F1", "uni08F2", "uni2000", "uni2001", "uni2002", "uni2003",
            "uni2004", "uni2005", "uni2006", "uni2007", "uni2008", "uni2009",
            "uni200A", "uni200B", "uni200C", "uni200D", "uni200E", "uni200F",
            "uni2028", "uni2029", "uni202A", "uni202B", "uni202C", "uni202D",
            "uni202E", "uni202F", "uni25CC", "uniFDFA", "uniFDFD")
    quran_glyphs += ("uni030A", "uni0325") # ring above and below

    subsetFont(font, quran_glyphs, True)

    # set font ascent to the highest glyph in the font so that waqf marks don't
    # get truncated
    # we could have set os2_typoascent_add and hhea_ascent_add, but ff makes
    # the offset relative to em-size in the former and font bounds in the
    # later, but we want both to be relative to font bounds
    ymax = 0
    for glyph in font.glyphs():
        bb = glyph.boundingBox()
        if bb[-1] > ymax:
            ymax = bb[-1]

    font.os2_typoascent = font.hhea_ascent = ymax

    # create overline glyph to be used for sajda line, it is positioned
    # vertically at the level of the base of waqf marks
    overline_pos = font[0x06D7].boundingBox()[1]
    makeOverUnderline(font, under=False, o_pos=overline_pos)

    generateFont(font, outfile)
Example #42
0
def scale(glyph, scalex, scaley):
    glyph.transform(psMat.scale(scalex, scaley))
Example #43
0
def matRescale(origin_x, origin_y, scale_x, scale_y):
    return psMat.compose(
        psMat.translate(-origin_x, -origin_y), psMat.compose(
        psMat.scale(scale_x, scale_y), 
        psMat.translate(origin_x, origin_y)))
Example #44
0
def modify_nerd(_g):
    align_left = [
        0xe0b0,
        0xe0b1,
        0xe0b4,
        0xe0b5,
        0xe0b8,
        0xe0b9,
        0xe0bc,
        0xe0bd,
        0xe0c0,
        0xe0c1,
        0xe0c4,
        0xe0c6,
        0xe0c8,
        0xe0cc,
        0xe0cd,
        0xe0d1,
        0xe0d2,
    ]
    align_right = [
        0xe0b2,
        0xe0b3,
        0xe0b6,
        0xe0b7,
        0xe0b7,
        0xe0ba,
        0xe0bb,
        0xe0be,
        0xe0bf,
        0xe0c2,
        0xe0c3,
        0xe0c5,
        0xe0c7,
        0xe0ca,
        0xe0ce,
        0xe0d4,
    ]
    # Powerline
    if _g.encoding >= 0xe0b0 and _g.encoding <= 0xe0d4:
        _g.transform(psMat.translate(0, -55))
        _g.width = 1024

        if _g.encoding >= 0xe0b0 and _g.encoding <= 0xe0b7:
            _g.transform(
                psMat.compose(psMat.scale(1.0, 0.982), psMat.translate(0, -1)))
            if _g.encoding in align_right:
                bb = _g.boundingBox()
                left = 1024 - (bb[2] - bb[0])
                _g.left_side_bearing = left
                _g.width = 1024
            if _g.encoding in align_left:
                _g.left_side_bearing = 0
                _g.width = 1024

        if _g.encoding >= 0xe0b8 and _g.encoding <= 0xe0bf:
            _g.transform(
                psMat.compose(psMat.scale(0.8, 0.982), psMat.translate(0, -1)))
            if _g.encoding in align_right:
                bb = _g.boundingBox()
                left = 1024 - (bb[2] - bb[0])
                _g.left_side_bearing = left
                _g.width = 1024
            if _g.encoding in align_left:
                _g.left_side_bearing = 0
                _g.width = 1024

        if _g.encoding >= 0xe0c0 and _g.encoding <= 0xe0c3:
            _g.transform(psMat.scale(0.7, 1.0))
            if _g.encoding in align_right:
                bb = _g.boundingBox()
                left = 1024 - (bb[2] - bb[0])
                _g.left_side_bearing = left
                _g.width = 1024
            if _g.encoding in align_left:
                _g.left_side_bearing = 0
                _g.width = 1024
        if _g.encoding >= 0xe0c4 and _g.encoding <= 0xe0c7:
            if _g.encoding in align_right:
                bb = _g.boundingBox()
                left = 1024 - (bb[2] - bb[0])
                _g.left_side_bearing = left
                _g.width = 1024
            if _g.encoding in align_left:
                _g.left_side_bearing = 0
                _g.width = 1024
        if _g.encoding == 0xe0c8 or _g.encoding == 0xe0ca:
            _g.transform(psMat.scale(0.7, 1.0))
            if _g.encoding in align_right:
                bb = _g.boundingBox()
                left = 1024 - (bb[2] - bb[0])
                _g.left_side_bearing = left
                _g.width = 1024
            if _g.encoding in align_left:
                _g.left_side_bearing = 0
                _g.width = 1024
        if _g.encoding == 0xe0ce:
            _g.transform(psMat.scale(0.8, 1.0))
            bb = _g.boundingBox()
            left = 1024 - (bb[2] - bb[0])
            _g.left_side_bearing = left
            _g.width = 1024
        if _g.encoding == 0xe0cf:
            _g.transform(psMat.scale(0.9, 1.0))
            _g = align_to_center(_g)
        if _g.encoding == 0xe0d0:
            _g = align_to_center(_g)
        if _g.encoding == 0xe0d1:
            _g.transform(
                psMat.compose(psMat.scale(1.0, 0.982), psMat.translate(0, -1)))
            _g.left_side_bearing = 0
            _g.width = 1024
        if _g.encoding == 0xe0d2 or _g.encoding == 0xe0d4:
            _g.transform(
                psMat.compose(psMat.scale(1.0, 0.982), psMat.translate(0, -1)))
            if _g.encoding in align_right:
                bb = _g.boundingBox()
                left = 1024 - (bb[2] - bb[0])
                _g.left_side_bearing = left
                _g.width = 1024
            if _g.encoding in align_left:
                _g.left_side_bearing = 0
                _g.width = 1024
    elif _g.encoding >= 0xf000 and _g.encoding <= 0xf2e0:
        _g.transform(
            psMat.compose(psMat.scale(0.75, 0.75), psMat.translate(0, 55)))
        _g.width = 1024
        _g = align_to_center(_g)
    else:
        _g.transform(psMat.translate(0, -55))
        _g.width = 1024
        _g = align_to_center(_g)

    return _g
Example #45
0
	if not os.path.exists(sys.argv[arg]):
		print ("ファイル名 " + sys.argv[arg] + " が見つかりません。")
		exit(0)

# 拡縮倍率
scale_x = 0.8
scale_y = 0.9


cidFontFileName = sys.argv[1]

# ファイルを開く
cidFont = fontforge.open(cidFontFileName)

#cidFont.em = 1000

for g in cidFont.glyphs():
	prevWidth = g.width
	prevWidth = 500
	g.transform(psMat.scale(scale_x, scale_y));
	movedist = prevWidth / 2 - g.width / 2;
	g.width = prevWidth;
	g.transform(psMat.translate(movedist, 0));
	g.width = prevWidth;

cidFont.generate(sys.argv[2] + ".ps")
#cidFont.save(sys.argv[2]+".sfd")
cidFont.close()


Example #46
0
def resize_supersub(_f):
    superscripts = [
        {
            "src": 0x0031,
            "dest": 0x00b9
        },
        {
            "src": 0x0032,
            "dest": 0x00b2
        },
        {
            "src": 0x0033,
            "dest": 0x00b3
        },
        {
            "src": 0x0030,
            "dest": 0x2070
        },
        {
            "src": 0x0069,
            "dest": 0x2071
        },
        {
            "src": 0x0034,
            "dest": 0x2074
        },
        {
            "src": 0x0037,
            "dest": 0x2077
        },
        {
            "src": 0x0038,
            "dest": 0x2078
        },
        {
            "src": 0x0039,
            "dest": 0x2079
        },
        {
            "src": 0x002b,
            "dest": 0x207a
        },
        {
            "src": 0x002d,
            "dest": 0x207b
        },
        {
            "src": 0x003d,
            "dest": 0x207c
        },
        {
            "src": 0x0028,
            "dest": 0x207d
        },
        {
            "src": 0x0029,
            "dest": 0x207e
        },
        {
            "src": 0x006e,
            "dest": 0x207f
        },
        # ↓上付きの大文字
        {
            "src": 0x0041,
            "dest": 0x1d2c
        },
        {
            "src": 0x00c6,
            "dest": 0x1d2d
        },
        {
            "src": 0x0042,
            "dest": 0x1d2e
        },
        {
            "src": 0x0044,
            "dest": 0x1d30
        },
        {
            "src": 0x0045,
            "dest": 0x1d31
        },
        {
            "src": 0x018e,
            "dest": 0x1d32
        },
        {
            "src": 0x0047,
            "dest": 0x1d33
        },
        {
            "src": 0x0048,
            "dest": 0x1d34
        },
        {
            "src": 0x0049,
            "dest": 0x1d35
        },
        {
            "src": 0x004a,
            "dest": 0x1d36
        },
        {
            "src": 0x004b,
            "dest": 0x1d37
        },
        {
            "src": 0x004c,
            "dest": 0x1d38
        },
        {
            "src": 0x004d,
            "dest": 0x1d39
        },
        {
            "src": 0x004e,
            "dest": 0x1d3a
        },
        ## ↓REVERSED N なのでNを左右反転させる必要あり
        {
            "src": 0x004e,
            "dest": 0x1d3b,
            "reversed": True
        },
        {
            "src": 0x004f,
            "dest": 0x1d3c
        },
        {
            "src": 0x0222,
            "dest": 0x1d3d
        },
        {
            "src": 0x0050,
            "dest": 0x1d3e
        },
        {
            "src": 0x0052,
            "dest": 0x1d3f
        },
        {
            "src": 0x0054,
            "dest": 0x1d40
        },
        {
            "src": 0x0055,
            "dest": 0x1d41
        },
        {
            "src": 0x0057,
            "dest": 0x1d42
        },
        # ↓上付きの小文字
        {
            "src": 0x0061,
            "dest": 0x1d43
        },
        {
            "src": 0x0250,
            "dest": 0x1d44
        },
        {
            "src": 0x0251,
            "dest": 0x1d45
        },
        {
            "src": 0x1d02,
            "dest": 0x1d46
        },
        {
            "src": 0x0062,
            "dest": 0x1d47
        },
        {
            "src": 0x0064,
            "dest": 0x1d48
        },
        {
            "src": 0x0065,
            "dest": 0x1d49
        },
        {
            "src": 0x0259,
            "dest": 0x1d4a
        },
        {
            "src": 0x025b,
            "dest": 0x1d4b
        },
        {
            "src": 0x025c,
            "dest": 0x1d4c
        },
        {
            "src": 0x0067,
            "dest": 0x1d4d
        },
        ## ↓TURNED i なので 180度回す必要あり
        {
            "src": 0x0069,
            "dest": 0x1d4e,
            "turned": True
        },
        {
            "src": 0x006b,
            "dest": 0x1d4f
        },
        {
            "src": 0x006d,
            "dest": 0x1d50
        },
        {
            "src": 0x014b,
            "dest": 0x1d51
        },
        {
            "src": 0x006f,
            "dest": 0x1d52
        },
        {
            "src": 0x0254,
            "dest": 0x1d53
        },
        {
            "src": 0x1d16,
            "dest": 0x1d54
        },
        {
            "src": 0x1d17,
            "dest": 0x1d55
        },
        {
            "src": 0x0070,
            "dest": 0x1d56
        },
        {
            "src": 0x0074,
            "dest": 0x1d57
        },
        {
            "src": 0x0075,
            "dest": 0x1d58
        },
        {
            "src": 0x1d1d,
            "dest": 0x1d59
        },
        {
            "src": 0x026f,
            "dest": 0x1d5a
        },
        {
            "src": 0x0076,
            "dest": 0x1d5b
        },
        {
            "src": 0x1d25,
            "dest": 0x1d5c
        },
        {
            "src": 0x03b2,
            "dest": 0x1d5d
        },
        {
            "src": 0x03b3,
            "dest": 0x1d5e
        },
        {
            "src": 0x03b4,
            "dest": 0x1d5f
        },
        {
            "src": 0x03c6,
            "dest": 0x1d60
        },
        {
            "src": 0x03c7,
            "dest": 0x1d61
        },
        {
            "src": 0x0056,
            "dest": 0x2c7d
        },
        {
            "src": 0x0068,
            "dest": 0x02b0
        },
        {
            "src": 0x0266,
            "dest": 0x02b1
        },
        {
            "src": 0x006a,
            "dest": 0x02b2
        },
        {
            "src": 0x006c,
            "dest": 0x02e1
        },
        {
            "src": 0x0073,
            "dest": 0x02e2
        },
        {
            "src": 0x0078,
            "dest": 0x02e3
        },
        {
            "src": 0x0072,
            "dest": 0x02b3
        },
        {
            "src": 0x0077,
            "dest": 0x02b7
        },
        {
            "src": 0x0079,
            "dest": 0x02b8
        },
        {
            "src": 0x0063,
            "dest": 0x1d9c
        },
        {
            "src": 0x0066,
            "dest": 0x1da0
        },
        {
            "src": 0x007a,
            "dest": 0x1dbb
        },
        {
            "src": 0x0061,
            "dest": 0x00aa
        },
        {
            "src": 0x0252,
            "dest": 0x1d9b
        },
        {
            "src": 0x0255,
            "dest": 0x1d9d
        },
        {
            "src": 0x00f0,
            "dest": 0x1d9e
        },
        {
            "src": 0x025c,
            "dest": 0x1d9f
        },
        {
            "src": 0x025f,
            "dest": 0x1da1
        },
        {
            "src": 0x0261,
            "dest": 0x1da2
        },
        {
            "src": 0x0265,
            "dest": 0x1da3
        },
        {
            "src": 0x0268,
            "dest": 0x1da4
        },
        {
            "src": 0x0269,
            "dest": 0x1da5
        },
        {
            "src": 0x026a,
            "dest": 0x1da6
        },
        {
            "src": 0x1d7b,
            "dest": 0x1da7
        },
        {
            "src": 0x029d,
            "dest": 0x1da8
        },
        {
            "src": 0x026d,
            "dest": 0x1da9
        },
        {
            "src": 0x1d85,
            "dest": 0x1daa
        },
        {
            "src": 0x029f,
            "dest": 0x1dab
        },
        {
            "src": 0x0271,
            "dest": 0x1dac
        },
        {
            "src": 0x0270,
            "dest": 0x1dad
        },
        {
            "src": 0x0272,
            "dest": 0x1dae
        },
        {
            "src": 0x0273,
            "dest": 0x1daf
        },
        {
            "src": 0x0274,
            "dest": 0x1db0
        },
        {
            "src": 0x0275,
            "dest": 0x1db1
        },
        {
            "src": 0x0278,
            "dest": 0x1db2
        },
        {
            "src": 0x0282,
            "dest": 0x1db3
        },
        {
            "src": 0x0283,
            "dest": 0x1db4
        },
        {
            "src": 0x01ab,
            "dest": 0x1db5
        },
        {
            "src": 0x0289,
            "dest": 0x1db6
        },
        {
            "src": 0x028a,
            "dest": 0x1db7
        },
        {
            "src": 0x1d1c,
            "dest": 0x1db8
        },
        {
            "src": 0x028b,
            "dest": 0x1db9
        },
        {
            "src": 0x028c,
            "dest": 0x1dba
        },
        {
            "src": 0x0290,
            "dest": 0x1dbc
        },
        {
            "src": 0x0291,
            "dest": 0x1dbd
        },
        {
            "src": 0x0292,
            "dest": 0x1dbe
        },
        {
            "src": 0x03b8,
            "dest": 0x1dbf
        },
    ]
    subscripts = [{
        "src": 0x0069,
        "dest": 0x1d62
    }, {
        "src": 0x0072,
        "dest": 0x1d63
    }, {
        "src": 0x0075,
        "dest": 0x1d64
    }, {
        "src": 0x0076,
        "dest": 0x1d65
    }, {
        "src": 0x03b2,
        "dest": 0x1d66
    }, {
        "src": 0x03b3,
        "dest": 0x1d67
    }, {
        "src": 0x03c1,
        "dest": 0x1d68
    }, {
        "src": 0x03c6,
        "dest": 0x1d69
    }, {
        "src": 0x03c7,
        "dest": 0x1d6a
    }, {
        "src": 0x006a,
        "dest": 0x2c7c
    }, {
        "src": 0x0030,
        "dest": 0x2080
    }, {
        "src": 0x0031,
        "dest": 0x2081
    }, {
        "src": 0x0032,
        "dest": 0x2082
    }, {
        "src": 0x0033,
        "dest": 0x2083
    }, {
        "src": 0x0034,
        "dest": 0x2084
    }, {
        "src": 0x0035,
        "dest": 0x2085
    }, {
        "src": 0x0036,
        "dest": 0x2086
    }, {
        "src": 0x0037,
        "dest": 0x2087
    }, {
        "src": 0x0038,
        "dest": 0x2088
    }, {
        "src": 0x0039,
        "dest": 0x2089
    }, {
        "src": 0x002b,
        "dest": 0x208a
    }, {
        "src": 0x002d,
        "dest": 0x208b
    }, {
        "src": 0x003d,
        "dest": 0x208c
    }, {
        "src": 0x0028,
        "dest": 0x208d
    }, {
        "src": 0x0029,
        "dest": 0x208e
    }, {
        "src": 0x0061,
        "dest": 0x2090
    }, {
        "src": 0x0065,
        "dest": 0x2091
    }, {
        "src": 0x006f,
        "dest": 0x2092
    }, {
        "src": 0x0078,
        "dest": 0x2093
    }, {
        "src": 0x0259,
        "dest": 0x2094
    }, {
        "src": 0x0068,
        "dest": 0x2095
    }, {
        "src": 0x006b,
        "dest": 0x2096
    }, {
        "src": 0x006c,
        "dest": 0x2097
    }, {
        "src": 0x006d,
        "dest": 0x2098
    }, {
        "src": 0x006e,
        "dest": 0x2099
    }, {
        "src": 0x0070,
        "dest": 0x209a
    }, {
        "src": 0x0073,
        "dest": 0x209b
    }, {
        "src": 0x0074,
        "dest": 0x209c
    }]

    for g in superscripts:
        _f.selection.select(g["src"])
        _f.copy()
        _f.selection.select(g["dest"])
        _f.paste()
    for g in subscripts:
        _f.selection.select(g["src"])
        _f.copy()
        _f.selection.select(g["dest"])
        _f.paste()

    for g in _f.glyphs("encoding"):
        if g.encoding > 0x2c7d:
            continue
        elif in_scripts(g.encoding, superscripts):
            if g.encoding == 0x1d5d or g.encoding == 0x1d61:
                g.transform(psMat.scale(0.70, 0.70))
            elif g.encoding == 0x1d3b:
                g.transform(psMat.scale(0.75, 0.75))
                g.transform(
                    psMat.compose(psMat.scale(-1, 1),
                                  psMat.translate(g.width, 0)))
            elif g.encoding == 0x1d4e:
                g.transform(psMat.scale(0.75, 0.75))
                g.transform(psMat.rotate(3.14159))
                g.transform(psMat.translate(0, 512))
            else:
                g.transform(psMat.scale(0.75, 0.75))
            bb = g.boundingBox()
            g.transform(psMat.translate(0, 244))
            align_to_center(g)
        elif in_scripts(g.encoding, subscripts):
            if g.encoding == 0x1d66 or g.encoding == 0x1d6a:
                g.transform(psMat.scale(0.70, 0.70))
            else:
                g.transform(psMat.scale(0.75, 0.75))
            bb = g.boundingBox()
            y = -144
            if bb[1] < -60:  # DESCENT - 144
                y = -60
            g.transform(psMat.translate(0, y))
            align_to_center(g)
    return _f
Example #47
0
def _set_proportion(font):
    mat = scale(SCALE_DOWN)
    font.selection.all()
    for glyph in list(font.selection.byGlyphs):
        glyph.transform(mat)
        glyph.width = WIDTH
Example #48
0
    circled.addReference(sc_name,
                         psMat.translate((circle_width - sc.width) / 2, 0))
    circled.addReference('modifier_circle')
    circled.width = circle_width

    modifier_lines_width = iso['modifier_lines'].width
    # create left variant
    modifier_left_width = iso['modifier_left'].width
    left = iso.createChar(-1,
                          name + gm.suffixes.small_caps + gm.suffixes.modleft)
    left.addReference('modifier_left')
    left.addReference(sc_name,
                      psMat.translate(modifier_left_width - (sc.width / 2), 0))
    left.addReference(
        'modifier_lines',
        psMat.compose(psMat.scale(sc.width / 2 / modifier_lines_width, 1),
                      psMat.translate(modifier_left_width, 0)))
    left.width = modifier_left_width + (sc.width / 2)
    # create right variant
    modifier_right_width = iso['modifier_right'].width
    right = iso.createChar(
        -1, name + gm.suffixes.small_caps + gm.suffixes.modright)
    right.addReference('modifier_right', psMat.translate(sc.width / 2, 0))
    right.addReference(sc_name)
    right.addReference(
        'modifier_lines',
        psMat.scale(sc.width / 2 / modifier_lines_width, 1),
    )
    right.width = modifier_left_width + (sc.width / 2)

    # create inline variant
Example #49
0
#!/usr/bin/python
# -*- coding: utf-8 -*-

# 花園明朝フォント(実験版)を生成する。
# 注意! UCS4オプションでコンパイルしたPythonを使うこと!
# 確認方法: ord(u'𠀀’) がちゃんと#x20000 になるかどうか。

import fontforge
import psMat
import sys, os, re, fnmatch, codecs

mat1 = psMat.scale(1.05,1.05)
mat2 = psMat.translate(-25,-25)
mat3 = psMat.translate(-256,0)
mat4 = psMat.scale(1.0, 2.0)
aalt = {} # add_aalt で異体字を入れる。溢れないよう、数は抑制する。
vari_dir = '/home/kawabata/Dropbox/cvs/kanji-database/variants/'

def make_font (name,style,version):
    global aalt
    font=fontforge.open("./basefont.ttf")
    font.os2_width=1024
    aalt = {}
    font.sfntRevision = float(version)
    fullname_en="Hanazono Mincho "+style
    fullname_ja="花園明朝 "+style
    print ("now generating "+fullname_en+" ("+fullname_ja+")")
    # 注意。
    # pid=1,eid=0,lid=0x0   の、id=4 は、自由文字列 (Hanazono-Mincho B) でいいが、
    # pid=3,eid=1,lid=0x409 の、id=4 は、pid=3,eid=1,lid=0x409 の、id=6と同じでなければいけない。
    # fontforgeでは、両方は同じである必要があるので、これは変更できない。
Example #50
0
def m_scale(scaleX, scaleY):
    return m_compose(psMat.translate(-c_halfsize, -c_middle),
                     psMat.scale(scaleX, scaleY),
                     psMat.translate(c_halfsize, c_middle))
Example #51
0
#Needs: fonts/StrokeTests.sfd

import sys, fontforge, psMat

stroketests = sys.argv[1]

print("triangle")
font = fontforge.open(stroketests)
font.selection.all()
triangle = fontforge.unitShape(3).transform(psMat.scale(25))
font.stroke("polygonal", triangle)
font.close()

print("square")
font = fontforge.open(stroketests)
font.selection.all()
square = fontforge.unitShape(4).transform(psMat.scale(25))
font.stroke("polygonal", square)
font.close()

print("pentagon")
font = fontforge.open(stroketests)
font.selection.all()
pent = fontforge.unitShape(5).transform(psMat.scale(25))
font.stroke("polygonal", pent)
font.close()

print("circular")
font = fontforge.open(stroketests)
font.selection.all()
font.stroke("circular", 25)
Example #52
0
def matRescale(origin_x, origin_y, scale_x, scale_y):
    return psMat.compose(
        psMat.translate(-origin_x, -origin_y),
        psMat.compose(psMat.scale(scale_x, scale_y),
                      psMat.translate(origin_x, origin_y)))
Example #53
0
          lastX = point.x; lastY = point.y
    if hypot(firstX - lastX, firstY - lastY) > 3.0:
      newContour += tmpContour
    newContour.closed = True
    newLayer += newContour
  glyph.foreground = newLayer

if (len(sys.argv) < 3):
  print 'Usage: %s source-file target-file' % sys.argv[0]
  quit(1)

print 'Loading base file %s...' % sys.argv[1]
BaseFont = fontforge.open(sys.argv[1])

for glyph in BaseFont.glyphs():
  if glyph.isWorthOutputting():
    if isJGlyphP(glyph):
      glyph.unlinkRef()

print 'Changing weight...'
for glyph in BaseFont.glyphs():
  if glyph.isWorthOutputting():
    if isJGlyph(glyph):
      glyph.transform(psMat.scale(2.0))
      glyph.stroke("circular", 10, "butt", "miter", ("removeexternal", "cleanup"))
      fixContour(glyph)
      glyph.transform(psMat.scale(0.5))

print 'Saving target file %s...' % sys.argv[2]
BaseFont.save(sys.argv[2])
Example #54
0
    def patch(self):
        for target_font in self.target_fonts:
            source_font = self.source_font
            target_font_em_original = target_font.em
            target_font.em = 2048
            target_font.encoding = 'ISO10646'

            # Rename font
            if self.rename_font:
                target_font.familyname += ' for Kovid'
                target_font.fullname += ' for Kovid'
                fontname, style = re.match("^([^-]*)(?:(-.*))?$",
                                           target_font.fontname).groups()
                target_font.fontname = fontname + 'ForKovid'
                if style is not None:
                    target_font.fontname += style
                target_font.appendSFNTName('English (US)', 'Preferred Family',
                                           target_font.familyname)
                target_font.appendSFNTName('English (US)', 'Compatible Full',
                                           target_font.fullname)

            source_bb = source_font['block'].boundingBox()
            target_bb = [0, 0, 0, 0]
            target_font_width = 0

            # Find the biggest char width and height in the Latin-1 extended range and the box drawing range
            # This isn't ideal, but it works fairly well - some fonts may need tuning after patching
            for cp in chain(range(0x00, 0x17f), range(0x2500, 0x2600)):
                try:
                    bbox = target_font[cp].boundingBox()
                except TypeError:
                    continue
                if not target_font_width:
                    target_font_width = target_font[cp].width
                if bbox[0] < target_bb[0]:
                    target_bb[0] = bbox[0]
                if bbox[1] < target_bb[1]:
                    target_bb[1] = bbox[1]
                if bbox[2] > target_bb[2]:
                    target_bb[2] = bbox[2]
                if bbox[3] > target_bb[3]:
                    target_bb[3] = bbox[3]

            # Find source and target size difference for scaling
            x_ratio = (target_bb[2] - target_bb[0]) / (source_bb[2] -
                                                       source_bb[0])
            y_ratio = (target_bb[3] - target_bb[1]) / (source_bb[3] -
                                                       source_bb[1])
            scale = psMat.scale(x_ratio, y_ratio)

            # Find source and target midpoints for translating
            x_diff = target_bb[0] - source_bb[0]
            y_diff = target_bb[1] - source_bb[1]
            translate = psMat.translate(x_diff, y_diff)
            transform = psMat.compose(scale, translate)

            # Create new glyphs from symbol font
            for source_glyph in source_font.glyphs():
                if source_glyph == source_font['block']:
                    # Skip the symbol font block glyph
                    continue

                # Select and copy symbol from its encoding point
                source_font.selection.select(source_glyph.encoding)
                source_font.copy()

                # Select and paste symbol to its unicode code point
                target_font.selection.select(source_glyph.unicode)
                target_font.paste()

                # Transform the glyph
                target_font.transform(transform)

                # Reset the font's glyph width so it's still considered monospaced
                target_font[source_glyph.unicode].width = target_font_width

            target_font.em = target_font_em_original

            # Generate patched font
            extension = os.path.splitext(target_font.path)[1]
            if extension.lower() not in ['.ttf', '.otf']:
                # Default to OpenType if input is not TrueType/OpenType
                extension = '.otf'
            target_font.generate(
                os.path.join(self.destdir,
                             '{0}{1}'.format(target_font.fullname, extension)))
    font = fontforge.font()
    font.fontname = FONTNAME
    font.familyname = FONTNAME
    font.copyright = 'Some of symbols are imported from FontAwesome SVGs'
    font.fullname = FONTNAME

    try:
        for svg_file in os.listdir(DIR):
            if svg_file.find('.svg') == -1:  # is not a svg file
                continue
            g = font.createChar(int(svg_file.split('-')[0], base=16))
            print(svg_file)
            g.importOutlines(os.path.join(DIR, svg_file),
                             ('removeoverlap', 'correctdir'))
            g.removeOverlap()
            move_mat = psMat.translate(-100, 0)
            g.transform(move_mat)
            scale_mat = psMat.scale(1.1)
            g.transform(scale_mat)
    except ValueError:
        print('"%s" is not a valid file name.' % svg_file)
        print(
            'File name should be in format "hexnumber-name.svg". e.g. "ff5a-search.svg"'
        )

    except Exception as e:
        raise e

    font.generate('%s.ttf' % FONTNAME)
Example #56
0
#Needs: fonts/StrokeTests.sfd

import sys, fontforge, psMat, math
from collections import OrderedDict

stroketests = sys.argv[1]
shortlist = ['D', 'Q', 'asciicircum']
convex = fontforge.unitShape(7).transform(psMat.scale(25))

def do_stroke_test(short, *args, **kwargs):
    font=fontforge.open(stroketests)
    if short:
        font.selection.select(*shortlist)
    else:
        font.selection.all()
    font.stroke(*args, **kwargs)
    font.close()

# Full font tests
shapes = OrderedDict()
shapes['triangle'] = fontforge.unitShape(3).transform(psMat.scale(25))
shapes['square'] = fontforge.unitShape(4).transform(psMat.scale(25))
shapes['pentagon'] = fontforge.unitShape(5).transform(psMat.scale(25))
shapes['circular'] = (25,)
shapes['calligraphic'] = (25, 2, 45)

for sn, s in shapes.items():
    print(sn)
    if isinstance(s, tuple):
        do_stroke_test(False, sn, *s)
    else:
Example #57
0
else:  # Widen
    WidthInterpol = BaseFont.interpolateFonts((float(argv[3]) - 1.0) * 5.0,
                                              ExpandedFontFile)
MidInterpol = WeightInterpol.interpolateFonts(0.5, WidthInterpol.path)
Interpolated = BaseFont.interpolateFonts(2.0, MidInterpol.path)
WeightInterpol.close()
WeightInterpol = None
WidthInterpol.close()
WidthInterpol = None
MidInterpol.close()
MidInterpol = None

# Change width of font
for glyph in BaseFont.glyphs():
    if glyph.isWorthOutputting():
        glyph.transform(scale(float(argv[3]), 1.0), ("partialRefs", ))
(kernFirst, kernSecond, kernVal) = BaseFont.getKerningClass("Kerning-1")
BaseFont.alterKerningClass(
    "Kerning-1", kernFirst, kernSecond,
    tuple(map(lambda x: int(round(float(x) * float(argv[3]))), kernVal)))

# Set output font properties
BaseFont.strokedfont = False
BaseFont.fontname = FamilyName + WidthDat[WidthCode]['Name'] + "-" + WeightDat[
    WeightCode]['Name']
BaseFont.familyname = HumanReadableFamilyName + WidthDat[WidthCode][
    'HumanReadableName']
BaseFont.fullname = HumanReadableFamilyName + WidthDat[WidthCode][
    'Abbr'] + " " + WeightDat[WeightCode]['Abbr']
BaseFont.weight = WeightDat[WeightCode]['HumanReadableName']
BaseFont.os2_weight = (WeightCode + 1) * 100
Example #58
0
de_font.selection.none()
# EastAsianWidthで全角(WまたはF)のグリフを削除
for glyph in de_font.glyphs():
    if glyph.unicode > 0 and unicodedata.east_asian_width(chr(
            glyph.unicode)) in ("W", "F"):
        de_font.selection.select(("more", ), glyph.glyphname)
de_font.clear()

# modify em
de_font.em = newfont_em
de_font.ascent = newfont_ascent
de_font.descent = newfont_descent

# scale down
for glyph in de_font.glyphs():
    glyph.transform(psMat.scale(0.83))
    glyph.width = 500

de_font.selection.all()
de_font.round()

de_font.generate("../Work/modDejaVu.ttf", '', generate_flags)
de_font.close()

########################################
# modified GenShin
########################################

print()
print("Open " + srcfont_GenShin)
fGs = fontforge.open(srcfont_GenShin)
Example #59
0
def copy_glyphs(sourceFont,
                sourceFontStart,
                sourceFontEnd,
                symbolFont,
                symbolFontStart,
                symbolFontEnd,
                exactEncoding=False):

    if exactEncoding is False:
        sourceFontList = []
        sourceFontCounter = 0

        for i in xrange(sourceFontStart, sourceFontEnd + 1):
            sourceFontList.append(format(i, 'X'))

    # Create glyphs from symbol font

    symbolFont.selection.select(("ranges", "unicode"), symbolFontStart,
                                symbolFontEnd)
    sourceFont.selection.select(("ranges", "unicode"), sourceFontStart,
                                sourceFontEnd)

    for sym_glyph in symbolFont.selection.byGlyphs:

        #sym_attr = SYM_ATTR[sym_glyph.unicode]
        glyphName = sym_glyph.glyphname

        if exactEncoding:
            # use the exact same hex values for the source font as for the symbol font
            currentSourceFontGlyph = sym_glyph.encoding
            copiedToSlot = str(sym_glyph.unicode)
        else:
            # use source font defined hex values based on passed in start and end
            # convince that this string really is a hex:
            currentSourceFontGlyph = int(
                "0x" + sourceFontList[sourceFontCounter], 16)
            copiedToSlot = sourceFontList[sourceFontCounter]

        if args.quiet == False:
            print "updating glyph: " + str(sym_glyph) + " " + str(
                sym_glyph.glyphname) + " putting at: " + str(copiedToSlot)

        # Prepare symbol glyph dimensions
        sym_dim = get_dim(sym_glyph)

        # Select and copy symbol from its encoding point
        symbolFont.selection.select(sym_glyph.encoding)
        symbolFont.copy()

        # check it
        if args.careful:

            if copiedToSlot.startswith("uni"):
                copiedToSlot = copiedToSlot[3:]

            codepoint = int("0x" + copiedToSlot, 16)
            try:
                sourceFont[codepoint]
            except TypeError:
                # nothing there go ahead and paste at this codepoint
                sourceFont.selection.select(currentSourceFontGlyph)
                sourceFont.paste()
        else:
            sourceFont.selection.select(currentSourceFontGlyph)
            sourceFont.paste()

        sourceFont[currentSourceFontGlyph].glyphname = glyphName

        if args.single:
            # Now that we have copy/pasted the glyph, it's time to scale and move it

            # Handle glyph stretching
            #if 'x' in sym_attr['stretch']:
            #        # Stretch the glyph horizontally
            #        scale_ratio = font_dim['width'] / sym_dim['width']

            #        sourceFont.transform(psMat.scale(scale_ratio, 1))
            #if 'y' in sym_attr['stretch']:
            #        # Stretch the glyph vertically
            #        scale_ratio = font_dim['height'] / sym_dim['height']

            #        sourceFont.transform(psMat.scale(1, scale_ratio))

            # Use the dimensions from the pasted and stretched glyph
            sym_dim = get_dim(sourceFont[currentSourceFontGlyph])

            # Center-align the glyph vertically
            font_ycenter = font_dim['height'] / 2
            sym_ycenter = sym_dim['height'] / 2

            # First move it to the ymax (top)
            sourceFont.transform(
                psMat.translate(0, font_dim['ymax'] - sym_dim['ymax']))

            # Then move it the y center difference
            sourceFont.transform(psMat.translate(0,
                                                 sym_ycenter - font_ycenter))

            # Ensure that the glyph doesn't extend outside the font's bounding box
            if sym_dim['width'] > font_dim['width']:
                # The glyph is too wide, scale it down to fit
                scale_matrix = psMat.scale(
                    font_dim['width'] / sym_dim['width'], 1)

                sourceFont.transform(scale_matrix)

                # Use the dimensions from the stretched glyph
                sym_dim = get_dim(sourceFont[currentSourceFontGlyph])

            # Handle glyph alignment
            #if sym_attr['align'] == 'c':
            #        # Center align
            #        align_matrix = psMat.translate(font_dim['width'] / 2 - sym_dim['width'] / 2 , 0)
            align_matrix = psMat.translate(
                font_dim['width'] / 2 - sym_dim['width'] / 2, 0)
            #elif sym_attr['align'] == 'r':
            #        # Right align
            #        align_matrix = psMat.translate(font_dim['width'] - sym_dim['width'], 0)
            #else:
            # No alignment (left alignment)
            #align_matrix = psMat.translate(0, 0)

            sourceFont.transform(align_matrix)

            #if sym_attr['overlap'] is True:
            #        overlap_width = sourceFont.em / 48

            #        # Stretch the glyph slightly horizontally if it should overlap
            #        sourceFont.transform(psMat.scale((sym_dim['width'] + overlap_width) / sym_dim['width'], 1))

            #        if sym_attr['align'] == 'l':
            #                # The glyph should be left-aligned, so it must be moved overlap_width to the left
            #                # This only applies to left-aligned glyphs because the glyph is scaled to the right
            #                sourceFont.transform(psMat.translate(-overlap_width, 0))

            # Ensure the font is considered monospaced on Windows
            sourceFont[currentSourceFontGlyph].width = font_dim['width']

        if exactEncoding is False:
            sourceFontCounter += 1

        # reset selection so iteration works propertly @todo fix? rookie misunderstanding?
        symbolFont.selection.select(("ranges", "unicode"), symbolFontStart,
                                    symbolFontEnd)
    # end for
    return