def _add_braille(font): font.selection.select(BLACK_CIRCLE) font.copy() font.selection.select(PRIVATE) font.paste() font.selection.select(PRIVATE) move_to_origin = translate(-512, -582.4) make_small = scale(BRAILLE_DIAMETER) for glyph in list(font.selection.byGlyphs): glyph.transform(compose(move_to_origin, make_small)) with BRAILLE_JSON.open() as f: braille = load(f) for b in braille: for p in b['points']: point = BRAILLE_POINTS[p] font.selection.select(PRIVATE) for glyph in list(font.selection.byGlyphs): glyph.transform(translate(point[0], point[1])) font.copy() font.selection.select(int(b['code'], 16)) font.pasteInto() for glyph in list(font.selection.byGlyphs): glyph.width = WIDTH font.selection.select(PRIVATE) for glyph in list(font.selection.byGlyphs): glyph.transform(translate(-point[0], -point[1])) font.selection.select(PRIVATE) font.cut()
def createDoubleAcute(font): glyph = None; # copy the single acute to the double acute position if glyphExists(font,0x00b4): font.selection.select(0x00b4); font.copy(); font.selection.select(0x02dd) font.paste(); glyph = font.createChar(0x02dd); elif glyphExists(font,0x02ca): font.selection.select(0x02ca); font.copy(); font.selection.select(0x02dd) font.paste(); glyph = font.createChar(0x02dd); elif glyphExists(font,0x0301): font.selection.select(0x0301); font.copy(); font.selection.select(0x030B); font.paste(); glyph = font.createChar(0x02dd); # duplicate the acute layer = glyph.foreground layer2 = layer.dup() # translate this layer left and right bb = layer.boundingBox() translation = (bb[2]-bb[0]-translationFix) / 2 layer.transform(psMat.translate(-translation,0)); layer2.transform(psMat.translate(translation,0)); # mix the two layers layer += layer2; # save the modified layer glyph.foreground = layer
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 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')
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)
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)
def geometric_triangle(rotation=0, black=True): sw = 46 xm = 37 b = bb + (bh - bw + 2 * xm) / 2.0 t = b + (bw - 2 * xm) * math.sin(math.pi / 3) contours = [] c = fontforge.contour() c.moveTo(bl + xm, b) c.lineTo(cx, t) c.lineTo(br - xm, b) c.closed = True contours.append(c) if not black: xm += sw * math.sqrt(3) c = fontforge.contour() c.moveTo(bl + xm, b + sw) c.lineTo(br - xm, b + sw) c.lineTo(cx, t - 2 * sw) c.closed = True contours.append(c) if rotation: cy = (b + t) / 2.0 rotT = psMat.compose(psMat.translate(-cx, -cy), psMat.compose(psMat.rotate(rotation), psMat.translate(cx, cy))) for c in contours: c.transform(rotT) return contours
def make_new_glyph(text, scale, list_x, y, new_glyph_codepoint, is_first_glyph, font): for index, char in enumerate(list(text)): if is_first_glyph: # 一文字目だけは、コピペして位置とサイズを変更(全ての文字が参照だと、上手くいかないっぽいので) char_codepoint = ord(char) font.selection.select(char_codepoint) font.copy() font.selection.select(('more', 'unicode'), new_glyph_codepoint) font.paste() matrix = psMat.compose(psMat.scale(scale), psMat.translate(list_x[index], y)) font[new_glyph_codepoint].transform(matrix) is_first_glyph = False else: # 親文字の二文字目以降は、文字の位置とサイズを設定して参照を追加 matrix = psMat.compose(psMat.scale(scale), psMat.translate(list_x[index], y)) char_codepoint = ord(char) font[new_glyph_codepoint].addReference( font[char_codepoint].glyphname, matrix) return is_first_glyph, font
def blackboard(font, bbold): dst = "𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ" \ + "𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫" \ + "𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡" \ + "ℼℽℾℿ⅀" \ + "⨾∘" src = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ") \ + list("abcdefghijklmnopqrstuvwxyz") \ + list("0123456789") \ + [chr(x) for x in [25, 13, 0, 5, 6]] \ + list(";=") adjust = { '𝕗': mat.translate(-100, 0), '𝕛': mat.translate(90, 0), '∘': mat.translate(0, 95), '⨾': mat.translate(0, 95), } for i in range(0, len(dst)): bbold.selection.select(("singletons", ), ord(src[i])) bbold.copy() font.selection.select(("singletons", ), ord(dst[i])) font.paste() glyph = font[ord(dst[i])] xform = moveToMonoNoSquash(glyph) if dst[i] in adjust: xform = mat.compose(xform, adjust[dst[i]]) glyph.transform(xform, ('round', )) glyph.width, glyph.vwidth = monosize
def translate_glyph(c, char_bbox, cap_height, baseline): # Put the glyph in the middle, and move it relative to the baseline. # Compute the proportion of the full EM that cap_height - baseline should consume. top_ratio = c.font.ascent / (c.font.ascent + c.font.descent) # In the original pixel coordinate space, compute how big a nice full sized glyph # should be. full_glyph_size = -(cap_height - baseline) / top_ratio # We know that the scale of the glyph is now good. But it is probably way off in terms of x & y, so we # need to fix up its position. glyph_bbox = c.boundingBox() # No matter where it is currently, take the glyph to x=0 and a y based on its positioning in # the original handwriting sample. t = psMat.translate(-glyph_bbox[0], -glyph_bbox[1] + ((baseline - char_bbox[3]) * c.font.em / full_glyph_size)) c.transform(t) # Put horizontal padding around the glyph. I choose a number here that looks reasonable, # there are far more sophisticated means of doing this (like looking at the original image, # and calculating how much space there should be). space = 20 scaled_width = glyph_bbox[2] - glyph_bbox[0] c.width = scaled_width + 2 * space t = psMat.translate(space, 0) c.transform(t)
def aroundCentroid(glyph, xform): xLo, yLo, xHi, yHi = glyph.layers[1].boundingBox( ) # layers[1] is foreground xShift = (xHi - xLo) / 2 + xLo yShift = (yHi - yLo) / 2 + yLo into = mat.translate(-xShift, -yShift) outof = mat.translate(xShift, yShift) return mat.compose(mat.compose(into, xform), outof)
def annotate_glyph(glyph, extra_glyph): layer = extra_glyph.layers[1].dup() mat = psMat.translate(-(extra_glyph.width / 2), 0) layer.transform(mat) mat = psMat.scale(0.3, 0.3) layer.transform(mat) mat = psMat.translate((extra_glyph.width / 2), 0) layer.transform(mat) mat = psMat.translate(0, -600) layer.transform(mat) glyph.layers[1] += layer
def modify_ellipsis(_f): """3点リーダーを半角にする DejaVuSansMono の U+22EF(⋯) をU+2026(…)、U+22EE(⋮)、U+22F0(⋰)、U+22F1(⋱) にコピーした上で回転させて生成 三点リーダの文字幅について · Issue #41 · miiton/Cica https://github.com/miiton/Cica/issues/41 """ _f.selection.select(0x22ef) _f.copy() _f.selection.select(0x2026) _f.paste() _f.selection.select(0x22ee) _f.paste() _f.selection.select(0x22f0) _f.paste() _f.selection.select(0x22f1) _f.paste() for g in _f.glyphs("encoding"): if g.encoding < 0x22ee: continue elif g.encoding > 0x22f1: break elif g.encoding == 0x22ee: bb = g.boundingBox() cx = (bb[2] + bb[0]) / 2 cy = (bb[3] + bb[1]) / 2 trcen = psMat.translate(-cx, -cy) rotcen = psMat.compose( trcen, psMat.compose(psMat.rotate(math.radians(90)), psMat.inverse(trcen))) g.transform(rotcen) elif g.encoding == 0x22f0: bb = g.boundingBox() cx = (bb[2] + bb[0]) / 2 cy = (bb[3] + bb[1]) / 2 trcen = psMat.translate(-cx, -cy) rotcen = psMat.compose( trcen, psMat.compose(psMat.rotate(math.radians(45)), psMat.inverse(trcen))) g.transform(rotcen) elif g.encoding == 0x22f1: bb = g.boundingBox() cx = (bb[2] + bb[0]) / 2 cy = (bb[3] + bb[1]) / 2 trcen = psMat.translate(-cx, -cy) rotcen = psMat.compose( trcen, psMat.compose(psMat.rotate(math.radians(-45)), psMat.inverse(trcen))) g.transform(rotcen) return _f
def kss3(font, nominal_glyph): glyph = font.createChar(-1, nominal_glyph.glyphname + '.kss3') glyph.glyphclass = b'mark' nominal_glyph.draw(glyph.glyphPen()) glyph.transform(psMat.translate(-nominal_glyph.width, 0)) glyph.transform(psMat.scale(0.5, CLUSTER_Y_SCALE)) glyph.transform( psMat.translate( 0, nominal_glyph.boundingBox()[3] - glyph.boundingBox()[3])) glyph.addAnchorPoint('cluster-next', 'basemark', 0, 0) glyph.addAnchorPoint('cluster-next', 'mark', 0, 0) glyph.addAnchorPoint('cluster-init', 'mark', 0, 0) glyph.width = 0
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)
def YOffset(percent, afont): '''Adjust the Y position.''' em = afont.ascent + afont.descent/2 if not percent: ret = fontforge.askString('Offset Percent?', 'Percent of Offset?', '64' ) if not ret: return try: percent = float(ret)/100 if percent < -1.5 or percent > 1.5: raise ValueError except ValueError: fontforge.postError('Wrong Percent!', "Need a value abs(x) <= 150.") return if percent == 0: # Do Nothing. return tavg, bavg = get_avg_topbtm(afont) if percent > 0: deltay = (afont.ascent - tavg)*percent else: deltay = (afont.descent - bavg)*percent matrix = psMat.translate(0, deltay) for glyph in afont.selection.byGlyphs: glyph.transform(matrix)
def modify_font(self, f): f.strokedfont = False for g in f.glyphs(): for i, c in enumerate(list(g.layers[1])): newc = self.adjust_contour(c) if newc != None: g.layers[1] += newc g.stroke(*self.nib) g.removeOverlap() g.addExtrema() g.transform(translate(0, self.nibheight / 2.0)) f.familyname = self.familyname f.fontname = self.fontname f.fullname = self.fullname f.appendSFNTName('English (US)', 'Preferred Family', self.familyname) f.private['StdHW'] = self.nibheight f.private['StdVW'] = self.nibwidth def adjustblue(y): return y - 100 + self.nibheight bv = list(f.private['BlueValues']) bv[1:] = map(adjustblue, bv[1:]) f.private['BlueValues'] = tuple(bv) f.uwidth = self.nibheight f.os2_weight = self.ttfweight f.weight = self.weight return f
def buildCompatChars(sfd, ttf): zwj = u'\u200D' ranges = ( (0xfb50, 0xfbb1), (0xfbd3, 0xfd3d), (0xfd50, 0xfdf9), (0xfdfc, 0xfdfc), (0xfe70, 0xfefc), ) with open(ttf, "rb") as f: data = f.read() blob = HarfBuzz.glib_blob_create(GLib.Bytes.new(data)) face = HarfBuzz.face_create(blob, 0) hbfont = HarfBuzz.font_create(face) upem = HarfBuzz.face_get_upem(face) HarfBuzz.font_set_scale(hbfont, upem, upem) HarfBuzz.ot_font_set_funcs(hbfont) ttfont = TTFont(ttf) for r in ranges: for c in range(r[0], r[1]+1): dec = ucd.decomposition(unichr(c)).split() if dec: keyword = dec[0] text = u'' for i in dec[1:]: text += unichr(int(str(i),16)) if keyword == '<initial>': text = text + zwj elif keyword == '<final>': text = zwj + text elif keyword == '<medial>': text = zwj + text + zwj components = shape(text, hbfont) if components: glyph = sfd.createChar(c) glyph.clear() glyph.color = 0xff0000 # red color x = 0 for component in components: gid = component[0] name = ttfont.getGlyphName(gid) x_advance = component[1] x_offset = component[2] y_offset = component[3] matrix = psMat.translate(x + x_offset, y_offset) # ignore blank glyphs, e.g. space or ZWJ if sfd[name].foreground or sfd[name].references: glyph.addReference(name, matrix) x += x_advance glyph.width = x
def flip_glyphs(): #font = fontforge.open('comic-family/comic-shanns.ttf') # I found it easier to just work with comic mono instead font = fontforge.open('comic-family/comic-mono.ttf') glyph_original_width = list(font.glyphs())[0].width font.selection.all() font.transform(psMat.scale(-1, 1)) font.transform(psMat.translate(glyph_original_width, 0)) for glyph in font.glyphs(): glyph.width = glyph_original_width font.familyname = 'Comic snnahS' font.version = '0.0.2' font.comment = 'https://github.com/z3tr/comic-snnahs' font.copyright = 'https://github.com/m5tfi/comic-snnahs/blob/master/LICENSE' font.fontname = 'Comic-snnahS' font.fullname = 'Comic snnahS' font.generate('Comic-snnahS.ttf') font.selection.all() font.fontname = 'Comic-snnahS-dlob' font.fullname = 'Comic snnahS dlob' font.weight = 'Bold' font.changeWeight(64) font.generate('Comic-snnahS-dlob.ttf')
def buildCompatChars(sfd, ttf): zwj = u'\u200D' ranges = ( (0xfb50, 0xfbb1), (0xfbd3, 0xfd3d), (0xfd50, 0xfdf9), (0xfdfc, 0xfdfc), (0xfe70, 0xfefc), ) with open(ttf, "rb") as f: data = f.read() blob = HarfBuzz.glib_blob_create(GLib.Bytes.new(data)) face = HarfBuzz.face_create(blob, 0) hbfont = HarfBuzz.font_create(face) upem = HarfBuzz.face_get_upem(face) HarfBuzz.font_set_scale(hbfont, upem, upem) HarfBuzz.ot_font_set_funcs(hbfont) ttfont = TTFont(ttf) for r in ranges: for c in range(r[0], r[1] + 1): dec = ucd.decomposition(unichr(c)).split() if dec: keyword = dec[0] text = u'' for i in dec[1:]: text += unichr(int(str(i), 16)) if keyword == '<initial>': text = text + zwj elif keyword == '<final>': text = zwj + text elif keyword == '<medial>': text = zwj + text + zwj components = shape(text, hbfont) if components: glyph = sfd.createChar(c) glyph.clear() glyph.color = 0xff0000 # red color x = 0 for component in components: gid = component[0] name = ttfont.getGlyphName(gid) x_advance = component[1] x_offset = component[2] y_offset = component[3] matrix = psMat.translate(x + x_offset, y_offset) # ignore blank glyphs, e.g. space or ZWJ if sfd[name].foreground or sfd[name].references: glyph.addReference(name, matrix) x += x_advance glyph.width = x
def resolveReferences(self, owner, scale, anchorMap): self.glyph = self.font.temporary['names'][self.name] glyph = self.glyph.glyph if self.parent: pglyph = self.parent.glyph.glyph (px, py) = getanchor(pglyph, self.at) if px is None: px = pglyph.width / 2 (cx, cy) = getanchor(glyph, self.withap, isMark=True) if cx is None: cx = glyph.width / 2 self.scale = psMat.compose(self.scale, psMat.translate(px - cx, py - cy)) if self.rsb is not None: self.advance = glyph.width - (self.rsb - pointMult( (self.rsb, 0), self.scale)[0]) self.setGlyphAnchors(glyph, anchorMap) # after attached scale established scale = psMat.compose(scale, self.scale) owner.addRealGlyph(self.glyph, scale) for c in self.children: c.resolveReferences(owner, scale, anchorMap) if self.parent: self.parent.mergeAnchors(self.anchors) else: owner.mergeAnchors(self.anchors, scale) return pointMult( (self.advance if self.advance is not None else glyph.width, 0), self.scale)[0]
def snap_point(point): nearest_x = find_nearest(wonky_sagittal_grid_positions_in_ps_fu, point.x) diff_x = abs(nearest_x - point.x) if diff_x <= 1 and diff_x > 0: print("snapping x; ", [point.x, point.y], "goes to", [nearest_x, point.y]) transformation_matrix = psMat.translate(nearest_x - point.x, 0) point.transform(transformation_matrix) nearest_y = find_nearest(wonky_sagittal_grid_positions_in_ps_fu, point.y) diff_y = abs(nearest_y - point.y) if diff_y <= 1 and diff_y > 0: print("snapping y; ", [point.x, point.y], "goes to", [point.x, nearest_y]) transformation_matrix = psMat.translate(0, nearest_y - point.y) point.transform(transformation_matrix)
def center_glyph_height(glyph, vcenter, abound=None): bounding = abound or glyph.boundingBox() # xmin,ymin,xmax,ymax glyphcenter = (bounding[3] - bounding[1]) / 2 + bounding[1] deltay = vcenter - glyphcenter matrix = psMat.translate(0, deltay) glyph.transform(matrix)
def YOffset(percent, afont): '''Adjust the Y position.''' em = afont.ascent + afont.descent / 2 if not percent: ret = fontforge.askString('Offset Percent?', 'Percent of Offset?', '64') if not ret: return try: percent = float(ret) / 100 if percent < -1.5 or percent > 1.5: raise ValueError except ValueError: fontforge.postError('Wrong Percent!', "Need a value abs(x) <= 150.") return if percent == 0: # Do Nothing. return tavg, bavg = get_avg_topbtm(afont) if percent > 0: deltay = (afont.ascent - tavg) * percent else: deltay = (afont.descent - bavg) * percent matrix = psMat.translate(0, deltay) for glyph in afont.selection.byGlyphs: glyph.transform(matrix)
def center_glyph_height(glyph, vcenter, abound=None): bounding = abound or glyph.boundingBox() # xmin,ymin,xmax,ymax glyphcenter = (bounding[3] - bounding[1])/2+bounding[1] deltay = vcenter - glyphcenter matrix = psMat.translate(0, deltay) glyph.transform(matrix)
def scale(glyph): #, wordMin, wordMax): global desc_scale wordMin, wordMax = getWord(glyph.glyphname) printBound(glyph, 'Image Size') iL, iB, iR, iT = glyph.boundingBox() # scale to word iH = iT - iB wH = wordMax - wordMin wScale = wH / iH scale_matrix = psMat.scale(wScale) glyph.transform(scale_matrix) s = 200 / ffMetrics['xheight'] #log_info('scale to FF',round(s,2)) logging.debug('scale to FF %5.2f', s) scale_matrix = psMat.scale(s) glyph.transform(scale_matrix) # move image vertically sL, sB, sR, sT = glyph.boundingBox() y = 300 - sB + (wordMin * s) base_matrix = psMat.translate(0, y) glyph.transform(base_matrix) #log_info('move y: %s bot: %s desc:%s'%(round(y,2), round(sB,2), round((wordMin*s),2))) logging.debug('move y: %5.2f bot: %5.2f desc:%5.2f', y, sB, (wordMin * s)) printBound(glyph, 'Moved ')
def copyglyph(font, infont, g, u, args) : extras = set() if args.scale is None : scale = psMat.identity() else : scale = psMat.scale(args.scale) o = font.findEncodingSlot(u) if o == -1 : glyph = font.createChar(u, g.glyphname) else : glyph = font[o] if len(g.references) == 0 : font.selection.select(glyph) pen = glyph.glyphPen() g.draw(pen) glyph.transform(scale) else : for r in g.references : t = psMat.compose(r[1], scale) newt = psMat.compose(psMat.identity(), psMat.translate(t[4], t[5])) glyph.addReference(r[0], newt) extras.add(r[0]) glyph.width = g.width * scale[0] if args.anchors : for a in g.anchorPoints : try : l = font.getSubtableOfAnchor(a[1]) except EnvironmentError : font.addAnchorClass("", a[0]*scale[0], a[1]*scale[3]) glyph.anchorPoints = g.anchorPoints return list(extras)
def create_ligature(font, bold_font, src_list, dest_pos, temp_pos, deco_type, bold): glyphname_list = [] total_width = 0 for src_char in src_list: base_font = font if bold: base_font = bold_font item = base_font.selection.select(("unicode", ), src_char) glyph = next(iter(item.byGlyphs)) glyphname_list.append(glyph.glyphname) width = glyph.width base_font.copy() font.selection.select(("unicode", ), temp_pos) font.paste() trans = psMat.translate((total_width, 0)) font.transform(trans) font.copy() font.selection.select(("unicode", ), dest_pos) font.pasteInto() total_width += width glyph = next(iter(font.selection.select(("unicode", ), dest_pos).byGlyphs)) glyph.width = total_width glyph.addPosSub(LIGATURE_SUBTABLE_NAME, " ".join(glyphname_list)) decorate(font, glyph, deco_type)
def moveToMonoNoSquash(glyph): # -------w-------- # ---ω--- # --a-- -b-- # | ( . ) | # -x- # | ( . ) | # -----w'------ # -a'- -b'- # # x = (a + ω/2) = (a' - ω/2) = a - a' # a + ω + b = w # a' + ω + b' = w' # a/b = a'/b' # # a' = ab'/b # b' = w' - ω - a' # a' = a/b (w' - ω - a') # a' + a/b(a') = a/b (w' - ω) # a'(1 + a/b) = a/b(w' - ω) # a' = a(w' - ω) ÷ b(1 + a/b) # a' = a(w' - ω)/(b + a) # x = a - a(w' - ω)/(b + a) ### x = a(1 - (w' - ω)/(b - a)) ### xFront, _, xBack, _ = glyph.layers[1].boundingBox() spaceBefore, spaceAfter = xFront, glyph.width - xBack boundingWidth = xBack - xFront if spaceBefore + spaceAfter != 0: disp = spaceBefore * (1 - (monosize[0] - boundingWidth) / (spaceAfter + spaceBefore)) else: disp = (spaceBefore + boundingWidth) / 2 return mat.translate(-disp, 0)
def _transform_sym(symfont, info): x_ratio = 1.0 y_ratio = 1.0 x_diff = 0 y_diff = 0 if info["name"] == "Seti-UI + Custom": x_ratio = 1.1 y_ratio = 1.1 x_diff = -100 y_diff = -450 elif info["name"] == "Devicons": x_ratio = 1.05 y_ratio = 1.05 x_diff = -100 y_diff = -250 elif info["name"] in ["Powerline Symbols", "Powerline Extra Symbols"]: x_ratio = 0.95 y_ratio = 0.88 x_diff = 0 y_diff = -30 elif info["name"] == "Font Linux": y_diff = -120 elif info["name"] == "Font Awesome Extension": y_diff = -400 elif info["name"] == "Pomicons": x_ratio = 1.2 y_ratio = 1.2 x_diff = -200 y_diff = -300 elif info["name"] == "Octicons": x_ratio = 0.95 y_ratio = 0.95 x_diff = 30 y_diff = -100 elif info["name"] == "Material": x_ratio = 1.1 y_ratio = 1.1 x_diff = -50 y_diff = -250 elif info["name"] == "Codicons": x_ratio = 0.85 y_ratio = 0.85 x_diff = 35 y_diff = -300 scale = psMat.scale(x_ratio, y_ratio) translate = psMat.translate(x_diff, y_diff) transform = psMat.compose(scale, translate) symfont.transform(transform)
def make_superscript_or_subscript(font, source_codepoint, dest_codepoint, superscript=True, placement_method=3): source_codepoint = codepoint(source_codepoint) dest_codepoint = codepoint(dest_codepoint) # vcenter = amount to raise raw scaled number to make it vertically centered # vdiff = amount to raise or lower from vcenter if placement_method == 1: vcenter = (1 - SUPERSUBSCRIPT_SCALE) * SUPERSUBSCRIPT_FRACTION_LINE vdiff = SUPERSUBSCRIPT_SCALE * SUPERSUBSCRIPT_FRACTION_LINE + ( 1 - SUPERSUBSCRIPT_SCALE / 2) * STROKE_WIDTH + SUPERSUBSCRIPT_FRACTION_LINE_SEPARATION if placement_method == 2: vcenter = SUPERSUBSCRIPT_FRACTION_LINE * (1 - SUPERSUBSCRIPT_SCALE) vdiff = CAP_HEIGHT / 2 if placement_method == 3: vcenter = SUPERSUBSCRIPT_FRACTION_LINE * (1 - SUPERSUBSCRIPT_SCALE) vdiff = (1 - SUPERSUBSCRIPT_SCALE / 2) * (CAP_HEIGHT - STROKE_WIDTH) if superscript: vshift = vcenter + vdiff else: vshift = vcenter - vdiff vshift_xform = psMat.translate(0, vshift) font.selection.select(source_codepoint) font.copy() font.selection.select(dest_codepoint) font.paste() dest_glyph = font.createChar(dest_codepoint) dest_glyph.transform(psMat.scale(SUPERSUBSCRIPT_SCALE)) dest_glyph.transform(vshift_xform) additionalbearing = STROKE_WIDTH / 2 * (1 - SUPERSUBSCRIPT_SCALE) dest_glyph.transform(psMat.translate(additionalbearing, 0)) dest_glyph.width = dest_glyph.width + additionalbearing print "%s => %d" % (unicodedata.name( unichr(dest_codepoint)), dest_codepoint)
def normalizeGlyph(g, letter): bb = g.boundingBox() #compact box that contains the letter dy = bb[3] - bb[1] # xmin,ymin,xmax,ymax newScale = 800 / (dy) transforms = deque() #shifting if letter in SPECIAL_Y_TRANS: transforms.append( psMat.translate(-bb[0], -bb[1] - SPECIAL_Y_TRANS[letter] * (bb[3] - bb[1]))) elif letter in DOWN_CHARS: #print('DOWN CASE: ', letter) #print(bb) transforms.append( psMat.translate(-bb[0], -bb[1] - 0.35 * (bb[3] - bb[1]))) # 0,0 35% of its height else: transforms.append(psMat.translate(-bb[0], -bb[1])) # if letter in SPECIAL_CHARS: # print('i: ', letter) # print(bb) # transforms.append(psMat.translate(300, 0) ) # scaling if dy > 800: transforms.append(psMat.scale(newScale)) if letter in MID_CHARS and letter not in SPECIAL_Y_SCALE: transforms.append(psMat.scale(0.5)) elif letter in SPECIAL_Y_SCALE: transforms.append(psMat.scale(SPECIAL_Y_SCALE[letter])) #composing while len(transforms) > 1: el1 = transforms.popleft() el2 = transforms.popleft() transforms.appendleft(psMat.compose(el1, el2)) g.transform(transforms[0]) print('POST: ', letter) bb2 = g.boundingBox() g.width = bb2[2] g.simplify() # g.round() # g.cluster(0, 100) print(g.boundingBox(), g.width) return g
def _hankaku_glyphs(font): origin = translate(-DESCENT, 0) # scale will scale glyphs with the origin (0, DESCENT) scl = scale(SCALE_DOWN) # original glyphs have width to fit this size. orig_glyph_width = WIDTH - DESCENT * 2 glyph_width = float(orig_glyph_width) * SCALE_DOWN trans_x = (WIDTH / 2 - glyph_width) / 2 trans_y = (WIDTH - glyph_width) / 2 - DESCENT trans = translate(trans_x, trans_y) mat = compose(compose(origin, scl), trans) font.selection.none() for i in HANKAKU_GLYPHS: font.selection.select(("more", "unicode"), i) for glyph in font.selection.byGlyphs: glyph.transform(mat) glyph.width = WIDTH / 2
def buildCompatChars(font, hbfont): zwj = u'\u200D' ranges = ( (0xfb50, 0xfbb1), (0xfbd3, 0xfd3d), (0xfd50, 0xfdf9), (0xfdfc, 0xfdfc), (0xfe70, 0xfefc), ) text = u'' codes = [] for r in ranges: for c in range(r[0], r[1]+1): dec = ucd.decomposition(unichr(c)).split() if dec: codes.append(c) keyword = dec[0] new_text = u'' for i in dec[1:]: new_text += unichr(int(str(i),16)) if keyword == '<initial>': new_text = new_text + zwj elif keyword == '<final>': new_text = zwj + new_text elif keyword == '<medial>': new_text = zwj + new_text + zwj text += new_text + '\n' lines = runHB(text, hbfont) i = 0 for c in codes: components = lines[i] i += 1 if components: glyph = font.createChar(c) glyph.clear() glyph.color = 0xff0000 # red color x = 0 for component in components: name = component[0] x_advance = component[1] y_advance = component[2] x_offset = component[3] y_offset = component[4] matrix = psMat.translate(x + x_offset, y_offset) # ignore blank glyphs, e.g. space or ZWJ if font[name].foreground or font[name].references: glyph.addReference(name, matrix) x += x_advance glyph.width = x
def add_smalltriangle(_f): _f.selection.select(0x25bc) _f.copy() _f.selection.select(0x25be) _f.paste() _f.transform(psMat.compose(psMat.scale(0.64), psMat.translate(0, 68))) _f.copy() _f.selection.select(0x25b8) _f.paste() _f.transform(psMat.rotate(math.radians(90))) _f.transform(psMat.translate(0, 212)) for g in _f.glyphs(): if g.encoding == 0x25be or g.encoding == 0x25b8: g.width = 512 g = align_to_center(g) return _f
def fixGlyphWidth(self, glyph, glyphName): modifiedWidth = self.fixedWidth while modifiedWidth < glyph.width : modifiedWidth += self.fixedWidth deltaWidth = modifiedWidth - glyph.width if self.isBase(glyphName): # right align matrix = psMat.translate(deltaWidth) # print "base " + glyphName + " translate by " + str(deltaWidth) else : if self.isMark(glyphName): # left align matrix = psMat.identity() else: # centre matrix = psMat.translate(.5 * deltaWidth) glyph.transform(matrix) glyph.width = modifiedWidth
def _set_proportion(font): scale = psMat.scale(SCALE_DOWN) font.selection.all() for glyph in list(font.selection.byGlyphs): x_to_center = X_TO_CENTER trans = psMat.translate(x_to_center, 0) mat = psMat.compose(scale, trans) glyph.transform(mat) glyph.width = EM
def add_vowel_u(font): gl = font["bhaataan_u_raw"] gl.importOutlines("./glyphs/u.svg") gl.left_side_bearing = 0 gl.right_side_bearing = 0 gl.width = 0 gl.addAnchorPoint("vowel_u", "mark", 158.5, 250) gl = font["bhaataan_uq_raw"] gl.addReference("bhaataan_u_raw", psMat.translate(100, 0)) gl.addReference("bhaataan_no_vowel_raw") gl.addAnchorPoint("vowel_u", "mark", 258.5, 250) gl.addPosSub("VQ_liga-1", ("bhaataan_u_raw", "bhaataan_no_vowel_raw")) gl = font[0xe021] gl.addReference("bhaataan_u_raw", psMat.translate(400, 0)) gl.addReference("dotted_circle") gl.addPosSub("dottedcircled_to_raw-1", "bhaataan_u_raw")
def fixGlyphWidth(self, glyph, glyphName): modifiedWidth = self.fixedWidth while modifiedWidth < glyph.width: modifiedWidth += self.fixedWidth deltaWidth = modifiedWidth - glyph.width if self.isBase(glyphName): # right align matrix = psMat.translate(deltaWidth) # print "base " + glyphName + " translate by " + str(deltaWidth) else: if self.isMark(glyphName): # left align matrix = psMat.identity() else: # centre matrix = psMat.translate(.5 * deltaWidth) glyph.transform(matrix) glyph.width = modifiedWidth
def _expand_shades(font, code): # `421` means the size of a set of pattern in shades. mat = translate(0, 421) font.selection.select(code) font.copy() for glyph in list(font.selection.byGlyphs): glyph.transform(mat) font.pasteInto()
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))
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))
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 scale_single_glyph(glyph, width, height): """Center glyph in a box of size width*height""" # Some glyphs (such as ‘;’) contain references (‘.’ + ‘,’), and moving the # referenced glyphs moves them in all glyphs that reference them. # Unlinking copies references into this glyph glyph.unlinkThisGlyph() # Width deltaw = width - glyph.width glyph.left_side_bearing += deltaw / 2 glyph.right_side_bearing += deltaw - glyph.left_side_bearing glyph.width = width # Height ylo = glyph.boundingBox()[1] deltah = height - glyph_height(glyph) glyph.transform(psMat.translate(0, deltah / 2.0 - ylo))
def matMove(move_x, move_y): return psMat.translate(move_x, move_y)
def m_skew(radiant): return m_compose(psMat.translate(-c_halfsize, -c_middle), psMat.skew(radiant), psMat.translate(c_halfsize, c_middle))
def m_scale(scaleX, scaleY): return m_compose(psMat.translate(-c_halfsize, -c_middle), psMat.scale(scaleX, scaleY), psMat.translate(c_halfsize, c_middle))
# char.background=glyph; for line in glfset: if line[0] != "#": if "=" in line: parts = line.split('=') if parts[1][0]=='"': parts[1] = parts[1].replace('"','') setattr(char,parts[0],parts[1]) else: setattr(char,parts[0],int(parts[1])) else: getattr(char, line)() if args.beta or args.next: char.transform(psMat.translate(0,int(sizes[glyph_name][1])*5-135)) setattr(char,"width",int(sizes[glyph_name][0])*10+40); # bearing 20 each side if args.verbose: glfCnt = glfCnt + 1 if glfCnt==60: print glyph_name, sys.stdout.flush() glfCnt=0 else: glfCnt = glfCnt + 1 if glfCnt==1150: print ".", sys.stdout.flush()
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))
#!/usr/local/bin/fontforge -script import sys import psMat import fontforge 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(): BaseFont.selection.select(("more",), glyph) print 'Rescaling...' for glyph in BaseFont.selection.byGlyphs: origWidth = glyph.width glyph.transform(psMat.translate(float(origWidth) * 0.1, 0.0), ("partialRefs",)) glyph.width = origWidth * 1.2 print 'Saving target file %s...' % sys.argv[2] BaseFont.save(sys.argv[2])
#!/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()
#!/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では、両方は同じである必要があるので、これは変更できない。
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)))
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()
#!/usr/bin/env fontforge from sys import argv, stderr import fontforge, psMat, math if len(argv) < 3: stderr.write("Usage: %s in-sfd out-sfd\n" % argv[0]) exit(1) fontforge.setPrefs('CoverageFormatsAllowed', 1) font = fontforge.open(argv[1]) font.hasvmetrics = True for glyph in font.glyphs(): if glyph.isWorthOutputting(): w = glyph.width glyph.transform(psMat.rotate(-(math.pi / 2.0))) glyph.transform(psMat.translate(font.descent, font.ascent)) glyph.width = font.em glyph.vwidth = w glyph.round() font.save(argv[2])
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: glyph.width = WidthJ
# set font encoding so we can select any unicode code point font.encoding = 'UnicodeFull' except: stderr.write("Error: fontforge can't open source font from %s" % args.src_font) sys.exit(1) # set ascent/descent ascent = config.get('font', {}).get('ascent', font.ascent) descent = config.get('font', {}).get('descent', font.descent) font.ascent = ascent font.descent = descent default_baseline = float(descent) / (ascent + descent) origin_point = lambda baseline: (0, (ascent + descent) * baseline - descent) offset_matrix = lambda offset: psMat.translate(0, offset * (ascent + descent)) # apply transformations for code, transform in transform_config: try: glyph = font[code] except TypeError: stderr.write("Warning: no such glyph (code=0x%04x)\n" % code) continue if 'rescale' in transform: baseline = transform.get('baseline', default_baseline) scale = transform['rescale'] apply_rescale(glyph, origin_point(baseline), scale) if 'offset' in transform: glyph.transform(offset_matrix(transform['offset']))
def m_translate(x, y): return psMat.translate(x, y)
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 font2.em = font.em font.selection.none() font2.selection.none() for glyph in glyphsWorthOutputting(font2):