Exemple #1
0
def apply_android_specific_fixes(font):
    """Apply fixes needed for Android."""
    # Set ascent, descent, and lineGap values to Android K values
    hhea = font['hhea']
    hhea.ascent = 1900
    hhea.descent = -500
    hhea.lineGap = 0

    # Remove combining keycap and the arrows from the cmap table:
    # https://github.com/google/roboto/issues/99
    font_data.delete_from_cmap(
        font,
        [
            0x20E3,  # COMBINING ENCLOSING KEYCAP
            0x2191,  # UPWARDS ARROW
            0x2193,  # DOWNWARDS ARROW
        ])

    # Drop tables not useful on Android
    for table in ['LTSH', 'hdmx', 'VDMX', 'gasp']:
        if table in font:
            del font[table]

    # Set bold bits for Black (macStyle bit 0, fsSelection bit 5, subfamily)
    name_records = font_data.get_name_records(font)
    family_name = name_records[1]
    subfam_name = name_records[2]
    if family_name.endswith('Black'):
        font['head'].macStyle |= (1 << 0)
        font['OS/2'].fsSelection |= (1 << 5)
        font['OS/2'].fsSelection &= ~(1 << 6)
        new_subfam_name = (('Bold ' + subfam_name)
                           if subfam_name != 'Regular' else 'Bold')
        font_data.set_name_record(font, 2, new_subfam_name)
def apply_android_specific_fixes(font):
    """Apply fixes needed for Android."""
    # Set ascent, descent, and lineGap values to Android K values
    hhea = font["hhea"]
    hhea.ascent = 1900
    hhea.descent = -500
    hhea.lineGap = 0

    # Remove combining keycap and the arrows from the cmap table:
    # https://github.com/google/roboto/issues/99
    font_data.delete_from_cmap(
        font, [0x20E3, 0x2191, 0x2193]  # COMBINING ENCLOSING KEYCAP  # UPWARDS ARROW  # DOWNWARDS ARROW
    )

    # Drop tables not useful on Android
    for table in ["LTSH", "hdmx", "VDMX", "gasp"]:
        if table in font:
            del font[table]
    cmap = font["cmap"]
    cmap.tables = [t for t in cmap.tables if t.format == 12]
    assert cmap.tables, "No format 12 cmap found in font"

    # Set bold bits for Black (macStyle bit 0, fsSelection bit 5, subfamily)
    name_records = font_data.get_name_records(font)
    family_name = name_records[1]
    subfam_name = name_records[2]
    if family_name.endswith("Black"):
        font["head"].macStyle |= 1 << 0
        font["OS/2"].fsSelection |= 1 << 5
        font["OS/2"].fsSelection &= ~(1 << 6)
        new_subfam_name = ("Bold " + subfam_name) if subfam_name != "Regular" else "Bold"
        font_data.set_name_record(font, 2, new_subfam_name)
def apply_android_specific_fixes(font):
    """Apply fixes needed for Android."""
    # Set ascent, descent, and lineGap values to Android K values
    hhea = font['hhea']
    hhea.ascent = 1900
    hhea.descent = -500
    hhea.lineGap = 0

    # Remove combining keycap and the arrows from the cmap table:
    # https://github.com/google/roboto/issues/99
    font_data.delete_from_cmap(font, [
        0x20E3, # COMBINING ENCLOSING KEYCAP
        0x2191, # UPWARDS ARROW
        0x2193, # DOWNWARDS ARROW
        ])

    # Drop tables not useful on Android
    for table in ['LTSH', 'hdmx', 'VDMX', 'gasp']:
        if table in font:
            del font[table]

    # Set bold bits for Black (macStyle bit 0, fsSelection bit 5, subfamily)
    name_records = font_data.get_name_records(font)
    family_name = name_records[1]
    subfam_name = name_records[2]
    if family_name.endswith('Black'):
        font['head'].macStyle |= (1 << 0)
        font['OS/2'].fsSelection |= (1 << 5)
        font['OS/2'].fsSelection &= ~(1 << 6)
        new_subfam_name = (
            ('Bold ' + subfam_name) if subfam_name != 'Regular' else 'Bold')
        font_data.set_name_record(font, 2, new_subfam_name)
Exemple #4
0
def main(font_path):
    font = TTFont(font_path, recalcBBoxes=False)

    # Force yMin and yMax
    font['head'].yMin = YMIN
    font['head'].yMax = YMAX

    # Enable Bold bits for Black styles
    if "Black" in font_path and "fvar" not in font:
        if "Italic" in font_path:
            font["OS/2"].fsSelection |= 32
        else:
            font["OS/2"].fsSelection ^= 64 | 32
        font["head"].macStyle |= 1

    # turn off round-to-grid flags in certain problem components
    # https://github.com/google/roboto/issues/153
    glyph_set = font.getGlyphSet()
    ellipsis = glyph_set['ellipsis']._glyph
    for component in ellipsis.components:
        component.flags &= ~(1 << 2)

    font_data.delete_from_cmap(
        font,
        [
            0x20E3,  # COMBINING ENCLOSING KEYCAP
            0x2191,  # UPWARDS ARROW
            0x2193,  # DOWNWARDS ARROW
        ])
    font.save(font_path)
def main(argv):
    """Modify all the fonts given in the command line."""
    for font_name in argv[1:]:
        font = ttLib.TTFont(font_name)

        assert "GSUB" not in font
        font["GSUB"] = create_simple_gsub([create_lookup(EMOJI_KEYCAPS, font), create_lookup(EMOJI_FLAGS, font)])

        font_data.delete_from_cmap(font, EMOJI_FLAGS.keys() + EMOJI_KEYCAPS.keys())

        font.save(font_name + "-fixed")
def main(argv):
    """Modify all the fonts given in the command line."""
    for font_name in argv[1:]:
        font = ttLib.TTFont(font_name)

        assert 'GSUB' not in font
        font['GSUB'] = create_simple_gsub([
            create_lookup(EMOJI_KEYCAPS, font),
            create_lookup(EMOJI_FLAGS, font)
        ])

        font_data.delete_from_cmap(font,
                                   EMOJI_FLAGS.keys() + EMOJI_KEYCAPS.keys())

        font.save(font_name + '-fixed')
def apply_android_specific_fixes(font):
    """Apply fixes needed for Android."""
    # Set ascent, descent, and lineGap values to Android K values
    hhea = font['hhea']
    hhea.ascent = 1900
    hhea.descent = -500
    hhea.lineGap = 0

    # Remove combining keycap and the arrows from the cmap table:
    # https://code.google.com/a/google.com/p/roboto/issues/detail?id=52
    font_data.delete_from_cmap(font, [
        0x20E3, # COMBINING ENCLOSING KEYCAP
        0x2191, # UPWARDS ARROW
        0x2193, # DOWNWARDS ARROW
        ])

    # Drop tables not useful on Android
    for table in ['LTSH', 'hdmx', 'VDMX', 'gasp']:
        if table in font:
            del font[table]
Exemple #8
0
def main(font_path):
    font = TTFont(font_path, recalcBBoxes=False)
    # turn off round-to-grid flags in certain problem components
    # https://github.com/google/roboto/issues/153
    glyph_set = font.getGlyphSet()
    ellipsis = glyph_set['ellipsis']._glyph
    for component in ellipsis.components:
        component.flags &= ~(1 << 2)

    font_data.delete_from_cmap(
        font,
        [
            0x20E3,  # COMBINING ENCLOSING KEYCAP
            0x2191,  # UPWARDS ARROW
            0x2193,  # DOWNWARDS ARROW
        ])
    # Update vertical metrics to match v2.136
    update_attribs(font, **android_and_cros_vert_metrics)
    update_psname_and_fullname(font, include_year=True)
    update_font_version(font)
    font.save(font_path)
def apply_android_specific_fixes(font):
    """Apply fixes needed for Android."""

    # Remove combining keycap and the arrows from the cmap table:
    # https://github.com/google/roboto/issues/99
    font_data.delete_from_cmap(font, [
        0x20E3, # COMBINING ENCLOSING KEYCAP
        0x2191, # UPWARDS ARROW
        0x2193, # DOWNWARDS ARROW
        ])

    # Drop tables not useful on Android
    for table in ['LTSH', 'hdmx', 'VDMX', 'gasp']:
        if table in font:
            del font[table]

    # turn off round-to-grid flags in certain problem components
    # https://github.com/google/roboto/issues/153
    glyph_set = font.getGlyphSet()
    ellipsis = glyph_set['ellipsis']._glyph
    for component in ellipsis.components:
        component.flags &= ~(1 << 2)
def apply_android_specific_fixes(font):
    """Apply fixes needed for Android."""
    # Set ascent, descent, and lineGap values to Android K values
    hhea = font['hhea']
    hhea.ascent = 1900
    hhea.descent = -500
    hhea.lineGap = 0

    # Remove combining keycap and the arrows from the cmap table:
    # https://code.google.com/a/google.com/p/roboto/issues/detail?id=52
    font_data.delete_from_cmap(
        font,
        [
            0x20E3,  # COMBINING ENCLOSING KEYCAP
            0x2191,  # UPWARDS ARROW
            0x2193,  # DOWNWARDS ARROW
        ])

    # Drop tables not useful on Android
    for table in ['LTSH', 'hdmx', 'VDMX', 'gasp']:
        if table in font:
            del font[table]
Exemple #11
0
def apply_android_specific_fixes(font):
    """Apply fixes needed for Android."""

    # Remove combining keycap and the arrows from the cmap table:
    # https://github.com/google/roboto/issues/99
    font_data.delete_from_cmap(
        font,
        [
            0x20E3,  # COMBINING ENCLOSING KEYCAP
            0x2191,  # UPWARDS ARROW
            0x2193,  # DOWNWARDS ARROW
        ])

    # Drop tables not useful on Android
    for table in ['LTSH', 'hdmx', 'VDMX', 'gasp']:
        if table in font:
            del font[table]

    # turn off round-to-grid flags in certain problem components
    # https://github.com/google/roboto/issues/153
    glyph_set = font.getGlyphSet()
    ellipsis = glyph_set['ellipsis']._glyph
    for component in ellipsis.components:
        component.flags &= ~(1 << 2)
Exemple #12
0
 def _remove_from_cmap(infile, outfile, exclude=[]):
     font = ttLib.TTFont(infile)
     font_data.delete_from_cmap(font, exclude)
     font.save(outfile)
Exemple #13
0
 def _remove_from_cmap(infile, outfile, exclude=[]):
   font = ttLib.TTFont(infile)
   font_data.delete_from_cmap(font, exclude)
   font.save(outfile)
Exemple #14
0
def remove_from_cmap(infile, outfile, exclude=frozenset()):
    """Removes a set of characters from a font file's cmap table."""
    font = ttLib.TTFont(f'{SCRIPT_PATH}/{infile}')
    font_data.delete_from_cmap(font, exclude)
    font.save(outfile)
Exemple #15
0
def main(argv):
    import glob
    from fontTools import ttx, ttLib

    options = []

    option_map = {
        "-V": "verbose",
        "-O": "keep_outlines",
        "-U": "uncompressed",
        "-S": "small_glyph_metrics",
        "-C": "keep_chunks",
    }

    for key, value in option_map.items():
        if key in argv:
            options.append(value)
            argv.remove(key)

    if len(argv) < 4:
        print("""
Usage:

emoji_builder.py [-V] [-O] [-U] [-S] [-A] font.ttf out-font.ttf strike-prefix...

This will search for files that have strike-prefix followed
by a hex number, and end in ".png".  For example, if strike-prefix
is "icons/uni", then files with names like "icons/uni1f4A9.png" will
be loaded.  All images for the same strike should have the same size
for best results.

If multiple strike-prefix parameters are provided, multiple
strikes will be embedded, in the order provided.

The script then embeds color bitmaps in the font, for characters
that the font already supports, and writes the new font out.

If -V is given, verbose mode is enabled.

If -U is given, uncompressed images are stored (imageFormat=1).

If -S is given, PNG images are stored with small glyph metrics (imageFormat=17).

By default, PNG images are stored with big glyph metrics (imageFormat=18).

If -O is given, the outline tables ('glyf', 'CFF ') and
related tables are NOT dropped from the font.
By default they are dropped.

If -C is given, unused chunks (color profile, etc) are NOT
dropped from the PNG images when embedding.
By default they are dropped.
""",
              file=sys.stderr)
        sys.exit(1)

    font_file = argv[1]
    out_file = argv[2]
    img_prefixes = argv[3:]
    del argv

    def add_font_table(font, tag, data):
        tab = ttLib.tables.DefaultTable.DefaultTable(tag)
        tab.data = str(data)
        font[tag] = tab

    def drop_outline_tables(font):
        for tag in ['cvt ', 'fpgm', 'glyf', 'loca', 'prep', 'CFF ', 'VORG']:
            try:
                del font[tag]
            except KeyError:
                pass

    print()

    font = ttx.TTFont(font_file)
    print("Loaded font '%s'." % font_file)

    font_metrics = FontMetrics(font['head'].unitsPerEm, font['hhea'].ascent,
                               -font['hhea'].descent)
    print("Font metrics: upem=%d ascent=%d descent=%d." % \
          (font_metrics.upem, font_metrics.ascent, font_metrics.descent))
    glyph_metrics = font['hmtx'].metrics
    unicode_cmap = font['cmap'].getcmap(3, 10)
    if not unicode_cmap:
        unicode_cmap = font['cmap'].getcmap(3, 1)
    if not unicode_cmap:
        raise Exception("Failed to find a Unicode cmap.")

    image_format = 1 if 'uncompressed' in options else (
        17 if 'small_glyph_metrics' in options else 18)

    ebdt = CBDT(font_metrics, options)
    ebdt.write_header()
    eblc = CBLC(font_metrics, options)
    eblc.write_header()
    eblc.start_strikes(len(img_prefixes))

    def is_vs(cp):
        return cp >= 0xfe00 and cp <= 0xfe0f

    for img_prefix in img_prefixes:
        print()

        img_files = {}
        glb = "%s*.png" % img_prefix
        print("Looking for images matching '%s'." % glb)
        for img_file in glob.glob(glb):
            codes = img_file[len(img_prefix):-4]
            if "_" in codes:
                pieces = codes.split("_")
                cps = [int(code, 16) for code in pieces]
                uchars = "".join([unichr(cp) for cp in cps if not is_vs(cp)])
            else:
                cp = int(codes, 16)
                if is_vs(cp):
                    print("ignoring unexpected vs input %04x" % cp)
                    continue
                uchars = unichr(cp)
            img_files[uchars] = img_file
        if not img_files:
            raise Exception("No image files found in '%s'." % glb)
        print("Found images for %d characters in '%s'." %
              (len(img_files), glb))

        glyph_imgs = {}
        advance = width = height = 0
        for uchars, img_file in img_files.items():
            if len(uchars) == 1:
                try:
                    glyph_name = unicode_cmap.cmap[ord(uchars)]
                except:
                    print("no cmap entry for %x" % ord(uchars))
                    raise ValueError("%x" % ord(uchars))
            else:
                glyph_name = get_glyph_name_from_gsub(uchars, font,
                                                      unicode_cmap.cmap)
            glyph_id = font.getGlyphID(glyph_name)
            glyph_imgs[glyph_id] = img_file
            if "verbose" in options:
                uchars_name = ",".join(["%04X" % ord(char) for char in uchars])
                # print "Matched U+%s: id=%d name=%s image=%s" % (
                #    uchars_name, glyph_id, glyph_name, img_file)

            advance += glyph_metrics[glyph_name][0]
            w, h = PNG(img_file).get_size()
            width += w
            height += h

        glyphs = sorted(glyph_imgs.keys())
        if not glyphs:
            raise Exception(
                "No common characters found between font and '%s'." % glb)
        print("Embedding images for %d glyphs for this strike." % len(glyphs))

        advance, width, height = (div(x, len(glyphs))
                                  for x in (advance, width, height))
        strike_metrics = StrikeMetrics(font_metrics, advance, width, height)
        print("Strike ppem set to %d." % (strike_metrics.y_ppem))

        ebdt.start_strike(strike_metrics)
        ebdt.write_glyphs(glyphs, glyph_imgs, image_format)
        glyph_maps = ebdt.end_strike()

        eblc.write_strike(strike_metrics, glyph_maps)

    print()

    ebdt = ebdt.data()
    add_font_table(font, 'CBDT', ebdt)
    print("CBDT table synthesized: %d bytes." % len(ebdt))
    eblc.end_strikes()
    eblc = eblc.data()
    add_font_table(font, 'CBLC', eblc)
    print("CBLC table synthesized: %d bytes." % len(eblc))

    print()

    if 'keep_outlines' not in options:
        drop_outline_tables(font)
        print("Dropped outline ('glyf', 'CFF ') and related tables.")

# hack removal of cmap pua entry for unknown flag glyph.  If we try to
# remove it earlier, getGlyphID dies.  Need to restructure all of this
# code.
    font_data.delete_from_cmap(font, [0xfe82b])

    font.save(out_file)
    print("Output font '%s' generated." % out_file)
def remove_from_cmap(infile, outfile, exclude=frozenset()):
    """Removes a set of characters from a font file's cmap table."""
    font = ttLib.TTFont(infile)
    font_data.delete_from_cmap(font, exclude)
    font.save(outfile)
Exemple #17
0
def main (argv):
	import glob
	from fontTools import ttx, ttLib

	options = []

	option_map = {
		"-V": "verbose",
		"-O": "keep_outlines",
		"-U": "uncompressed",
                "-S": "small_glyph_metrics",
		"-C": "keep_chunks",
	}

	for key, value in option_map.items ():
		if key in argv:
			options.append (value)
			argv.remove (key)

	if len (argv) < 4:
		print("""
Usage:

emoji_builder.py [-V] [-O] [-U] [-S] [-A] font.ttf out-font.ttf strike-prefix...

This will search for files that have strike-prefix followed
by a hex number, and end in ".png".  For example, if strike-prefix
is "icons/uni", then files with names like "icons/uni1f4A9.png" will
be loaded.  All images for the same strike should have the same size
for best results.

If multiple strike-prefix parameters are provided, multiple
strikes will be embedded, in the order provided.

The script then embeds color bitmaps in the font, for characters
that the font already supports, and writes the new font out.

If -V is given, verbose mode is enabled.

If -U is given, uncompressed images are stored (imageFormat=1).

If -S is given, PNG images are stored with small glyph metrics (imageFormat=17).

By default, PNG images are stored with big glyph metrics (imageFormat=18).

If -O is given, the outline tables ('glyf', 'CFF ') and
related tables are NOT dropped from the font.
By default they are dropped.

If -C is given, unused chunks (color profile, etc) are NOT
dropped from the PNG images when embedding.
By default they are dropped.
""", file=sys.stderr)
		sys.exit (1)

	font_file = argv[1]
	out_file = argv[2]
	img_prefixes = argv[3:]
	del argv

	def add_font_table (font, tag, data):
		tab = ttLib.tables.DefaultTable.DefaultTable (tag)
		tab.data = str(data)
		font[tag] = tab

	def drop_outline_tables (font):
		for tag in ['cvt ', 'fpgm', 'glyf', 'loca', 'prep', 'CFF ', 'VORG']:
			try:
				del font[tag]
			except KeyError:
				pass


	print()

	font = ttx.TTFont (font_file)
	print("Loaded font '%s'." % font_file)

	font_metrics = FontMetrics (font['head'].unitsPerEm,
				    font['hhea'].ascent,
				    -font['hhea'].descent)
	print("Font metrics: upem=%d ascent=%d descent=%d." % \
	      (font_metrics.upem, font_metrics.ascent, font_metrics.descent))
	glyph_metrics = font['hmtx'].metrics
	unicode_cmap = font['cmap'].getcmap (3, 10)
	if not unicode_cmap:
		unicode_cmap = font['cmap'].getcmap (3, 1)
	if not unicode_cmap:
		raise Exception ("Failed to find a Unicode cmap.")

	image_format = 1 if 'uncompressed' in options else (17
                if 'small_glyph_metrics' in options else 18)

	ebdt = CBDT (font_metrics, options)
	ebdt.write_header ()
	eblc = CBLC (font_metrics, options)
	eblc.write_header ()
	eblc.start_strikes (len (img_prefixes))

        def is_vs(cp):
                return cp >= 0xfe00 and cp <= 0xfe0f

	for img_prefix in img_prefixes:
		print()

		img_files = {}
		glb = "%s*.png" % img_prefix
		print("Looking for images matching '%s'." % glb)
		for img_file in glob.glob (glb):
			codes = img_file[len (img_prefix):-4]
			if "_" in codes:
				pieces = codes.split ("_")
                                cps = [int(code, 16) for code in pieces]
				uchars = "".join ([unichr(cp) for cp in cps if not is_vs(cp)])
			else:
                                cp = int(codes, 16)
                                if is_vs(cp):
                                        print("ignoring unexpected vs input %04x" % cp)
                                        continue
				uchars = unichr(cp)
			img_files[uchars] = img_file
		if not img_files:
			raise Exception ("No image files found in '%s'." % glb)
		print("Found images for %d characters in '%s'." % (len (img_files), glb))

		glyph_imgs = {}
		advance = width = height = 0
		for uchars, img_file in img_files.items ():
			if len (uchars) == 1:
                                try:
                                        glyph_name = unicode_cmap.cmap[ord (uchars)]
                                except:
                                        print("no cmap entry for %x" % ord(uchars))
                                        raise ValueError("%x" % ord(uchars))
			else:
				glyph_name = get_glyph_name_from_gsub (uchars, font, unicode_cmap.cmap)
			glyph_id = font.getGlyphID (glyph_name)
			glyph_imgs[glyph_id] = img_file
			if "verbose" in options:
				uchars_name = ",".join (["%04X" % ord (char) for char in uchars])
				# print "Matched U+%s: id=%d name=%s image=%s" % (
                                #    uchars_name, glyph_id, glyph_name, img_file)

			advance += glyph_metrics[glyph_name][0]
			w, h = PNG (img_file).get_size ()
			width += w
			height += h

		glyphs = sorted (glyph_imgs.keys ())
		if not glyphs:
			raise Exception ("No common characters found between font and '%s'." % glb)
		print("Embedding images for %d glyphs for this strike." % len (glyphs))

		advance, width, height = (div (x, len (glyphs)) for x in (advance, width, height))
		strike_metrics = StrikeMetrics (font_metrics, advance, width, height)
		print("Strike ppem set to %d." % (strike_metrics.y_ppem))

		ebdt.start_strike (strike_metrics)
		ebdt.write_glyphs (glyphs, glyph_imgs, image_format)
		glyph_maps = ebdt.end_strike ()

		eblc.write_strike (strike_metrics, glyph_maps)

	print()

	ebdt = ebdt.data ()
	add_font_table (font, 'CBDT', ebdt)
	print("CBDT table synthesized: %d bytes." % len (ebdt))
	eblc.end_strikes ()
	eblc = eblc.data ()
	add_font_table (font, 'CBLC', eblc)
	print("CBLC table synthesized: %d bytes." % len (eblc))

	print()

	if 'keep_outlines' not in options:
		drop_outline_tables (font)
		print("Dropped outline ('glyf', 'CFF ') and related tables.")

        # hack removal of cmap pua entry for unknown flag glyph.  If we try to
        # remove it earlier, getGlyphID dies.  Need to restructure all of this
        # code.
        font_data.delete_from_cmap(font, [0xfe82b])

	font.save (out_file)
	print("Output font '%s' generated." % out_file)