def create_font_mappings(): alpha = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] specials = [' ', ',', '.', '!', '?', ':', ';', '/', '>', '<'] # TODO: Add more mappings = {} for letter in alpha: tface = ft.Face('/snap/wine-platform/58/opt/wine-staging/share/wine/fonts/arial.ttf') tface.set_char_size(48 * 64) tface.load_char(letter) bitmap = tface.glyph.bitmap mappings[letter] = np.array(bitmap.buffer).reshape(bitmap.rows, bitmap.width) for letter in alpha: tface = ft.Face('/snap/wine-platform/58/opt/wine-staging/share/wine/fonts/arial.ttf') tface.set_char_size(48 * 64) tface.load_char(letter.upper()) bitmap = tface.glyph.bitmap mappings[letter.upper()] = np.array(bitmap.buffer).reshape(bitmap.rows, bitmap.width) for character in specials: tface = ft.Face('/snap/wine-platform/58/opt/wine-staging/share/wine/fonts/arial.ttf') tface.set_char_size(48 * 64) tface.load_char(character) bitmap = tface.glyph.bitmap mappings[character] = np.array(bitmap.buffer).reshape(bitmap.rows, bitmap.width) print str(len(mappings.keys())) + " Characters Mapped to Font Imagery" return mappings
def __init__(self, scene, id, file, font_width=None, font_height=None, charmap=None, monochrome=False): super().__init__(scene, id) self._file = file self._monochrome = monochrome self._font_width = font_width self._font_height = font_height self._faces = [] if isinstance(file, list): assert len(file) == 4 for i, f in enumerate(file): face = freetype.Face(Font.BASE_DIR + file[i]) if charmap is not None: face.set_charmap(charmap) self._faces.append(face) assert self._faces[i] is not None else: face = freetype.Face(Font.BASE_DIR + file) self._faces.append(face) if charmap is not None: face.set_charmap(charmap) for i in range(3): self._faces.append(face)
def __init__(self, src_file, ttx_index=0): if src_file.lower().endswith('.otf'): self.isTrueType = False self.ftFont = freetype.Face(src_file) elif src_file.lower().endswith('.ttf'): self.isTrueType = True self.ftFont = freetype.Face(src_file) elif src_file.lower().endswith('.ttx'): self.isTrueType = True if self.ttx_index is None: raise Exception('.ttx missing --ttx-index.') self.ftFont = freetype.Face(src_file, index=ttx_index) else: raise Exception('Unrecognized file extension: %s' % self.src_file)
def _make_font(self, filename, size): face = ft.Face(filename) face.set_char_size(size * 64) if not face.is_fixed_width: raise UserWarning('Font is not monotype') grid_height = self.grid_height grid_width = self.grid_width # Determine largest glyph size width, height, ascender, descender = 0, 0, 0, 0 # start at 32 to skip 32 first ASCII characters for c in range(32, grid_width * grid_height + 32): face.load_char(chr(c), ft.FT_LOAD_RENDER | ft.FT_LOAD_FORCE_AUTOHINT) bitmap = face.glyph.bitmap width = max(width, bitmap.width) ascender = max(ascender, face.glyph.bitmap_top) descender = max(descender, bitmap.rows - face.glyph.bitmap_top) height = ascender + descender # Generate texture data z = numpy.zeros((height * grid_height, width * grid_width), dtype=numpy.ubyte) for j in range(grid_height): for i in range(grid_width): pos = chr(32 + j * grid_width + i) face.load_char(pos, ft.FT_LOAD_RENDER | ft.FT_LOAD_FORCE_AUTOHINT) bitmap = face.glyph.bitmap x = i * width + face.glyph.bitmap_left y = j * height + ascender - face.glyph.bitmap_top z[y:y + bitmap.rows, x:x + bitmap.width].flat = bitmap.buffer self._font_data = z self._glyph_width = width self._glyph_height = height
def __init__(self, font_manager, font_id, name): super(Type1Font, self).__init__(font_manager, font_id, name) # self._glyphs = {} try: self._face = freetype.Face(self.filename) except: raise NameError("Freetype can't open file %s" % (self.filename)) if self.tfm is None: self._find_afm() encodings = [charmap.encoding for charmap in self._face.charmaps] if freetype.FT_ENCODING_ADOBE_CUSTOM in encodings: encoding = freetype.FT_ENCODING_ADOBE_CUSTOM elif freetype.FT_ENCODING_ADOBE_STANDARD in encodings: encoding = freetype.FT_ENCODING_ADOBE_STANDARD else: # encoding = freetype.FT_ENCODING_UNICODE raise NameError("Font %s doesn't have an Adobe encoding" % (self.name)) self._face.select_charmap(encoding) self._init_index() # self._log_face_information() # self._log_glyph_table() self._font_size = {}
def process_face(name, style, size): print('Processing ... %s %s %s' % (name, style, size)) face = freetype.Face('/usr/share/fonts/truetype/%s-%s.ttf' % (name, style)) face.set_pixel_sizes(0, size) fontname = '%s_%s_%d' % (name.lower(), style.lower(), size) with open('font_%s.h' % fontname, 'wt') as f: f.write('#include <stdint.h>\n\n') f.write('extern const uint8_t* const Font_%s_%s_%d[%d + 1 - %d];\n' % (name, style, size, MAX_GLYPH, MIN_GLYPH)) with open('font_%s.c' % fontname, 'wt') as f: f.write('#include "font_%s.h"\n\n' % fontname) f.write('// first two bytes are width and height of the glyph\n') f.write('// third, fourth and fifth bytes are advance\n') f.write('// bearingX and bearingY of the horizontal metrics of the glyph\n') f.write('// rest is packed 4-bit glyph data\n\n') f.write('// clang-format off\n\n') for i in range(MIN_GLYPH, MAX_GLYPH + 1): c = chr(i) face.load_char(c, freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_NORMAL) bitmap = face.glyph.bitmap metrics = face.glyph.metrics assert metrics.width // 64 == bitmap.width assert metrics.height // 64 == bitmap.rows assert metrics.width % 64 == 0 assert metrics.height % 64 == 0 assert metrics.horiAdvance % 64 == 0 assert metrics.horiBearingX % 64 == 0 assert metrics.horiBearingY % 64 == 0 assert bitmap.width == bitmap.pitch assert len(bitmap.buffer) == bitmap.pitch * bitmap.rows width = bitmap.width rows = bitmap.rows advance = metrics.horiAdvance // 64 bearingX = metrics.horiBearingX // 64 # the following code is here just for some letters (listed below) # not using negative bearingX makes life so much easier; add it to advance instead if c in 'jy}),/' and bearingX < 0: advance += -bearingX bearingX = 0 bearingY = metrics.horiBearingY // 64 assert advance >= 0 and advance <= 255 assert bearingX >= 0 and bearingX <= 255 assert bearingY >= 0 and bearingY <= 255 print('Loaded glyph "%c" ... %d x %d @ %d grays (%d bytes, metrics: %d, %d, %d)' % (c, bitmap.width, bitmap.rows, bitmap.num_grays, len(bitmap.buffer), advance, bearingX, bearingY)) f.write('/* %c */ static const uint8_t Font_%s_%s_%d_glyph_%d[] = { %d, %d, %d, %d, %d' % (c, name, style, size, i, width, rows, advance, bearingX, bearingY)) buf = list(bitmap.buffer) if len(buf) > 0: if FONT_BPP == 2: for _ in range(4 - len(buf) % 4): buf.append(0) buf = [((a & 0xC0) | ((b & 0xC0) >> 2) | ((c & 0xC0) >> 4) | ((d & 0xC0) >> 6)) for a, b, c, d in [buf[i:i + 4] for i in range(0, len(buf), 4)]] elif FONT_BPP == 4: if len(buf) % 2 > 0: buf.append(0) buf = [((a & 0xF0) | (b >> 4)) for a, b in [buf[i:i + 2] for i in range(0, len(buf), 2)]] f.write(', ' + ', '.join(['%d' % x for x in buf])) f.write(' };\n') f.write('\nconst uint8_t * const Font_%s_%s_%d[%d + 1 - %d] = {\n' % (name, style, size, MAX_GLYPH, MIN_GLYPH)) for i in range(MIN_GLYPH, MAX_GLYPH + 1): f.write(' Font_%s_%s_%d_glyph_%d,\n' % (name, style, size, i)) f.write('};\n')
def make_freetype_font(self): """ Function doc """ face = ft.Face(self.font_file) face.set_char_size(self.char_res*64) # Determine largest glyph size width, height, ascender, descender = 0, 0, 0, 0 for c in range(32,128): face.load_char(chr(c), ft.FT_LOAD_RENDER | ft.FT_LOAD_FORCE_AUTOHINT) bitmap = face.glyph.bitmap width = max(width, bitmap.width) ascender = max(ascender, face.glyph.bitmap_top) descender = max(descender, bitmap.rows-face.glyph.bitmap_top) height = ascender+descender # Generate texture data self.font_buffer = np.zeros((height*6, width*16), dtype=np.ubyte) for j in range(6): for i in range(16): face.load_char(chr(32+j*16+i), ft.FT_LOAD_RENDER | ft.FT_LOAD_FORCE_AUTOHINT ) bitmap = face.glyph.bitmap x = i*width + face.glyph.bitmap_left y = j*height + ascender - face.glyph.bitmap_top self.font_buffer[y:y+bitmap.rows,x:x+bitmap.width].flat = bitmap.buffer # Bound texture GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) self.texture_id = GL.glGenTextures(1) GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture_id) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RED, self.font_buffer.shape[1], self.font_buffer.shape[0], 0, GL.GL_RED, GL.GL_UNSIGNED_BYTE, self.font_buffer) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) # Fill the font variables with data self.text_u = width/float(self.font_buffer.shape[1]) self.text_v = height/float(self.font_buffer.shape[0]) return True
def load_font(filename, size): global font_texture_id, font_height, font_map face = freetype.Face(filename) face.set_char_size(size*64) face_list = [] font_bitmap_width = 0 ascender, descender = 0, 0 for c in range(32, 128): face.load_char(chr(c), freetype.FT_LOAD_RENDER | freetype.FT_LOAD_FORCE_AUTOHINT) face_list.append((chr(c), font_bitmap_width)) font_bitmap_width += face.glyph.bitmap.width ascender = max(ascender, face.glyph.bitmap_top) descender = max(descender, face.glyph.bitmap.rows-face.glyph.bitmap_top) font_height = ascender + descender font_map = {} font_bitmap = numpy.zeros((font_height, font_bitmap_width), dtype=numpy.ubyte) for c, x in face_list: face.load_char(c, freetype.FT_LOAD_RENDER | freetype.FT_LOAD_FORCE_AUTOHINT) y = ascender - face.glyph.bitmap_top w, h = face.glyph.bitmap.width, face.glyph.bitmap.rows font_bitmap[y:y+h, x:x+w].flat = face.glyph.bitmap.buffer font_map[c] = (w, x / font_bitmap_width, (x+w) / font_bitmap_width) font_texture_id = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, font_texture_id) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, font_bitmap_width, font_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, font_bitmap)
def test_vf_axis_get_set(): ft_vt, ft_vs = _ft_ver() if ft_vt < (2, 8, 1): pytest.skip( "Incomplete VF support in FreeType lib {} (need 2.8.1 or later)". format(ft_vs)) return font_path = os.path.join(test_folder, "..", "examples", "SourceSansVariable-Roman.otf") face = freetype.Face(font_path) dc_in = (373, ) face.set_var_design_coords(dc_in) dcoords = face.get_var_design_coords() assert dcoords[0] == dc_in[0] bc_in = (-0.5, ) face.set_var_blend_coords(bc_in) bcoords = face.get_var_blend_coords() assert bcoords[0] == bc_in[0] # try 'reset to defaults' option face.set_var_design_coords(None, reset=True) dcoords = face.get_var_design_coords() vsi = face.get_variation_info() expected = tuple([vsi.axes[i].default for i in range(len(dcoords))]) assert dcoords == expected
def face(self): if not hasattr(self, "_face"): try: self._face = ft.Face(str(self.path)) except ft.ft_errors.FT_Exception: raise RuntimeError(f"Could not open {self.path}") return getattr(self, "_face")
def __init__(self, filename, x_height_in_px=None): self.filename = filename self.face = freetype.Face(filename) # Set size by rendering /x and dividing by its height if x_height_in_px is None: self.scale_factor = 1 else: self.face.set_pixel_sizes(0, self.face.units_per_EM) # render at 1 pixel per unit x_height_at_em = self.get_xheight() self.scale_factor = x_height_in_px / x_height_at_em x_height_unit = int(self.face.units_per_EM * self.scale_factor) self.face.set_pixel_sizes(0, x_height_unit) self.ascender = self.face.ascender self.ascender_px = int(self.face.ascender * self.scale_factor) """The font's ascender height, in font units and pixels.""" self.descender = self.face.descender self.descender_px = int(self.face.descender * self.scale_factor) """The font's descender height, in font units and pixels (usually negative).""" self.full_height = self.ascender - self.descender self.full_height_px = self.ascender_px - self.descender_px """The font's full (descender + ascender) height, in font units and pixels.""" self.baseline_ratio = 1 - (self.ascender) / self.full_height """The ascender-to-descender ratio.""" self.ttFont = ttLib.TTFont(self.filename) self.hbFont = None self.glyphcache = {}
def __init__(self, filename, size, minchar, maxchar, monospaced, defchar, charset): super().__init__() self._face = freetype.Face(filename) self.minchar = minchar self.maxchar = maxchar self.monospaced = monospaced self.defchar = defchar # .def_charset is requested charset or '' if -c was not specified self.def_charset = charset # .charset has all defined characters with '' for those in range but undefined. if defchar is None: # Binary font self.charset = [chr(char) for char in range(minchar, maxchar + 1)] elif charset == '': self.charset = [chr(defchar)] + [ chr(char) for char in range(minchar, maxchar + 1) ] else: n = sorted([ord(x) for x in chr(defchar) + charset]) self.minchar = n[0] self.maxchar = n[-1] self.charset = [chr(defchar)] + [ chr(char) if chr(char) in charset else '' for char in range(n[0], n[-1] + 1) ] # .pop_charset has only the defined characters self.pop_charset = [c for c in self.charset if c] self.max_width = self.get_dimensions(size) self.width = self.max_width if monospaced else 0 for char in self.pop_charset: # Populate dictionary self._render_char(char)
def _load_glyph(self): face = freetype.Face(self.char.face, index=self.char.index) face.set_char_size(int(self.char.height * 64)) face.load_char(self.char.char, freetype.FT_LOAD_DEFAULT | freetype.FT_LOAD_NO_BITMAP) self.char.set_metrics(face) return face.glyph.get_glyph()
def __init__(self, font_path, font_size, outline=False, outline_thickness=4): self.face = freetype.Face(font_path) self.face.set_pixel_sizes(font_size, font_size) self.char_to_tex = {} self.char_sizes = {} self.font_size = font_size self.cache_file = font_path[:-4] + f'_{font_size}{"p" if not outline else "o"}.raw' self.line_height = 0 self.min_top = None self.outline = outline self.outline_thickness = outline_thickness self.fill_char_index() full_binary = self.get_full_binary() self.texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.texture) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.line_height * MAGIC_NUMBER, len(full_binary) // (MAGIC_NUMBER * self.line_height * 4), 0, GL_RGBA, GL_UNSIGNED_BYTE, full_binary) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) self.vbo = Vbo()
def init(): global face, jpeg import freetype from tjpgwrap import TurboJPEG jpeg = TurboJPEG('/usr/lib/libturbojpeg.so') face = freetype.Face("font.ttf") face.set_char_size( 1000 )
def addFontFiles(self, fontPaths, monospaceOnly=False): """ Add a list of font files to the FontManger font search space. Each element of the fontPaths list must be a valid path including the font file name. Relative paths can be used, with the current working directory being the origin. If monospaceOnly is True, each font file will only be added if it is a monospace font (as only monospace fonts are currently supported by TextBox). Adding fonts to the FontManager is not persistent across runs of the script, so any extra font paths need to be added each time the script starts. """ fi_list = [] for fp in fontPaths: if os.path.isfile(fp) and os.path.exists(fp): face = ft.Face(fp) if monospaceOnly: if face.is_fixed_width: fi_list.append(self._createFontInfo(fp, face)) else: fi_list.append(self._createFontInfo(fp, face)) self.fontStyles.sort() return fi_list
def load_glyph(font_name: str, glyph: str, index: int = 0) -> Polygon: face = freetype.Face(font_manager.findfont(font_name), index=index) face.set_char_size(128 * 64) face.load_char(glyph, freetype.FT_LOAD_DEFAULT | freetype.FT_LOAD_NO_BITMAP) ctx = [] face.glyph.outline.decompose(ctx, move_to=move_to, line_to=line_to, conic_to=conic_to, cubic_to=cubic_to) bbox = face.glyph.outline.get_bbox() width = bbox.xMax - bbox.xMin height = bbox.yMax - bbox.yMin svg = f"""<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}"> <g transform="translate(0, {bbox.yMax - bbox.yMin}) scale(1, -1) translate({-bbox.xMin}, {-bbox.yMin})" transform-origin="0 0"> <path style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" d="{' '.join(ctx)}" /> <!-- rect x="{bbox.xMin}" y="{bbox.yMin}" width="{width}" height="{height}" /--> </g> </svg> """ svg_io = io.StringIO(svg) lc, w, h = vp.read_svg(svg_io, 1) mls = lc.as_mls() poly = Polygon(mls.geoms[0]) for geom in mls.geoms[1:]: poly = poly.symmetric_difference(Polygon(geom)) return poly
def __init__(self, font_file, font_pt=40): self.font_file = font_file self.font_pt = int(font_pt) self._face = freetype.Face(font_file) self._face.set_pixel_sizes(0, font_pt) self._character_map = {} for i in range(0, 128): # Generate texture face = self._face face.load_char(chr(i)) buf = face.glyph.bitmap.buffer src = (np.array(buf) / 255.0).astype(np.float32) src = src.reshape((face.glyph.bitmap.rows, face.glyph.bitmap.width)) tex = Texture( sampler=Sampler( magFilter=GL_LINEAR, minFilter=GL_LINEAR, wrapS=GL_CLAMP_TO_EDGE, wrapT=GL_CLAMP_TO_EDGE ), source=src, source_channels="R", ) character = Character( texture=tex, size=np.array([face.glyph.bitmap.width, face.glyph.bitmap.rows]), bearing=np.array([face.glyph.bitmap_left, face.glyph.bitmap_top]), advance=face.glyph.advance.x, ) self._character_map[chr(i)] = character self._vbo = None self._vao = None
def __init__(self, name, charset, size=None, pixel_size=None, bold=False, monochrome=True): self.size = size self.monochrome = monochrome self.bold = bold font = self.font = freetype.Face(name) if pixel_size is not None: font.set_pixel_sizes(pixel_size, pixel_size) else: size = int(size * 64) font.set_char_size(size, size, RESOLUTION, RESOLUTION) self.width = self.get_width() self.height = self.get_height() metrics = self.font.size self.ascender = metrics.ascender / 64.0 self.descender = metrics.descender / 64.0 self.glyph_dict = {} self.glyphs = [] self.charmap = {} charcode, agindex = font.get_first_char() while agindex != 0: self.charmap[agindex] = charcode charcode, agindex = font.get_next_char(charcode, agindex) for c in charset: self.load_char(c) space_glyph = self.load_char(' ', force=True)
def __init__(self, path=None, lazy=False, size=1500): self.path = path self.ttfont = TTFont(self.path) self._src_ttfont = TTFont(self.path) self.glyphset = None self.recalc_glyphset() self.axis_order = None self.instance_coordinates = self._get_dflt_instance_coordinates() self.instances_coordinates = self._get_instances_coordinates() self.glyphs = self.marks = self.mkmks = self.kerns = \ self.glyph_metrics = self.names = self.attribs = None self.ftfont = freetype.Face(self.path) self.ftslot = self.ftfont.glyph self.size = size self.ftfont.set_char_size(self.size) with open(self.path, 'rb') as fontfile: self._fontdata = fontfile.read() self.hbface = hb.Face.create(self._fontdata) self.hbfont = hb.Font.create(self.hbface) self.hbfont.scale = (self.size, self.size) if not lazy: self.recalc_tables()
def __init__(self, fontname: str) -> None: self.face = freetype.Face(fontname) height_base = int(BASE_FONT) self.face.set_char_size(height=PRESCALE * height_base * 64) dim = 1024 self.margin = 3 self.packer = SkyLine(dim, dim) load_results = loadCached() if load_results is not None: self.atlas, self.image = load_results else: self.atlas = {} self.image = numpy.zeros((dim, dim), dtype=numpy.uint8) old_set = frozenset(list(self.atlas.keys())) import string chars = string.digits + string.ascii_letters + string.punctuation + ' ' #self.addGlyphs(string.digits + string.letters + string.punctuation) for i in chars: self.getGlyph(i) new_set = frozenset(list(self.atlas.keys())) if old_set != new_set: saveCached(self.image, self.atlas)
def addFontFile(self, fontPath, monospaceOnly=False): """Add a Font File to the FontManger font search space. The fontPath must be a valid path including the font file name. Relative paths can be used, with the current working directory being the origin. If monospaceOnly is True, the font file will only be added if it is a monospace font. Adding a Font to the FontManager is not persistent across runs of the script, so any extra font paths need to be added each time the script starts. """ fi_list = set() if os.path.isfile(fontPath) and os.path.exists(fontPath): try: face = ft.Face(str(fontPath)) except Exception: logging.warning( "Font Manager failed to load file {}".format(fontPath)) return if face.family_name is None: logging.warning( "{} doesn't have valid font family name".format(fontPath)) return if monospaceOnly: if face.is_fixed_width: fi_list.add(self._createFontInfo(fontPath, face)) else: fi_list.add(self._createFontInfo(fontPath, face)) return fi_list
def calculateBlackRaster(g): if g == None: print 'selcet a glyph first' return root = os.path.split(f.path)[0] tail = 'Temp.ttf' fulltempfontpath = os.path.join(root, tail) f.generate(fulltempfontpath,'ttf', decompose = False, checkOutlines = False, autohint = False, releaseMode = False, glyphOrder=None, progressBar = None ) start = time.time() face = freetype.Face(fulltempfontpath) face.set_pixel_sizes(1000, 1000) face.load_char(g.name, freetype.FT_LOAD_RENDER | freetype.FT_LOAD_TARGET_MONO ) surface = len(face.glyph.bitmap.buffer) black = 0 for pixel in face.glyph.bitmap.buffer: if pixel == 255: black += 1 print "with FreeType:" print "finished in %f seconds" % (time.time() - start) print 'black:', (black/surface)*100, '%'
def cache_font_bitmap(font_filename): """创建字形位图缓存,用于中日韩光学字符识别。 产生的图像以英文书写顺序排列256×256个字形,覆盖Unicode基本多文种平面。 字形尺寸是16×16像素,故可将0类cv2.blockMeanHash的结果直接与之比较。 只有本函数需要FreeType。如果目标环境难以启用FreeType,可从其他计算机拷贝缓存数据。 以基于思源黑体的开源像素字体生成脚本为蓝本编写了本函数,但代码已面目全非。 https://github.com/44670/SourceHanSans-Pixel """ import freetype face = freetype.Face(font_filename) face.set_pixel_sizes(17, 16) # 微调以撑满 img = np.empty((4096, 4096 // 8), dtype=np.uint8) for i in range(65536): if not face.get_char_index(i): continue face.load_char(chr(i), flags=freetype.FT_LOAD_TARGET_MONO | freetype.FT_LOAD_RENDER) pitch = face.glyph.bitmap.pitch buffer = face.glyph.bitmap.buffer for y in range(min(face.glyph.bitmap.rows, 16)): for x in range(min((face.glyph.bitmap.width - 1) // 8 + 1, 2)): img[i >> 8 << 4 | y, (i & 255) << 1 | x] = buffer[pitch * y + x] if i % 100 == 0: print(progress_bar(i / 65536, 40), i) return np.unpackbits(img, axis=1) * 255
def __init__(self, filename, size, textureSize=2048): """ Initialize font Parameters: ----------- atlas: TextureAtlas Texture atlas where glyph texture will be stored filename: str Font filename size : float Font size """ self.scale = 64.0 self.atlas = _TextureAtlas(textureSize, textureSize, format='alpha') self.filename = filename self.size = size self.glyphs = {} face = ft.Face(str(filename)) # ft.Face doesn't support Pathlib yet face.set_char_size(int(self.size * self.scale)) self.info = FontInfo(filename, face) self._dirty = False metrics = face.size self.ascender = metrics.ascender / self.scale self.descender = metrics.descender / self.scale self.height = metrics.height / self.scale self.linegap = self.height - self.ascender + self.descender self.format = self.atlas.format
def __init__(self, window: wx.Window, size: int) -> None: super().__init__() self._face = freetype.Face(_FONT_PATH) self._face.set_char_size(size * 64) self._glyphs = {} # type: typing.Dict[str, _Glyph] window.Bind(wx.EVT_WINDOW_DESTROY, self._OnWindowDestroy)
def makefont(self, filename, fontsize): face = freetype.Face(filename) face.set_pixel_sizes(0, fontsize) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) gl.glActiveTexture(gl.GL_TEXTURE0) self.top_bearing = 0 for c in range(128): face.load_char(chr(c), freetype.FT_LOAD_RENDER) glyph = face.glyph bitmap = glyph.bitmap size = bitmap.width, bitmap.rows bearing = glyph.bitmap_left, glyph.bitmap_top self.top_bearing = max(self.top_bearing, bearing[1]) advance = glyph.advance.x # create glyph texture texObj = gl.glGenTextures(1) gl.glBindTexture(gl.GL_TEXTURE_2D, texObj) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_R8, *size, 0, gl.GL_RED, gl.GL_UNSIGNED_BYTE, bitmap.buffer) self.characters.append((texObj, size, bearing, advance)) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4) gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
def __init__(self, hres, atlas, filename, size, style, glyphclass=OutlinedGlyph): self.hres = hres self.atlas = atlas assert atlas.depth == 3 self.filename = filename self.size = size self.style = style self.glyphs = {} self.glyphclass = glyphclass self.face = ft.Face(self.filename) self.face.set_char_size(int(self.size * 64), hres=int(self.hres / 4), vres=int(self.hres / 4)) self._dirty = True metrics = self.face.size self.ascender = self.ft2screen(metrics.ascender) self.descender = self.ft2screen(metrics.descender) self.height = self.ft2screen(metrics.height) self.linegap = self.height - self.ascender + self.descender self.depth = atlas.depth
def __init__(self, filename, size, minchar, maxchar, monospaced, defchar, charset, bitmapped): super().__init__() self._face = freetype.Face(filename) # .crange is the inclusive range of ordinal values spanning the character set. self.crange = range(minchar, maxchar + 1) self.monospaced = monospaced self.defchar = defchar # .charset has all defined characters with '' for those in range but undefined. # Sort order is increasing ordinal value of the character whether defined or not, # except that item 0 is the default char. if defchar is None: # Binary font self.charset = [chr(ordv) for ordv in self.crange] elif charset == '': self.charset = [chr(defchar)] + [chr(ordv) for ordv in self.crange] else: cl = [ord(x) for x in chr(defchar) + charset if self._face.get_char_index(x) != 0 ] self.crange = range(min(cl), max(cl) + 1) # Inclusive ordinal value range cs = [chr(ordv) if chr(ordv) in charset and self._face.get_char_index(chr(ordv)) != 0 else '' for ordv in self.crange] # .charset has an item for all chars in range. '' if unsupported. # item 0 is the default char. Subsequent chars are in increasing ordinal value. self.charset = [chr(defchar)] + cs # Populate self with defined chars only self.update(dict.fromkeys([c for c in self.charset if c])) self.max_width = self.bmp_dimensions(size) if bitmapped else self.get_dimensions(size) self.width = self.max_width if monospaced else 0 self._assign_values() # Assign values to existing keys
def setupFonts(cls): ''' ''' try: pycut_fonts_module = os.environ["PYCUT_FONTS_TEXT_2_PATHS"] base, name = os.path.split(pycut_fonts_module) sys.path.append(base) pycut_fonts = importlib.import_module(name) cls.fonts_dir = pycut_fonts.fonts_dir cls.fonts_family_alias = pycut_fonts.fonts_family_alias except Exception as e: print("failed to load %s - %s" % (pycut_fonts_module, e)) print("using default font dirs %ss" % cls.fonts_dir) cls.lookup = {} for font_dir in cls.fonts_dir: ttfs = glob.glob(os.path.join(font_dir, "*.ttf")) for ttf in ttfs: face = freetype.Face(ttf) family = face.family_name.decode("ascii", "strict").lower() style = face.style_name.decode("ascii", "strict").lower() if family not in cls.lookup: cls.lookup[family] = {} cls.lookup[family][style] = ttf for family in cls.lookup: print("----------------", family) for style in cls.lookup[family]: print(" %-20s -> %s" % (style, cls.lookup[family][style]))