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 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
class TTXLEFont(LEFontInstance): def __init__(self, fname, size=12): super(TTXLEFont, self).__init__() self.ttx = TTFont(fname) self.size = size self.upem = self.ttx['head'].unitsPerEm self.cmap = self.ttx['cmap'].getcmap(3, 1).cmap def getFontTable(self, table): return self.ttx.getTableData(table) def getAscent(self): self.ttx['hhea'].ascent * self.size * 1. / self.upem def getDescent(self): self.ttx['hhea'].descent * self.size * 1. / self.upem def getLeading(self): self.ttx['hhea'].lineGap * self.size * 1. / self.upem def getUnitsPerEm(self): return self.upem def mapCharToGlyph(self, code): return self.ttx.getGlyphID(self.cmap[code]) def getGlyphAdvance(self, glyph): if glyph >= self.ttx['maxp'].numGlyphs: return (0., 0.) name = self.ttx.getGlyphName(glyph) x = self.ttx['hmtx'][name][0] * self.size * 1. / self.upem if 'vmtx' in self.ttx: y = self.ttx['vmtx'][name][0] * self.size * 1. / self.upem else: y = 0. return (x, y) def getGlyphPoint(self, glyph, point): return (0., 0.) def getXPixelsPerEm(self): return self.size def getYPixelsPerEm(self): return self.size def getScaleFactorX(self): return 1. def getScaleFactorY(self): return 1.
else: features_string += f' {feature_text_line}' features_string += f'\n}} {feature_name};\n' aalt_string += '} aalt;\n' final_string = classes_string + prefix_string + aalt_string + features_string # Rename glyphs within features string to match target set print(' Renaming features glyphs') with open(Path(INDEX_DIR / f'{config["inputFile"]}.json'), 'r') as file: glyph_id_map = json.load(file) glyph_id_map_keys = sorted(glyph_id_map.keys(), reverse=True) for glyph_name in glyph_id_map_keys: regex = rf'(^|\s|\{{|\[|\\)({glyph_name})(\s|\}}|\]|\'|\;|$)' if re.search(regex, final_string) is not None: glyph_id = glyph_id_map[glyph_name] new_glyph_name = input_font.getGlyphName(glyph_id) # Run twice for instances that are sandwiched between two other instances for i in range(2): final_string = re.sub(regex, f'\g<1>{new_glyph_name}\g<3>', final_string) with open(Path(TEMP_DIR / 'features.fea'), 'w') as features_file: features_file.write(final_string) # Set up substitution functionality print(' Adding features set to output font') addOpenTypeFeaturesFromString(output_font, final_string) # Save font print(' Saving output font to TTF file') output_font.save(output_file_path) output_font.close() print(f'Completed font "{output_file_path}"')
import icu icufont = TTXLEFont(sys.argv[1], ttx=tt) iculayout = icu.LayoutEngine( icufont, icu.ScriptCodes.index(opts.script) if opts.script else 0, 0) lf = codecs.open(sys.argv[2], "r", "utf_8") count = 0 for line in lf.readlines(): count += 1 text = line.strip() b = hbng.Buffer(text) b.shape(hbfont, shapers=["ot"]) hbres = [x.gid for x in b.glyphs] s = gr.Segment(grfont, grface, 0, text, 0) grres = [x.gid for x in s.slots] if opts.compare == 'graphite': if hbres != grres: hbnres = [tt.getGlyphName(x) for x in hbres] grnres = [tt.getGlyphName(x) for x in grres] print("Failed at line %d: %s %r, %r" % (count, text.encode('utf_8'), hbnres, grnres)) elif opts.compare == "icu": iculayout.layoutChars(text, 0) icures = filter(lambda x: x != 65535, list(iculayout.getGlyphs())) if hbres != icures: hbnres = [tt.getGlyphName(x) for x in hbres] icunres = [tt.getGlyphName(x) for x in icures] print("Failed at line %d: %s %r, %r" % (count, text.encode('utf_8'), hbnres, icunres))
preview = "" for i in range(num_chars): preview += str(chr(i + start_char)) image = Image.new("RGB", (1000, 1000)) draw = ImageDraw.Draw(image) draw.text((0, 0), preview, font=font) image = image.crop(image.getbbox()) image.save(args.tf + "_prev" + str(args.pt[pt]) + ".png") pixels = image.load() # Find the max and min values ymax = 0 ymin = 0 for z in range(num_chars): m = glyphtools.get_glyph_metrics(font_info, font_info.getGlyphName(start_id + z)) new_ymax = (font_size * m['yMax'] / scale) new_ymin = (font_size * m['yMin'] / scale) ymin = round(min(ymin, new_ymin)) ymax = round(max(ymax, new_ymax)) maxmax = round(abs(ymin) + abs(ymax)) # We are adding a new font size. Allign the start address if curr_offset & 3: curr_offset = (curr_offset + 3) & ~3 # Add the glyph header indicating the global size of the font font_data += abs(ymin).to_bytes(1, byteorder="little", signed=False) font_data += abs(ymax).to_bytes(1, byteorder="little", signed=False) font_data.append(0) font_data.append(0)
tt = TTFont(sys.argv[1]) if opts.compare == "icu": from palaso.font.icule import TTXLEFont import icu icufont = TTXLEFont(sys.argv[1], ttx=tt) iculayout = icu.LayoutEngine(icufont, icu.ScriptCodes.index(opts.script) if opts.script else 0, 0) lf = codecs.open(sys.argv[2], "r", "utf_8") count = 0 for line in lf.readlines() : count += 1 text = line.strip() b = hbng.Buffer(text) b.shape(hbfont, shapers=["ot"]) hbres = [x.gid for x in b.glyphs] s = gr.Segment(grfont, grface, 0, text, 0) grres = [x.gid for x in s.slots] if opts.compare == 'graphite' : if hbres != grres : hbnres = [tt.getGlyphName(x) for x in hbres] grnres = [tt.getGlyphName(x) for x in grres] print("Failed at line %d: %s %r, %r" % (count, text.encode('utf_8'), hbnres, grnres)) elif opts.compare == "icu": iculayout.layoutChars(text, 0) icures = filter(lambda x: x != 65535, list(iculayout.getGlyphs())) if hbres != icures : hbnres = [tt.getGlyphName(x) for x in hbres] icunres = [tt.getGlyphName(x) for x in icures] print("Failed at line %d: %s %r, %r" % (count, text.encode('utf_8'), hbnres, icunres))