Beispiel #1
0
def apply_web_specific_fixes(font, family_name):
    """Apply fixes needed for web fonts."""
    # Set OS/2 table values to old values
    os2 = font['OS/2']
    os2.sTypoAscender = 1536
    os2.sTypoDescender = -512
    os2.sTypoLineGap = 102
    os2.usWinAscent = 1946
    os2.usWinDescent = 512

    subfamily_name = font_data.get_name_records(font)[2].encode('ASCII')
    assert (subfamily_name in [
        'Thin', 'Thin Italic', 'Light', 'Light Italic', 'Regular', 'Italic',
        'Medium', 'Medium Italic', 'Bold', 'Bold Italic', 'Black',
        'Black Italic'
    ])

    if 'Condensed' in font_data.get_name_records(font)[1]:
        family_name += ' Condensed'
    full_name = family_name + ' ' + subfamily_name

    # Family name
    font_data.set_name_record(font, 1, family_name)
    font_data.set_name_record(font, 16, family_name)

    # Unique identifier and full name
    font_data.set_name_record(font, 3, full_name)
    font_data.set_name_record(font, 4, full_name)
    font_data.set_name_record(font, 18, None)

    # PostScript name
    font_data.set_name_record(font, 6,
                              (family_name + '-' + subfamily_name).replace(
                                  ' ', ''))
def apply_web_specific_fixes(font, family_name):
    """Apply fixes needed for web fonts."""
    # Set OS/2 table values to old values
    os2 = font['OS/2']
    os2.sTypoAscender = 1536
    os2.sTypoDescender = -512
    os2.sTypoLineGap = 102
    os2.usWinAscent = 1946
    os2.usWinDescent = 512

    subfamily_name = font_data.get_name_records(font)[2].encode('ASCII')
    assert(subfamily_name in
        ['Thin', 'Thin Italic',
         'Light', 'Light Italic',
         'Regular', 'Italic',
         'Medium', 'Medium Italic',
         'Bold', 'Bold Italic',
         'Black', 'Black Italic'])

    if 'Condensed' in font_data.get_name_records(font)[1]:
        family_name += ' Condensed'
    full_name = family_name + ' ' + subfamily_name

    # Family name
    font_data.set_name_record(font, 1, family_name)
    font_data.set_name_record(font, 16, family_name)

    # Unique identifier and full name
    font_data.set_name_record(font, 3, full_name)
    font_data.set_name_record(font, 4, full_name)
    font_data.set_name_record(font, 18, None)

    # PostScript name
    font_data.set_name_record(
        font, 6, (family_name+'-'+subfamily_name).replace(' ', ''))
Beispiel #3
0
def apply_web_specific_fixes(font, family_name):
    """Apply fixes needed for web fonts."""
    # Set OS/2 table values to old values
    os2 = font['OS/2']
    os2.sTypoAscender = 1536
    os2.sTypoDescender = -512
    os2.sTypoLineGap = 102
    os2.usWinAscent = 1946
    os2.usWinDescent = 512

    subfamily_name = font_data.get_name_records(font)[2].encode('ASCII')
    assert(subfamily_name in
        ['Thin', 'Thin Italic',
         'Light', 'Light Italic',
         'Regular', 'Italic',
         'Medium', 'Medium Italic',
         'Bold', 'Bold Italic',
         'Black', 'Black Italic'])

    if 'Condensed' in font_data.get_name_records(font)[1]:
        family_name += ' Condensed'
    full_name = family_name + ' ' + subfamily_name

    # Family, subfamily names
    font_data.set_name_record(font, 16, family_name)
    style_map = ['Regular', 'Bold', 'Italic', 'Bold Italic']
    if subfamily_name in style_map:
        font_data.set_name_record(font, 1, family_name)
    else:
        weight = subfamily_name.split()[0]
        new_family_name = family_name
        if weight != 'Regular':
            new_family_name += ' ' + weight
        font_data.set_name_record(font, 1, new_family_name)

        # all weights outside regular and bold should only have subfamily
        # "Regular" or "Italic"
        italic = subfamily_name.endswith('Italic')
        font_data.set_name_record(font, 2, style_map[italic << 1])


    # Unique identifier and full name
    font_data.set_name_record(font, 3, full_name)
    font_data.set_name_record(font, 4, full_name.replace(' Regular', ''))
    font_data.set_name_record(font, 18, None)

    # PostScript name
    font_data.set_name_record(
        font, 6, (family_name+'-'+subfamily_name).replace(' ', ''))

    # Copyright message
    font_data.set_name_record(
        font, 0, 'Copyright 2011 Google Inc. All Rights Reserved.')
Beispiel #4
0
 def setUp(self):
     font_files, self.fonts = self.loaded_fonts
     self.font_files = [path.basename(f) for f in font_files]
     self.condensed_family_name = self.family_name + ' Condensed'
     self.names = []
     for font in self.fonts:
         self.names.append(font_data.get_name_records(font))
Beispiel #5
0
def summarize_file(root, path):
    font = ttLib.TTFont(path)
    table_info = {}
    reader = font.reader
    for tag in reader.keys():
        entry = reader.tables[tag]
        entry_len = entry.length
        entry_checkSum = int(entry.checkSum)
        if entry_checkSum < 0:
            entry_checkSum += 0x100000000
        table_info[tag] = (entry_len, entry_checkSum)

    relpath = path[len(root) + 1:]
    size = os.path.getsize(path)
    # Printable_font_revision requires you specify the accuracy of digits.
    # ttLib apparently reads the fixed values as a float, so it loses the info.
    # Adobe fonts use 3 digits, so the default from printable_font_revision of 2
    # is insufficient.
    # Assume that the name from the name table is accurate, and use it instead.
    version_string = noto_lint.font_version(font)
    match = re.match(r'Version (\d+\.\d+)', version_string)
    if match:
        version = match.group(1)
    else:
        version = noto_lint.printable_font_revision(font)  # default 2
    num_glyphs = len(font.getGlyphOrder())
    full_name = font_data.get_name_records(font)[4]
    cmap = set(
        get_largest_cmap(font).keys())  # copy needed? what's the lifespan?
    num_chars = len(cmap)
    font.close()

    return (relpath, version, full_name, size, num_glyphs, num_chars, cmap,
            table_info)
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)
Beispiel #7
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, 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 _load_font(data, codelist_map):
    if len(data) < 4:
      data = data + tuple([None] * (4 - len(data)))
    key, fname, name, codelistfile = data

    if not fname:
      if not name:
        raise Exception('must have name if no font provided')
      if not codelistfile:
        raise Exception('must have codelist file if no font provided')
      fontpath = None
    else:
      fontpath = path.join(data_dir, fname)
      if not path.isfile(fontpath):
        raise Exception('font "%s" not found' % fontpath)

    if codelistfile:
      codelist = _load_codelist(codelistfile, data_dir, codelist_map)

    if fname and (not codelistfile or not name):
      font = ttLib.TTFont(fontpath)
      if not name:
        names = font_data.get_name_records(font)
        name = names[16] if 16 in names else names[1] if 1 in names else None
        if not name:
          raise Exception('cannot read name from font "%s"' % fontpath)
      if not codelistfile:
        codelist = CodeList.fromset(font_data.get_cmap(font))

    return key, fontpath, name, codelist
Beispiel #9
0
 def setUp(self):
     font_files, self.fonts = self.loaded_fonts
     self.font_files = [path.basename(f) for f in font_files]
     self.condensed_family_name = self.family_name + ' Condensed'
     self.names = []
     for font in self.fonts:
         self.names.append(font_data.get_name_records(font))
Beispiel #10
0
def fix_font(f, dstdir, version_info, autohint, dry_run):
  print '\n-----\nfont:', f
  font = ttLib.TTFont(f)
  fname = path.basename(f)
  expected_font_revision = get_revision(font, fname)
  if expected_font_revision != None:
    font_revision = font_data.printable_font_revision(font, 3)
    if font_revision != expected_font_revision:
      _alert('revision', font_revision, expected_font_revision)
      font['head'].fontRevision = float(expected_font_revision)

    names = font_data.get_name_records(font)
    NAME_ID = 5
    font_version = names[NAME_ID]
    expected_version = (
        'Version %s;%s' % (expected_font_revision, version_info))
    if font_version != expected_version:
      _alert('version string', font_version, expected_version)
      font_data.set_name_record(font, NAME_ID, expected_version)

  expected_upem = 2048
  upem = font['head'].unitsPerEm
  if upem != expected_upem:
    print 'expected %d upem but got %d upem' % (expected_upem, upem)

  if _is_ui_metrics(fname):
    if upem == 2048:
      expected_ascent = 2163
      expected_descent = -555
    elif upem == 1000:
      expected_ascent = 1069
      expected_descent = -293
    else:
      raise Exception('no expected ui ascent/descent for upem: %d' % upem)

    font_ascent = font['hhea'].ascent
    font_descent = font['hhea'].descent
    if font_ascent != expected_ascent:
      _alert_and_check('ascent', font_ascent, expected_ascent, 2)
      font['hhea'].ascent = expected_ascent
      font['OS/2'].sTypoAscender = expected_ascent
      font['OS/2'].usWinAscent = expected_ascent

    if font_descent != expected_descent:
      _alert_and_check('descent', font_descent, expected_descent, 2)
      font['hhea'].descent = expected_descent
      font['OS/2'].sTypoDescender = expected_descent
      font['OS/2'].usWinDescent = -expected_descent

  tool_utils.ensure_dir_exists(path.join(dstdir, 'unhinted'))

  dst = path.join(dstdir, 'unhinted', fname)
  if dry_run:
    print 'dry run would write:\n  "%s"' % dst
  else:
    font.save(dst)
    print 'wrote %s' % dst

  if autohint:
    autohint_font(dst, path.join(dstdir, 'hinted', fname), autohint, dry_run)
Beispiel #11
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)
Beispiel #12
0
def apply_web_specific_fixes(font, family_name):
    """Apply fixes needed for web fonts."""
    # Set OS/2 table values to old values
    os2 = font['OS/2']
    os2.sTypoAscender = 1536
    os2.sTypoDescender = -512
    os2.sTypoLineGap = 102
    os2.usWinAscent = 1946
    os2.usWinDescent = 512

    subfamily_name = font_data.get_name_records(font)[2].encode('ASCII')
    assert(subfamily_name in
        ['Thin', 'Thin Italic',
         'Light', 'Light Italic',
         'Regular', 'Italic',
         'Medium', 'Medium Italic',
         'Bold', 'Bold Italic',
         'Black', 'Black Italic'])

    if 'Condensed' in font_data.get_name_records(font)[1]:
        family_name += ' Condensed'
    full_name = family_name + ' ' + subfamily_name

    # macStyle
    bold = subfamily_name.startswith(('Bold', 'Black'))
    italic = subfamily_name.endswith('Italic')
    macStyle = (italic << 1) | bold
    font['head'].macStyle = macStyle

    # Family, subfamily names
    font_data.set_name_record(font, 16, family_name)
    style_map = ['Regular', 'Bold', 'Italic', 'Bold Italic']
    if subfamily_name in style_map:
        font_data.set_name_record(font, 1, family_name)
    else:
        weight = subfamily_name.split()[0]
        font_data.set_name_record(font, 1, '%s %s' % (family_name, weight))
        font_data.set_name_record(font, 2, style_map[macStyle])

    # Unique identifier and full name
    font_data.set_name_record(font, 3, full_name)
    font_data.set_name_record(font, 4, full_name)
    font_data.set_name_record(font, 18, None)

    # PostScript name
    font_data.set_name_record(
        font, 6, (family_name+'-'+subfamily_name).replace(' ', ''))
Beispiel #13
0
def apply_web_specific_fixes(font, family_name):
    """Apply fixes needed for web fonts."""
    # Set OS/2 table values to old values
    os2 = font['OS/2']
    os2.sTypoAscender = 1536
    os2.sTypoDescender = -512
    os2.sTypoLineGap = 102
    os2.usWinAscent = 1946
    os2.usWinDescent = 512

    subfamily_name = font_data.get_name_records(font)[2].encode('ASCII')
    assert (subfamily_name in [
        'Thin', 'Thin Italic', 'Light', 'Light Italic', 'Regular', 'Italic',
        'Medium', 'Medium Italic', 'Bold', 'Bold Italic', 'Black',
        'Black Italic'
    ])

    if 'Condensed' in font_data.get_name_records(font)[1]:
        family_name += ' Condensed'
    full_name = family_name + ' ' + subfamily_name

    # macStyle
    bold = subfamily_name.startswith(('Bold', 'Black'))
    italic = subfamily_name.endswith('Italic')
    macStyle = (italic << 1) | bold
    font['head'].macStyle = macStyle

    # Family, subfamily names
    font_data.set_name_record(font, 16, family_name)
    style_map = ['Regular', 'Bold', 'Italic', 'Bold Italic']
    if subfamily_name in style_map:
        font_data.set_name_record(font, 1, family_name)
    else:
        weight = subfamily_name.split()[0]
        font_data.set_name_record(font, 1, '%s %s' % (family_name, weight))
        font_data.set_name_record(font, 2, style_map[macStyle])

    # Unique identifier and full name
    font_data.set_name_record(font, 3, full_name)
    font_data.set_name_record(font, 4, full_name)
    font_data.set_name_record(font, 18, None)

    # PostScript name
    font_data.set_name_record(font, 6,
                              (family_name + '-' + subfamily_name).replace(
                                  ' ', ''))
Beispiel #14
0
def get_font_family_name(font_file):
    font = ttLib.TTFont(font_file, fontNumber=0)
    name_record = font_data.get_name_records(font)
    try:
        name = name_record[16]
    except KeyError:
        name = name_record[1]
        if name.endswith("Regular"):
            name = name.rsplit(" ", 1)[0]
    return name
Beispiel #15
0
def get_font_family_name(font_file):
    font = ttLib.TTFont(font_file, fontNumber=0)
    name_record = font_data.get_name_records(font)
    try:
      name = name_record[16]
    except KeyError:
      name = name_record[1]
      if name.endswith('Regular'):
        name = name.rsplit(' ', 1)[0]
    return name
Beispiel #16
0
def fix_name_table(font):
    """Fix copyright and reversed values in the 'name' table."""
    modified = False
    name_records = font_data.get_name_records(font)

    copyright_data = name_records[0]
    years = re.findall('20[0-9][0-9]', copyright_data)
    year = min(years)
    copyright_data = u'Copyright %s Google Inc. All Rights Reserved.' % year

    if copyright_data != name_records[0]:
        print 'Updated copyright message to "%s"' % copyright_data
        font_data.set_name_record(font, 0, copyright_data)
        modified = True

    for name_id in [1, 3, 4, 6]:
        record = name_records[name_id]
        for source in NAME_CORRECTIONS:
            if source in record:
                oldrecord = record
                record = record.replace(source, NAME_CORRECTIONS[source])
                break
        if record != name_records[name_id]:
            font_data.set_name_record(font, name_id, record)
            print 'Updated name table record #%d from "%s" to "%s"' % (
                name_id, oldrecord, record)
            modified = True

    trademark_names = ['Noto', 'Arimo', 'Tinos', 'Cousine']
    trademark_name = None
    font_family = name_records[1]
    for name in trademark_names:
        if font_family.find(name) != -1:
            trademark_name = name
            break
    if not trademark_name:
        print 'no trademarked name in \'%s\'' % font_family
    else:
        trademark_line = TRADEMARK_TEMPLATE % trademark_name
        if name_records[7] != trademark_line:
            old_line = name_records[7]
            font_data.set_name_record(font, 7, trademark_line)
            modified = True
            print 'Updated name table record 7 from "%s" to "%s"' % (
                old_line, trademark_line)

    if name_records[11] != NOTO_URL:
        font_data.set_name_record(font, 11, NOTO_URL)
        modified = True
        print 'Updated name table record 11 to "%s"' % NOTO_URL

    # TODO: check preferred family/subfamily(16&17)

    return modified
def fix_name_table(font):
    """Fix copyright and reversed values in the 'name' table."""
    modified = False
    name_records = font_data.get_name_records(font)

    copyright_data = name_records[0]
    years = re.findall('20[0-9][0-9]', copyright_data)
    year = min(years)
    copyright_data = u'Copyright %s Google Inc. All Rights Reserved.' % year

    if copyright_data != name_records[0]:
        print 'Updated copyright message to "%s"' % copyright_data
        font_data.set_name_record(font, 0, copyright_data)
        modified = True

    for name_id in [1, 3, 4, 6]:
        record = name_records[name_id]
        for source in NAME_CORRECTIONS:
            if source in record:
                oldrecord = record
                record = record.replace(source, NAME_CORRECTIONS[source])
                break
        if record != name_records[name_id]:
            font_data.set_name_record(font, name_id, record)
            print 'Updated name table record #%d from "%s" to "%s"' % (
                name_id, oldrecord, record)
            modified = True

    trademark_names = ['Noto', 'Arimo', 'Tinos', 'Cousine']
    trademark_name = None
    font_family = name_records[1]
    for name in trademark_names:
        if font_family.find(name) != -1:
            trademark_name = name
            break
    if not trademark_name:
        print 'no trademarked name in \'%s\'' % font_family
    else:
        trademark_line = TRADEMARK_TEMPLATE % trademark_name
        if name_records[7] != trademark_line:
            old_line = name_records[7]
            font_data.set_name_record(font, 7, trademark_line)
            modified = True
            print 'Updated name table record 7 from "%s" to "%s"' % (old_line, trademark_line)

    if name_records[11] != NOTO_URL:
        font_data.set_name_record(font, 11, NOTO_URL)
        modified = True
        print 'Updated name table record 11 to "%s"' % NOTO_URL

    # TODO: check preferred family/subfamily(16&17)

    return modified
Beispiel #18
0
def get_bumped_version(ttfont, is_hinted=None):
  """Return bumped values for the header and name tables."""

  names = font_data.get_name_records(ttfont)
  version = names[_VERSION_ID]
  m = re.match(r'Version (\d{1,5})\.(\d{1,5})( uh)?(;.*)?', version)
  if not m:
    print '! Could not match version string (%s)' % version
    return None, None

  major_version = m.group(1)
  minor_version = m.group(2)
  print 'old version: "%s"' % version
  if is_hinted == None:
    is_hinted = not bool(m.group(3))
    print 'computed hinted = %s' % is_hinted

  version_remainder = m.group(4)
  accuracy = len(minor_version)
  print_revision = font_data.printable_font_revision(ttfont, accuracy)
  # sanity check
  expected_revision = major_version + '.' + minor_version
  if expected_revision != print_revision:
    raise ValueError('! Expected revision \'%s\' but got revision \'%s\'' % (
        expected_revision, print_revision))

  # bump the minor version keeping significant digits:
  new_minor_version = str(int(minor_version) + 1).zfill(accuracy)
  new_revision = major_version + '.' + new_minor_version
  print 'Update revision from  \'%s\' to \'%s\'' % (
      expected_revision, new_revision)
  # double check we are going to properly round-trip this value
  float_revision = float(new_revision)
  fixed_revision = misc.fixedTools.floatToFixed(float_revision, 16)
  rt_float_rev = misc.fixedTools.fixedToFloat(fixed_revision, 16)
  rt_float_rev_int = int(rt_float_rev)
  rt_float_rev_frac = int(round((rt_float_rev - rt_float_rev_int) *
                                10 ** accuracy))
  rt_new_revision = (str(rt_float_rev_int) + '.' +
                     str(rt_float_rev_frac).zfill(accuracy))
  if new_revision != rt_new_revision:
    raise ValueError(
        '! Could not update new revision, expected \'%s\' but got \'%s\'' % (
        new_revision, rt_new_revision))

  new_version_string = 'Version ' + new_revision
  if not is_hinted:
    new_version_string += ' uh'
  if version_remainder:
    new_version_string += version_remainder

  return float_revision, new_version_string
Beispiel #19
0
def get_bumped_version(ttfont, is_hinted=None):
    """Return bumped values for the header and name tables."""

    names = font_data.get_name_records(ttfont)
    version = names[_VERSION_ID]
    m = re.match(r'Version (\d{1,5})\.(\d{1,5})( uh)?(;.*)?', version)
    if not m:
        print('! Could not match version string (%s)' % version)
        return None, None

    major_version = m.group(1)
    minor_version = m.group(2)
    print('old version: "%s"' % version)
    if is_hinted == None:
        is_hinted = not bool(m.group(3))
        print('computed hinted = %s' % is_hinted)

    version_remainder = m.group(4)
    accuracy = len(minor_version)
    print_revision = font_data.printable_font_revision(ttfont, accuracy)
    # sanity check
    expected_revision = major_version + '.' + minor_version
    if expected_revision != print_revision:
        raise ValueError('! Expected revision \'%s\' but got revision \'%s\'' %
                         (expected_revision, print_revision))

    # bump the minor version keeping significant digits:
    new_minor_version = str(int(minor_version) + 1).zfill(accuracy)
    new_revision = major_version + '.' + new_minor_version
    print('Update revision from  \'%s\' to \'%s\'' %
          (expected_revision, new_revision))
    # double check we are going to properly round-trip this value
    float_revision = float(new_revision)
    fixed_revision = misc.fixedTools.floatToFixed(float_revision, 16)
    rt_float_rev = misc.fixedTools.fixedToFloat(fixed_revision, 16)
    rt_float_rev_int = int(rt_float_rev)
    rt_float_rev_frac = int(
        round((rt_float_rev - rt_float_rev_int) * 10**accuracy))
    rt_new_revision = (str(rt_float_rev_int) + '.' +
                       str(rt_float_rev_frac).zfill(accuracy))
    if new_revision != rt_new_revision:
        raise ValueError(
            '! Could not update new revision, expected \'%s\' but got \'%s\'' %
            (new_revision, rt_new_revision))

    new_version_string = 'Version ' + new_revision
    if not is_hinted:
        new_version_string += ' uh'
    if version_remainder:
        new_version_string += version_remainder

    return float_revision, new_version_string
Beispiel #20
0
def get_family_filename(family):
  """Returns a filename to use for a family zip of hinted/unhinted members.
     This is basically the postscript name with weight/style removed.
  """
  font = ttLib.TTFont(family.rep_member.filepath, fontNumber=0)
  name_record = font_data.get_name_records(font)
  try:
    name = name_record[6]
    ix = name.find('-')
    if ix >= 0:
      name = name[:ix]
  except KeyError:
    name = name_record[1]
    if name.endswith('Regular'):
      name = name.rsplit(' ', 1)[0]
    name = name.replace(' ', '')
  return name
Beispiel #21
0
def get_family_filename(family):
    """Returns a filename to use for a family zip of hinted/unhinted members.
    This is basically the postscript name with weight/style removed.
    """
    font = ttLib.TTFont(family.rep_member.filepath, fontNumber=0)
    name_record = font_data.get_name_records(font)
    try:
        name = name_record[6]
        ix = name.find("-")
        if ix >= 0:
            name = name[:ix]
    except KeyError:
        name = name_record[1]
        if name.endswith("Regular"):
            name = name.rsplit(" ", 1)[0]
        name = name.replace(" ", "")
    return name
Beispiel #22
0
def apply_temporary_fixes(font, is_for_cros=False):
    """Apply some temporary fixes."""
    # Fix usWeight:
    font_name = font_data.font_name(font)
    weight = noto_fonts.parse_weight(font_name)
    weight_number = noto_fonts.WEIGHTS[weight]
    # Chrome OS wants Thin to have usWeightClass=100
    if is_for_cros and weight == 'Thin':
        weight_number = 100
    font['OS/2'].usWeightClass = weight_number

    # Set bold bits for Black (macStyle bit 0, fsSelection bit 5)
    name_records = font_data.get_name_records(font)
    family_name = name_records[1]
    if family_name.endswith('Black'):
        font['head'].macStyle |= (1 << 0)
        font['OS/2'].fsSelection |= (1 << 5)
        font['OS/2'].fsSelection &= ~(1 << 6)
Beispiel #23
0
def apply_temporary_fixes(font, is_for_cros=False):
    """Apply some temporary fixes."""
    # Fix usWeight:
    font_name = font_data.font_name(font)
    weight = noto_fonts.parse_weight(font_name)
    weight_number = noto_fonts.WEIGHTS[weight]
    # Chrome OS wants Thin to have usWeightClass=100
    if is_for_cros and weight == 'Thin':
        weight_number = 100
    font['OS/2'].usWeightClass = weight_number

    # Set bold bits for Black (macStyle bit 0, fsSelection bit 5)
    name_records = font_data.get_name_records(font)
    family_name = name_records[1]
    if family_name.endswith('Black'):
        font['head'].macStyle |= (1 << 0)
        font['OS/2'].fsSelection |= (1 << 5)
        font['OS/2'].fsSelection &= ~(1 << 6)
Beispiel #24
0
def apply_temporary_fixes(font):
    """Apply some temporary fixes."""
    # Fix usWeight:
    font_name = font_data.font_name(font)
    weight = noto_fonts.parse_weight(font_name)
    weight_number = noto_fonts.WEIGHTS[weight]
    font['OS/2'].usWeightClass = weight_number

    # Set ascent, descent, and lineGap values to Android K values
    hhea = font['hhea']
    hhea.ascent = 1900
    hhea.descent = -500
    hhea.lineGap = 0

    # Set bold bits for Black (macStyle bit 0, fsSelection bit 5)
    name_records = font_data.get_name_records(font)
    family_name = name_records[1]
    if family_name.endswith('Black'):
        font['head'].macStyle |= (1 << 0)
        font['OS/2'].fsSelection |= (1 << 5)
        font['OS/2'].fsSelection &= ~(1 << 6)
def apply_temporary_fixes(font):
    """Apply some temporary fixes."""
    # Fix usWeight:
    font_name = font_data.font_name(font)
    weight = noto_fonts.parse_weight(font_name)
    weight_number = noto_fonts.WEIGHTS[weight]
    font['OS/2'].usWeightClass = weight_number

    # Set ascent, descent, and lineGap values to Android K values
    hhea = font['hhea']
    hhea.ascent = 1900
    hhea.descent = -500
    hhea.lineGap = 0

    # Set bold bits for Black (macStyle bit 0, fsSelection bit 5)
    name_records = font_data.get_name_records(font)
    family_name = name_records[1]
    if family_name.endswith('Black'):
        font['head'].macStyle |= (1 << 0)
        font['OS/2'].fsSelection |= (1 << 5)
        font['OS/2'].fsSelection &= ~(1 << 6)
def fix_name_table(font):
    """Fix copyright and reversed values in the 'name' table."""
    modified = False
    name_records = font_data.get_name_records(font)

    copyright_data = name_records[0]
    years = re.findall('20[0-9][0-9]', copyright_data)
    year = min(years)
    copyright_data = u'Copyright %s Google Inc. All Rights Reserved.' % year

    if copyright_data != name_records[0]:
        print 'Updated copyright message to "%s"' % copyright_data
        font_data.set_name_record(font, 0, copyright_data)
        modified = True

    for name_id in [1, 3, 4, 6]:
        record = name_records[name_id]
        for source in NAME_CORRECTIONS:
            if source in record:
                oldrecord = record
                record = record.replace(source, NAME_CORRECTIONS[source])
                break
        if record != name_records[name_id]:
            font_data.set_name_record(font, name_id, record)
            print 'Updated name table record #%d from "%s" to "%s"' % (
                name_id, oldrecord, record)
            modified = True

    if name_records[7] != TRADEMARK_LINE:
      font_data.set_name_record(font, 7, TRADEMARK_LINE)
      modified = True
      print 'Updated name table record 7 to "%s"' % TRADEMARK_LINE

    # TODO: check preferred family/subfamily(16&17)

    return modified
Beispiel #27
0
def get_font_family_name(font_file):
    font = ttLib.TTFont(font_file)
    name_record = font_data.get_name_records(font)
    return name_record[1]
Beispiel #28
0
def _swat_font(noto_font, dst_root, dry_run):
  filepath = noto_font.filepath
  basename = path.basename(filepath)
  if noto_font.is_cjk:
    print '# Skipping cjk font %s' % basename
    return
  if noto_font.fmt == 'ttc':
    print '# Deferring ttc font %s' % basename
    _ttc_fonts[noto_font] = ttc_utils.ttcfile_filenames(filepath)
    return

  ttfont = ttLib.TTFont(filepath, fontNumber=0)

  names = font_data.get_name_records(ttfont)

  # create relative root path
  rel_filepath = _noto_relative_path(filepath)
  if not rel_filepath:
    raise ValueError('Could not identify noto root of %s' % filepath)

  print '-----\nUpdating %s' % rel_filepath

  dst_file = path.join(dst_root, rel_filepath)

  try:
    new_revision, new_version_string = get_bumped_version(
        ttfont, noto_font.is_hinted)
  except ValueError as e:
    print e
    return

  print '%s: %s' % ('Would write' if dry_run else 'Writing', dst_file)

  new_trademark = "%s is a trademark of Google Inc." % noto_font.family

  # description field should be set.
  # Roozbeh has note, make sure design field has information
  # on whether the font is hinted.
  # Missing in Lao and Khmer, default in Cham.
  if (cldr_data.get_english_script_name(noto_font.script) in
      ['Lao', 'Khmer', 'Cham']):
    new_description =  'Data %shinted.' % ('' if noto_font.is_hinted else 'un')
  # elif noto_font.vendor is 'Monotype':
  elif not noto_font.is_cjk and noto_font.family == 'Noto':
    new_description = (
      'Data %shinted. Designed by Monotype design team.' %
      ('' if noto_font.is_hinted else 'un'))
  else:
    new_description = None

  if re.match(r'^Copyright 201\d Google Inc. All Rights Reserved\.$',
              names[_COPYRIGHT_ID]):
    new_copyright = None
  else:
    new_copyright = '!!'

  if names.get(_DESIGNER_ID) in [
      'Steve Matteson',
      'Monotype Design Team',
      'Danh Hong',
      ]:
    new_designer = None
  elif names.get(_DESIGNER_ID) == 'Monotype Design team':
    new_designer = 'Monotype Design Team'
  elif (_DESIGNER_ID not in names
        and cldr_data.get_english_script_name(noto_font.script) == 'Khmer'):
    new_designer = 'Danh Hong'
  else:
    new_designer = '!!'

  if names.get(_DESIGNER_URL_ID) in [
      'http://www.monotype.com/studio',
      'http://www.khmertype.org',
      ]:
    new_designer_url = None
  elif names.get(_DESIGNER_URL_ID) in [
      'http://www.monotypeimaging.com/ProductsServices/TypeDesignerShowcase',
      ]:
    new_designer_url = 'http://www.monotype.com/studio'
  elif names.get(_DESIGNER_URL_ID) in [
      'http://www.khmertype.blogspot.com',
      'http://www.khmertype.blogspot.com/',
      'http://khmertype.blogspot.com/',
      'http://wwwkhmertype.blogspot.com.com/',
      ]:
    new_designer_url = 'http://www.khmertype.org'
  else:
    new_designer_url = '!!!'

  if names.get(_MANUFACTURER_ID) in [
      'Monotype Imaging Inc.',
      'Danh Hong',
      ]:
    new_manufacturer = None
  else:
    new_manufacturer = '!!!'

  def update(name_id, new, newText=None):
    old = names.get(name_id)
    if new and (new != old):
      if not dry_run and not '!!!' in new:
        font_data.set_name_record(ttfont, name_id, new, addIfMissing='win')

      label = _NAME_ID_LABELS[name_id]
      oldText = '\'%s\'' % old if old else 'None'
      newText = newText or ('\'%s\'' % new)
      print '%s:\n  old: %s\n  new: %s' % (label, oldText, newText or new)

      label_change = _changes.get(label)
      if not label_change:
        label_change = {}
        _changes[label] = label_change
      new_val_change = label_change.get(new)
      if not new_val_change:
        new_val_change = {}
        label_change[new] = new_val_change
      old_val_fonts = new_val_change.get(old)
      if not old_val_fonts:
        old_val_fonts = []
        new_val_change[old] = old_val_fonts
      old_val_fonts.append(noto_font.filepath)

  update(_COPYRIGHT_ID, new_copyright)
  update(_VERSION_ID, new_version_string)
  update(_TRADEMARK_ID, new_trademark)
  update(_MANUFACTURER_ID, new_manufacturer)
  update(_DESIGNER_ID, new_designer)
  update(_DESCRIPTION_ID, new_description)
  update(_VENDOR_URL_ID, _NOTO_URL)
  update(_DESIGNER_URL_ID, new_designer_url)
  update(_LICENSE_ID, _SIL_LICENSE, newText='(OFL)')
  update(_LICENSE_URL_ID, _SIL_LICENSE_URL)

  if autofix_for_release.fix_fstype(ttfont):
    _autofix['fstype'].append(noto_font.filepath)
  if autofix_for_release.fix_vendor_id(ttfont):
    _autofix['vendor_id'].append(noto_font.filepath)
  if autofix_for_release.fix_attachlist(ttfont):
    _autofix['attachlist'].append(noto_font.filepath)
  if noto_font.is_hinted:
    tables_to_drop = _HINTED_TABLES_TO_DROP
  else:
    tables_to_drop = _UNHINTED_TABLES_TO_DROP
    if autofix_for_release.drop_hints(ttfont):
      _autofix['drop_hints'].append(noto_font.filepath)
  if autofix_for_release.drop_tables(ttfont, tables_to_drop):
    _autofix['drop_tables'].append(noto_font.filepath)
  if noto_font.family == 'Noto':
    if autofix_for_release.fix_linegap(ttfont):
      _autofix['linegap'].append(noto_font.filepath)
  if autofix_for_release.fix_os2_unicoderange(ttfont):
    _autofix['os2_unicoderange'].append(noto_font.filepath)

  if dry_run:
    return

  ttfont['head'].fontRevision = float_revision

  dst_dir = path.dirname(dst_file)
  if not path.isdir(dst_dir):
    os.makedirs(dst_dir)
  ttfont.save(dst_file)
  print 'Wrote file.'
Beispiel #29
0
 def setUp(self):
     _, self.fonts = self.loaded_fonts
     self.condensed_family_name = self.family_name + ' Condensed'
     self.names = []
     for font in self.fonts:
         self.names.append(font_data.get_name_records(font))
Beispiel #30
0
def _swat_font(noto_font, dst_root, dry_run):
    filepath = noto_font.filepath
    basename = path.basename(filepath)
    if noto_font.is_cjk:
        print '# Skipping cjk font %s' % basename
        return
    if noto_font.fmt == 'ttc':
        print '# Deferring ttc font %s' % basename
        _ttc_fonts[noto_font] = ttc_utils.ttcfile_filenames(filepath)
        return

    ttfont = ttLib.TTFont(filepath, fontNumber=0)

    names = font_data.get_name_records(ttfont)

    # create relative root path
    rel_filepath = _noto_relative_path(filepath)
    if not rel_filepath:
        raise ValueError('Could not identify noto root of %s' % filepath)

    print '-----\nUpdating %s' % rel_filepath

    dst_file = path.join(dst_root, rel_filepath)

    version = names[_VERSION_ID]
    m = re.match(r'Version (\d{1,5})\.(\d{1,5})(.*)', version)
    if not m:
        print '! Could not match version string (%s)' % version
        return

    major_version = m.group(1)
    minor_version = m.group(2)
    version_remainder = m.group(3)
    accuracy = len(minor_version)
    print_revision = font_data.printable_font_revision(ttfont, accuracy)
    # sanity check
    expected_revision = major_version + '.' + minor_version
    if expected_revision != print_revision:
        print '! Expected revision \'%s\' but got revision \'%s\'' % (
            expected_revision, print_revision)
        return

    # bump the minor version keeping significant digits:
    new_minor_version = str(int(minor_version) + 1).zfill(accuracy)
    new_revision = major_version + '.' + new_minor_version
    print 'Update revision from  \'%s\' to \'%s\'' % (expected_revision,
                                                      new_revision)
    # double check we are going to properly round-trip this value
    float_revision = float(new_revision)
    fixed_revision = misc.fixedTools.floatToFixed(float_revision, 16)
    rt_float_rev = misc.fixedTools.fixedToFloat(fixed_revision, 16)
    rt_float_rev_int = int(rt_float_rev)
    rt_float_rev_frac = int(
        round((rt_float_rev - rt_float_rev_int) * 10**accuracy))
    rt_new_revision = (str(rt_float_rev_int) + '.' +
                       str(rt_float_rev_frac).zfill(accuracy))
    if new_revision != rt_new_revision:
        print '! Could not update new revision, expected \'%s\' but got \'%s\'' % (
            new_revision, rt_new_revision)
        return

    new_version_string = 'Version ' + new_revision
    if not noto_font.is_hinted:
        new_version_string += ' uh'

    print '%s: %s' % ('Would write' if dry_run else 'Writing', dst_file)

    new_trademark = "%s is a trademark of Google Inc." % noto_font.family

    # description field should be set.
    # Roozbeh has note, make sure design field has information
    # on whether the font is hinted.
    # Missing in Lao and Khmer, default in Cham.
    if (cldr_data.get_english_script_name(noto_font.script)
            in ['Lao', 'Khmer', 'Cham']):
        new_description = 'Data %shinted.' % (''
                                              if noto_font.is_hinted else 'un')
    # elif noto_font.vendor is 'Monotype':
    elif not noto_font.is_cjk and noto_font.family == 'Noto':
        new_description = ('Data %shinted. Designed by Monotype design team.' %
                           ('' if noto_font.is_hinted else 'un'))
    else:
        new_description = None

    if re.match(r'^Copyright 201\d Google Inc. All Rights Reserved\.$',
                names[_COPYRIGHT_ID]):
        new_copyright = None
    else:
        new_copyright = '!!'

    if names.get(_DESIGNER_ID) in [
            'Steve Matteson',
            'Monotype Design Team',
            'Danh Hong',
    ]:
        new_designer = None
    elif names.get(_DESIGNER_ID) == 'Monotype Design team':
        new_designer = 'Monotype Design Team'
    elif (_DESIGNER_ID not in names
          and cldr_data.get_english_script_name(noto_font.script) == 'Khmer'):
        new_designer = 'Danh Hong'
    else:
        new_designer = '!!'

    if names.get(_DESIGNER_URL_ID) in [
            'http://www.monotype.com/studio',
            'http://www.khmertype.org',
    ]:
        new_designer_url = None
    elif names.get(_DESIGNER_URL_ID) in [
            'http://www.monotypeimaging.com/ProductsServices/TypeDesignerShowcase',
    ]:
        new_designer_url = 'http://www.monotype.com/studio'
    elif names.get(_DESIGNER_URL_ID) in [
            'http://www.khmertype.blogspot.com',
            'http://www.khmertype.blogspot.com/',
            'http://khmertype.blogspot.com/',
            'http://wwwkhmertype.blogspot.com.com/',
    ]:
        new_designer_url = 'http://www.khmertype.org'
    else:
        new_designer_url = '!!!'

    if names.get(_MANUFACTURER_ID) in [
            'Monotype Imaging Inc.',
            'Danh Hong',
    ]:
        new_manufacturer = None
    else:
        new_manufacturer = '!!!'

    def update(name_id, new, newText=None):
        old = names.get(name_id)
        if new and (new != old):
            if not dry_run and not '!!!' in new:
                font_data.set_name_record(ttfont,
                                          name_id,
                                          new,
                                          addIfMissing='win')

            label = _NAME_ID_LABELS[name_id]
            oldText = '\'%s\'' % old if old else 'None'
            newText = newText or ('\'%s\'' % new)
            print '%s:\n  old: %s\n  new: %s' % (label, oldText, newText
                                                 or new)

            label_change = _changes.get(label)
            if not label_change:
                label_change = {}
                _changes[label] = label_change
            new_val_change = label_change.get(new)
            if not new_val_change:
                new_val_change = {}
                label_change[new] = new_val_change
            old_val_fonts = new_val_change.get(old)
            if not old_val_fonts:
                old_val_fonts = []
                new_val_change[old] = old_val_fonts
            old_val_fonts.append(noto_font.filepath)

    update(_COPYRIGHT_ID, new_copyright)
    update(_VERSION_ID, new_version_string)
    update(_TRADEMARK_ID, new_trademark)
    update(_MANUFACTURER_ID, new_manufacturer)
    update(_DESIGNER_ID, new_designer)
    update(_DESCRIPTION_ID, new_description)
    update(_VENDOR_URL_ID, _NOTO_URL)
    update(_DESIGNER_URL_ID, new_designer_url)
    update(_LICENSE_ID, _SIL_LICENSE, newText='(OFL)')
    update(_LICENSE_URL_ID, _SIL_LICENSE_URL)

    if autofix_for_release.fix_fstype(ttfont):
        _autofix['fstype'].append(noto_font.filepath)
    if autofix_for_release.fix_vendor_id(ttfont):
        _autofix['vendor_id'].append(noto_font.filepath)
    if autofix_for_release.fix_attachlist(ttfont):
        _autofix['attachlist'].append(noto_font.filepath)
    if noto_font.is_hinted:
        tables_to_drop = _HINTED_TABLES_TO_DROP
    else:
        tables_to_drop = _UNHINTED_TABLES_TO_DROP
        if autofix_for_release.drop_hints(ttfont):
            _autofix['drop_hints'].append(noto_font.filepath)
    if autofix_for_release.drop_tables(ttfont, tables_to_drop):
        _autofix['drop_tables'].append(noto_font.filepath)
    if noto_font.family == 'Noto':
        if autofix_for_release.fix_linegap(ttfont):
            _autofix['linegap'].append(noto_font.filepath)
    if autofix_for_release.fix_os2_unicoderange(ttfont):
        _autofix['os2_unicoderange'].append(noto_font.filepath)

    if dry_run:
        return

    ttfont['head'].fontRevision = float_revision

    dst_dir = path.dirname(dst_file)
    if not path.isdir(dst_dir):
        os.makedirs(dst_dir)
    ttfont.save(dst_file)
    print 'Wrote file.'
Beispiel #31
0
def _swat_font(noto_font, dst_root, dry_run):
    filepath = noto_font.filepath
    basename = path.basename(filepath)
    if noto_font.is_cjk:
        print("# Skipping cjk font %s" % basename)
        return
    if noto_font.fmt == "ttc":
        print("# Deferring ttc font %s" % basename)
        _ttc_fonts[noto_font] = ttc_utils.ttcfile_filenames(filepath)
        return

    ttfont = ttLib.TTFont(filepath, fontNumber=0)

    names = font_data.get_name_records(ttfont)

    # create relative root path
    rel_filepath = _noto_relative_path(filepath)
    if not rel_filepath:
        raise ValueError("Could not identify noto root of %s" % filepath)

    print("-----\nUpdating %s" % rel_filepath)

    dst_file = path.join(dst_root, rel_filepath)

    try:
        new_revision, new_version_string = get_bumped_version(
            ttfont, noto_font.is_hinted)
    except ValueError as e:
        print(e)
        return

    print("%s: %s" % ("Would write" if dry_run else "Writing", dst_file))

    new_trademark = "%s is a trademark of Google Inc." % noto_font.family

    # description field should be set.
    # Roozbeh has note, make sure design field has information
    # on whether the font is hinted.
    # Missing in Lao and Khmer, default in Cham.
    if cldr_data.get_english_script_name(
            noto_font.script) in ["Lao", "Khmer", "Cham"]:
        new_description = "Data %shinted." % (""
                                              if noto_font.is_hinted else "un")
    # elif noto_font.vendor is 'Monotype':
    elif not noto_font.is_cjk and noto_font.family == "Noto":
        new_description = "Data %shinted. Designed by Monotype design team." % (
            "" if noto_font.is_hinted else "un")
    else:
        new_description = None

    if re.match(r"^Copyright 201\d Google Inc. All Rights Reserved\.$",
                names[_COPYRIGHT_ID]):
        new_copyright = None
    else:
        new_copyright = "!!"

    if names.get(_DESIGNER_ID) in [
            "Steve Matteson",
            "Monotype Design Team",
            "Danh Hong",
    ]:
        new_designer = None
    elif names.get(_DESIGNER_ID) == "Monotype Design team":
        new_designer = "Monotype Design Team"
    elif (_DESIGNER_ID not in names
          and cldr_data.get_english_script_name(noto_font.script) == "Khmer"):
        new_designer = "Danh Hong"
    else:
        new_designer = "!!"

    if names.get(_DESIGNER_URL_ID) in [
            "http://www.monotype.com/studio",
            "http://www.khmertype.org",
    ]:
        new_designer_url = None
    elif names.get(_DESIGNER_URL_ID) in [
            "http://www.monotypeimaging.com/ProductsServices/TypeDesignerShowcase",
    ]:
        new_designer_url = "http://www.monotype.com/studio"
    elif names.get(_DESIGNER_URL_ID) in [
            "http://www.khmertype.blogspot.com",
            "http://www.khmertype.blogspot.com/",
            "http://khmertype.blogspot.com/",
            "http://wwwkhmertype.blogspot.com.com/",
    ]:
        new_designer_url = "http://www.khmertype.org"
    else:
        new_designer_url = "!!!"

    if names.get(_MANUFACTURER_ID) in [
            "Monotype Imaging Inc.",
            "Danh Hong",
    ]:
        new_manufacturer = None
    else:
        new_manufacturer = "!!!"

    def update(name_id, new, newText=None):
        old = names.get(name_id)
        if new and (new != old):
            if not dry_run and not "!!!" in new:
                font_data.set_name_record(ttfont,
                                          name_id,
                                          new,
                                          addIfMissing="win")

            label = _NAME_ID_LABELS[name_id]
            oldText = "'%s'" % old if old else "None"
            newText = newText or ("'%s'" % new)
            print("%s:\n  old: %s\n  new: %s" %
                  (label, oldText, newText or new))

            label_change = _changes.get(label)
            if not label_change:
                label_change = {}
                _changes[label] = label_change
            new_val_change = label_change.get(new)
            if not new_val_change:
                new_val_change = {}
                label_change[new] = new_val_change
            old_val_fonts = new_val_change.get(old)
            if not old_val_fonts:
                old_val_fonts = []
                new_val_change[old] = old_val_fonts
            old_val_fonts.append(noto_font.filepath)

    update(_COPYRIGHT_ID, new_copyright)
    update(_VERSION_ID, new_version_string)
    update(_TRADEMARK_ID, new_trademark)
    update(_MANUFACTURER_ID, new_manufacturer)
    update(_DESIGNER_ID, new_designer)
    update(_DESCRIPTION_ID, new_description)
    update(_VENDOR_URL_ID, _NOTO_URL)
    update(_DESIGNER_URL_ID, new_designer_url)
    update(_LICENSE_ID, _SIL_LICENSE, newText="(OFL)")
    update(_LICENSE_URL_ID, _SIL_LICENSE_URL)

    if autofix_for_release.fix_fstype(ttfont):
        _autofix["fstype"].append(noto_font.filepath)
    if autofix_for_release.fix_vendor_id(ttfont):
        _autofix["vendor_id"].append(noto_font.filepath)
    if autofix_for_release.fix_attachlist(ttfont):
        _autofix["attachlist"].append(noto_font.filepath)
    if noto_font.is_hinted:
        tables_to_drop = _HINTED_TABLES_TO_DROP
    else:
        tables_to_drop = _UNHINTED_TABLES_TO_DROP
        if autofix_for_release.drop_hints(ttfont):
            _autofix["drop_hints"].append(noto_font.filepath)
    if autofix_for_release.drop_tables(ttfont, tables_to_drop):
        _autofix["drop_tables"].append(noto_font.filepath)
    if noto_font.family == "Noto":
        if autofix_for_release.fix_linegap(ttfont):
            _autofix["linegap"].append(noto_font.filepath)
    if autofix_for_release.fix_os2_unicoderange(ttfont):
        _autofix["os2_unicoderange"].append(noto_font.filepath)

    if dry_run:
        return

    ttfont["head"].fontRevision = float_revision

    dst_dir = path.dirname(dst_file)
    if not path.isdir(dst_dir):
        os.makedirs(dst_dir)
    ttfont.save(dst_file)
    print("Wrote file.")
Beispiel #32
0
def apply_web_specific_fixes(font, unhinted, family_name):
    """Apply fixes needed for web fonts."""
    # Set OS/2 table values to old values
    os2 = font['OS/2']
    os2.sTypoAscender = 1536
    os2.sTypoDescender = -512
    os2.sTypoLineGap = 102
    os2.usWinAscent = 1946
    os2.usWinDescent = 512

    subfamily_name = font_data.get_name_records(font)[2].encode('ASCII')
    assert (subfamily_name in [
        'Thin', 'Thin Italic', 'Light', 'Light Italic', 'Regular', 'Italic',
        'Medium', 'Medium Italic', 'Bold', 'Bold Italic', 'Black',
        'Black Italic'
    ])

    if 'Condensed' in font_data.get_name_records(font)[1]:
        family_name += ' Condensed'
    full_name = family_name
    if subfamily_name != 'Regular':
        full_name += ' ' + subfamily_name

    # Family, subfamily names
    font_data.set_name_record(font, 16, family_name)
    style_map = ['Regular', 'Bold', 'Italic', 'Bold Italic']
    if subfamily_name in style_map:
        font_data.set_name_record(font, 1, family_name)
    else:
        weight = subfamily_name.split()[0]
        new_family_name = family_name
        if weight != 'Regular':
            new_family_name += ' ' + weight
        font_data.set_name_record(font, 1, new_family_name)

        # all weights outside regular and bold should only have subfamily
        # "Regular" or "Italic"
        italic = subfamily_name.endswith('Italic')
        font_data.set_name_record(font, 2, style_map[italic << 1])

    # Unique identifier and full name
    font_data.set_name_record(font, 3, full_name)
    font_data.set_name_record(font, 4, full_name)
    font_data.set_name_record(font, 18, None)

    # PostScript name
    font_data.set_name_record(font, 6,
                              (family_name + '-' + subfamily_name).replace(
                                  ' ', ''))

    # Copyright message
    font_data.set_name_record(
        font, 0, 'Copyright 2011 Google Inc. All Rights Reserved.')

    # hotpatch glyphs by swapping
    # https://github.com/google/roboto/issues/18
    glyf = font['glyf']
    tmp = glyf['chi']
    glyf['chi'] = glyf['chi.alt']
    glyf['chi.alt'] = tmp

    # make glyph orders consistent for feature copying
    # https://github.com/google/roboto/issues/71
    glyph_order = font.getGlyphOrder()
    for i, glyph_name in enumerate(glyph_order):
        if glyph_name.endswith('.lnum'):
            new_name = glyph_name.replace('.lnum', '.pnum')
            glyph_order[i] = new_name
            font['glyf'][new_name] = font['glyf'][glyph_name]

            # append old name to glyph order so del succeeds
            glyph_order.append(glyph_name)
            del font['glyf'][glyph_name]

    # copy features from unhinted
    # https://github.com/google/roboto/pull/163
    for table in ['GDEF', 'GPOS', 'GSUB']:
        font[table] = unhinted[table]
Beispiel #33
0
def _swat_font(noto_font, dst_root, dry_run):
  filepath = noto_font.filepath
  basename = path.basename(filepath)
  if noto_font.is_cjk:
    print '# Skipping cjk font %s' % basename
    return
  if noto_font.fmt == 'ttc':
    print '# Deferring ttc font %s' % basename
    _ttc_fonts[noto_font] = ttc_utils.ttcfile_filenames(filepath)
    return

  ttfont = ttLib.TTFont(filepath, fontNumber=0)

  names = font_data.get_name_records(ttfont)

  # create relative root path
  rel_filepath = _noto_relative_path(filepath)
  if not rel_filepath:
    raise ValueError('Could not identify noto root of %s' % filepath)

  print '-----\nUpdating %s' % rel_filepath

  dst_file = path.join(dst_root, rel_filepath)

  version = names[_VERSION_ID]
  m = re.match(r'Version (\d{1,5})\.(\d{1,5})(.*)', version)
  if not m:
    print '! Could not match version string (%s)' % version
    return

  major_version = m.group(1)
  minor_version = m.group(2)
  version_remainder = m.group(3)
  accuracy = len(minor_version)
  print_revision = font_data.printable_font_revision(ttfont, accuracy)
  # sanity check
  expected_revision = major_version + '.' + minor_version
  if expected_revision != print_revision:
    print '! Expected revision \'%s\' but got revision \'%s\'' % (
        expected_revision, print_revision)
    return

  # bump the minor version keeping significant digits:
  new_minor_version = str(int(minor_version) + 1).zfill(accuracy)
  new_revision = major_version + '.' + new_minor_version
  print 'Update revision from  \'%s\' to \'%s\'' % (
      expected_revision, new_revision)
  # double check we are going to properly round-trip this value
  float_revision = float(new_revision)
  fixed_revision = misc.fixedTools.floatToFixed(float_revision, 16)
  rt_float_rev = misc.fixedTools.fixedToFloat(fixed_revision, 16)
  rt_float_rev_int = int(rt_float_rev)
  rt_float_rev_frac = int(round((rt_float_rev - rt_float_rev_int) *
                                10 ** accuracy))
  rt_new_revision = (str(rt_float_rev_int) + '.' +
                     str(rt_float_rev_frac).zfill(accuracy))
  if new_revision != rt_new_revision:
    print '! Could not update new revision, expected \'%s\' but got \'%s\'' % (
        new_revision, rt_new_revision)
    return

  new_version_string = 'Version ' + new_revision
  if not noto_font.is_hinted:
    new_version_string += ' uh'

  print '%s: %s' % ('Would write' if dry_run else 'Writing', dst_file)

  new_trademark = "%s is a trademark of Google Inc." % noto_font.family

  # description field should be set.
  # Roozbeh has note, make sure design field has information
  # on whether the font is hinted.
  # Missing in Lao and Khmer, default in Cham.
  if (cldr_data.get_english_script_name(noto_font.script) in
      ['Lao', 'Khmer', 'Cham']):
    new_description =  'Data %shinted.' % ('' if noto_font.is_hinted else 'un')
  # elif noto_font.vendor is 'Monotype':
  elif not noto_font.is_cjk and noto_font.family == 'Noto':
    new_description = (
      'Data %shinted. Designed by Monotype design team.' %
      ('' if noto_font.is_hinted else 'un'))
  else:
    new_description = None

  if re.match(r'^Copyright 201\d Google Inc. All Rights Reserved\.$',
              names[_COPYRIGHT_ID]):
    new_copyright = None
  else:
    new_copyright = '!!'

  if names.get(_DESIGNER_ID) in [
      'Steve Matteson',
      'Monotype Design Team',
      'Danh Hong',
      ]:
    new_designer = None
  elif names.get(_DESIGNER_ID) == 'Monotype Design team':
    new_designer = 'Monotype Design Team'
  elif (_DESIGNER_ID not in names
        and cldr_data.get_english_script_name(noto_font.script) == 'Khmer'):
    new_designer = 'Danh Hong'
  else:
    new_designer = '!!'

  if names.get(_DESIGNER_URL_ID) in [
      'http://www.monotype.com/studio',
      'http://www.khmertype.org',
      ]:
    new_designer_url = None
  elif names.get(_DESIGNER_URL_ID) in [
      'http://www.monotypeimaging.com/ProductsServices/TypeDesignerShowcase',
      ]:
    new_designer_url = 'http://www.monotype.com/studio'
  elif names.get(_DESIGNER_URL_ID) in [
      'http://www.khmertype.blogspot.com',
      'http://www.khmertype.blogspot.com/',
      'http://khmertype.blogspot.com/',
      'http://wwwkhmertype.blogspot.com.com/',
      ]:
    new_designer_url = 'http://www.khmertype.org'
  else:
    new_designer_url = '!!!'

  if names.get(_MANUFACTURER_ID) in [
      'Monotype Imaging Inc.',
      'Danh Hong',
      ]:
    new_manufacturer = None
  else:
    new_manufacturer = '!!!'

  def update(name_id, new, newText=None):
    old = names.get(name_id)
    if new and (new != old):
      if not dry_run and not '!!!' in new:
        font_data.set_name_record(ttfont, name_id, new, addIfMissing='win')

      label = _NAME_ID_LABELS[name_id]
      oldText = '\'%s\'' % old if old else 'None'
      newText = newText or ('\'%s\'' % new)
      print '%s:\n  old: %s\n  new: %s' % (label, oldText, newText or new)

      label_change = _changes.get(label)
      if not label_change:
        label_change = {}
        _changes[label] = label_change
      new_val_change = label_change.get(new)
      if not new_val_change:
        new_val_change = {}
        label_change[new] = new_val_change
      old_val_fonts = new_val_change.get(old)
      if not old_val_fonts:
        old_val_fonts = []
        new_val_change[old] = old_val_fonts
      old_val_fonts.append(noto_font.filepath)

  update(_COPYRIGHT_ID, new_copyright)
  update(_VERSION_ID, new_version_string)
  update(_TRADEMARK_ID, new_trademark)
  update(_MANUFACTURER_ID, new_manufacturer)
  update(_DESIGNER_ID, new_designer)
  update(_DESCRIPTION_ID, new_description)
  update(_VENDOR_URL_ID, _NOTO_URL)
  update(_DESIGNER_URL_ID, new_designer_url)
  update(_LICENSE_ID, _SIL_LICENSE, newText='(OFL)')
  update(_LICENSE_URL_ID, _SIL_LICENSE_URL)

  if autofix_for_release.fix_fstype(ttfont):
    _autofix['fstype'].append(noto_font.filepath)
  if autofix_for_release.fix_vendor_id(ttfont):
    _autofix['vendor_id'].append(noto_font.filepath)
  if autofix_for_release.fix_attachlist(ttfont):
    _autofix['attachlist'].append(noto_font.filepath)
  if noto_font.is_hinted:
    tables_to_drop = _HINTED_TABLES_TO_DROP
  else:
    tables_to_drop = _UNHINTED_TABLES_TO_DROP
    if autofix_for_release.drop_hints(ttfont):
      _autofix['drop_hints'].append(noto_font.filepath)
  if autofix_for_release.drop_tables(ttfont, tables_to_drop):
    _autofix['drop_tables'].append(noto_font.filepath)
  if noto_font.family == 'Noto':
    if autofix_for_release.fix_linegap(ttfont):
      _autofix['linegap'].append(noto_font.filepath)
  if autofix_for_release.fix_os2_unicoderange(ttfont):
    _autofix['os2_unicoderange'].append(noto_font.filepath)

  if dry_run:
    return

  ttfont['head'].fontRevision = float_revision

  dst_dir = path.dirname(dst_file)
  if not path.isdir(dst_dir):
    os.makedirs(dst_dir)
  ttfont.save(dst_file)
  print 'Wrote file.'
Beispiel #34
0
 def setUp(self):
     _, self.fonts = self.loaded_fonts
     self.condensed_family_name = self.family_name + ' Condensed'
     self.names = []
     for font in self.fonts:
         self.names.append(font_data.get_name_records(font))
def fix_font(f, dst_dir, rel_dir, version, version_info, autohint, dry_run):
  print '\n-----\nfont:', f
  font = ttLib.TTFont(f)

  relfont = _get_release_font(f, rel_dir)
  expected_font_revision = get_new_version(font, relfont, version)
  if expected_font_revision != None:
    font_revision = font_data.printable_font_revision(font, 3)
    if font_revision != expected_font_revision:
      _alert('revision', font_revision, expected_font_revision)
      font['head'].fontRevision = float(expected_font_revision)

    names = font_data.get_name_records(font)
    NAME_ID = 5
    font_version = names[NAME_ID]
    expected_version = (
        'Version %s;%s' % (expected_font_revision, version_info))
    if font_version != expected_version:
      _alert('version string', font_version, expected_version)
      font_data.set_name_record(font, NAME_ID, expected_version)

  expected_upem = 1000
  upem = font['head'].unitsPerEm
  if upem != expected_upem:
    print 'expected %d upem but got %d upem' % (expected_upem, upem)

  if _is_ui_metrics(f):
    if upem == 2048:
      expected_ascent = 2163
      expected_descent = -555
    elif upem == 1000:
      expected_ascent = 1069
      expected_descent = -293
    else:
      raise Exception('no expected ui ascent/descent for upem: %d' % upem)

    font_ascent = font['hhea'].ascent
    font_descent = font['hhea'].descent
    if font_ascent != expected_ascent:
      _alert_and_check('ascent', font_ascent, expected_ascent, 2)
      font['hhea'].ascent = expected_ascent
      font['OS/2'].sTypoAscender = expected_ascent
      font['OS/2'].usWinAscent = expected_ascent

    if font_descent != expected_descent:
      _alert_and_check('descent', font_descent, expected_descent, -2)
      font['hhea'].descent = expected_descent
      font['OS/2'].sTypoDescender = expected_descent
      font['OS/2'].usWinDescent = -expected_descent

  tool_utils.ensure_dir_exists(path.join(dst_dir, 'unhinted'))

  fname = path.basename(f)
  udst = path.join(dst_dir, 'unhinted', fname)
  if dry_run:
    print 'dry run would write:\n  "%s"' % udst
  else:
    font.save(udst)
    print 'wrote %s' % udst

  if autohint:
    hdst = path.join(dst_dir, 'hinted', fname)
    autohint_font(udst, hdst, autohint, dry_run)
Beispiel #36
0
def _swat_font(noto_font, dst_root, dry_run):
    filepath = noto_font.filepath
    basename = path.basename(filepath)
    if noto_font.is_cjk:
        print('# Skipping cjk font %s' % basename)
        return
    if noto_font.fmt == 'ttc':
        print('# Deferring ttc font %s' % basename)
        _ttc_fonts[noto_font] = ttc_utils.ttcfile_filenames(filepath)
        return

    ttfont = ttLib.TTFont(filepath, fontNumber=0)

    names = font_data.get_name_records(ttfont)

    # create relative root path
    rel_filepath = _noto_relative_path(filepath)
    if not rel_filepath:
        raise ValueError('Could not identify noto root of %s' % filepath)

    print('-----\nUpdating %s' % rel_filepath)

    dst_file = path.join(dst_root, rel_filepath)

    try:
        new_revision, new_version_string = get_bumped_version(
            ttfont, noto_font.is_hinted)
    except ValueError as e:
        print(e)
        return

    print('%s: %s' % ('Would write' if dry_run else 'Writing', dst_file))

    new_trademark = "%s is a trademark of Google Inc." % noto_font.family

    # description field should be set.
    # Roozbeh has note, make sure design field has information
    # on whether the font is hinted.
    # Missing in Lao and Khmer, default in Cham.
    if (cldr_data.get_english_script_name(noto_font.script)
            in ['Lao', 'Khmer', 'Cham']):
        new_description = 'Data %shinted.' % (''
                                              if noto_font.is_hinted else 'un')
    # elif noto_font.vendor is 'Monotype':
    elif not noto_font.is_cjk and noto_font.family == 'Noto':
        new_description = ('Data %shinted. Designed by Monotype design team.' %
                           ('' if noto_font.is_hinted else 'un'))
    else:
        new_description = None

    if re.match(r'^Copyright 201\d Google Inc. All Rights Reserved\.$',
                names[_COPYRIGHT_ID]):
        new_copyright = None
    else:
        new_copyright = '!!'

    if names.get(_DESIGNER_ID) in [
            'Steve Matteson',
            'Monotype Design Team',
            'Danh Hong',
    ]:
        new_designer = None
    elif names.get(_DESIGNER_ID) == 'Monotype Design team':
        new_designer = 'Monotype Design Team'
    elif (_DESIGNER_ID not in names
          and cldr_data.get_english_script_name(noto_font.script) == 'Khmer'):
        new_designer = 'Danh Hong'
    else:
        new_designer = '!!'

    if names.get(_DESIGNER_URL_ID) in [
            'http://www.monotype.com/studio',
            'http://www.khmertype.org',
    ]:
        new_designer_url = None
    elif names.get(_DESIGNER_URL_ID) in [
            'http://www.monotypeimaging.com/ProductsServices/TypeDesignerShowcase',
    ]:
        new_designer_url = 'http://www.monotype.com/studio'
    elif names.get(_DESIGNER_URL_ID) in [
            'http://www.khmertype.blogspot.com',
            'http://www.khmertype.blogspot.com/',
            'http://khmertype.blogspot.com/',
            'http://wwwkhmertype.blogspot.com.com/',
    ]:
        new_designer_url = 'http://www.khmertype.org'
    else:
        new_designer_url = '!!!'

    if names.get(_MANUFACTURER_ID) in [
            'Monotype Imaging Inc.',
            'Danh Hong',
    ]:
        new_manufacturer = None
    else:
        new_manufacturer = '!!!'

    def update(name_id, new, newText=None):
        old = names.get(name_id)
        if new and (new != old):
            if not dry_run and not '!!!' in new:
                font_data.set_name_record(ttfont,
                                          name_id,
                                          new,
                                          addIfMissing='win')

            label = _NAME_ID_LABELS[name_id]
            oldText = '\'%s\'' % old if old else 'None'
            newText = newText or ('\'%s\'' % new)
            print('%s:\n  old: %s\n  new: %s' %
                  (label, oldText, newText or new))

            label_change = _changes.get(label)
            if not label_change:
                label_change = {}
                _changes[label] = label_change
            new_val_change = label_change.get(new)
            if not new_val_change:
                new_val_change = {}
                label_change[new] = new_val_change
            old_val_fonts = new_val_change.get(old)
            if not old_val_fonts:
                old_val_fonts = []
                new_val_change[old] = old_val_fonts
            old_val_fonts.append(noto_font.filepath)

    update(_COPYRIGHT_ID, new_copyright)
    update(_VERSION_ID, new_version_string)
    update(_TRADEMARK_ID, new_trademark)
    update(_MANUFACTURER_ID, new_manufacturer)
    update(_DESIGNER_ID, new_designer)
    update(_DESCRIPTION_ID, new_description)
    update(_VENDOR_URL_ID, _NOTO_URL)
    update(_DESIGNER_URL_ID, new_designer_url)
    update(_LICENSE_ID, _SIL_LICENSE, newText='(OFL)')
    update(_LICENSE_URL_ID, _SIL_LICENSE_URL)

    if autofix_for_release.fix_fstype(ttfont):
        _autofix['fstype'].append(noto_font.filepath)
    if autofix_for_release.fix_vendor_id(ttfont):
        _autofix['vendor_id'].append(noto_font.filepath)
    if autofix_for_release.fix_attachlist(ttfont):
        _autofix['attachlist'].append(noto_font.filepath)
    if noto_font.is_hinted:
        tables_to_drop = _HINTED_TABLES_TO_DROP
    else:
        tables_to_drop = _UNHINTED_TABLES_TO_DROP
        if autofix_for_release.drop_hints(ttfont):
            _autofix['drop_hints'].append(noto_font.filepath)
    if autofix_for_release.drop_tables(ttfont, tables_to_drop):
        _autofix['drop_tables'].append(noto_font.filepath)
    if noto_font.family == 'Noto':
        if autofix_for_release.fix_linegap(ttfont):
            _autofix['linegap'].append(noto_font.filepath)
    if autofix_for_release.fix_os2_unicoderange(ttfont):
        _autofix['os2_unicoderange'].append(noto_font.filepath)

    if dry_run:
        return

    ttfont['head'].fontRevision = float_revision

    dst_dir = path.dirname(dst_file)
    if not path.isdir(dst_dir):
        os.makedirs(dst_dir)
    ttfont.save(dst_file)
    print('Wrote file.')
def get_font_family_name(font_file):
    font = ttLib.TTFont(font_file)
    name_record = font_data.get_name_records(font)
    return name_record[1]
Beispiel #38
0
def apply_web_cros_common_fixes(font, unhinted, family_name):
    """Apply fixes needed for web and CrOS targets"""
    subfamily_name = font_data.get_name_records(font)[2].encode('ASCII')
    assert(subfamily_name in
        ['Thin', 'Thin Italic',
         'Light', 'Light Italic',
         'Regular', 'Italic',
         'Medium', 'Medium Italic',
         'Bold', 'Bold Italic',
         'Black', 'Black Italic'])

    if 'Condensed' in font_data.get_name_records(font)[1]:
        family_name += ' Condensed'
    full_name = family_name
    if subfamily_name != 'Regular':
        full_name += ' ' + subfamily_name

    # Family, subfamily names
    font_data.set_name_record(font, 16, family_name)
    style_map = ['Regular', 'Bold', 'Italic', 'Bold Italic']
    if subfamily_name in style_map:
        font_data.set_name_record(font, 1, family_name)
    else:
        weight = subfamily_name.split()[0]
        new_family_name = family_name
        if weight != 'Regular':
            new_family_name += ' ' + weight
        font_data.set_name_record(font, 1, new_family_name)

        # all weights outside regular and bold should only have subfamily
        # "Regular" or "Italic"
        italic = subfamily_name.endswith('Italic')
        font_data.set_name_record(font, 2, style_map[italic << 1])

    # Unique identifier and full name
    font_data.set_name_record(font, 3, full_name)
    font_data.set_name_record(font, 4, full_name)
    font_data.set_name_record(font, 18, None)

    # PostScript name
    font_data.set_name_record(
        font, 6, (family_name+'-'+subfamily_name).replace(' ', ''))

    # Copyright message
    font_data.set_name_record(
        font, 0, 'Copyright 2011 Google Inc. All Rights Reserved.')

    # hotpatch glyphs by swapping
    # https://github.com/google/roboto/issues/18
    glyf = font['glyf']
    tmp = glyf['chi']
    glyf['chi'] = glyf['chi.alt']
    glyf['chi.alt'] = tmp

    # make glyph orders consistent for feature copying
    # https://github.com/google/roboto/issues/71
    glyph_order = font.getGlyphOrder()
    for i, glyph_name in enumerate(glyph_order):
        if glyph_name.endswith('.lnum'):
            new_name = glyph_name.replace('.lnum', '.pnum')
            glyph_order[i] = new_name
            font['glyf'][new_name] = font['glyf'][glyph_name]

            # append old name to glyph order so del succeeds
            glyph_order.append(glyph_name)
            del font['glyf'][glyph_name]

    # copy features from unhinted
    # https://github.com/google/roboto/pull/163
    for table in ['GDEF', 'GPOS', 'GSUB']:
        font[table] = unhinted[table]
Beispiel #39
0
def fix_name_table(font):
    """Fix copyright and reversed values in the 'name' table."""
    modified = False
    name_records = font_data.get_name_records(font)

    copyright_data = name_records[0]
    years = re.findall("20[0-9][0-9]", copyright_data)
    year = min(years)
    copyright_data = u"Copyright %s Google Inc. All Rights Reserved." % year

    if copyright_data != name_records[0]:
        print('Updated copyright message to "%s"' % copyright_data)
        font_data.set_name_record(font, 0, copyright_data)
        modified = True

    for name_id in [1, 3, 4, 6]:
        record = name_records[name_id]
        for source in NAME_CORRECTIONS:
            if source in record:
                oldrecord = record
                record = record.replace(source, NAME_CORRECTIONS[source])
                break
        if record != name_records[name_id]:
            font_data.set_name_record(font, name_id, record)
            print(
                'Updated name table record #%d from "%s" to "%s"'
                % (name_id, oldrecord, record)
            )
            modified = True

    trademark_names = ["Noto", "Arimo", "Tinos", "Cousine"]
    trademark_name = None
    font_family = name_records[1]
    for name in trademark_names:
        if font_family.find(name) != -1:
            trademark_name = name
            break
    if not trademark_name:
        print("no trademarked name in '%s'" % font_family)
    else:
        trademark_line = TRADEMARK_TEMPLATE % trademark_name
        if name_records[7] != trademark_line:
            old_line = name_records[7]
            font_data.set_name_record(font, 7, trademark_line)
            modified = True
            print(
                'Updated name table record 7 from "%s" to "%s"'
                % (old_line, trademark_line)
            )

    if name_records[11] != NOTO_URL:
        font_data.set_name_record(font, 11, NOTO_URL)
        modified = True
        print('Updated name table record 11 to "%s"' % NOTO_URL)

    if name_records[_LICENSE_ID] != _SIL_LICENSE:
        font_data.set_name_record(font, _LICENSE_ID, _SIL_LICENSE)
        modified = True
        print("Updated license id")

    if name_records[_LICENSE_URL_ID] != _SIL_LICENSE_URL:
        font_data.set_name_record(font, _LICENSE_URL_ID, _SIL_LICENSE_URL)
        modified = True
        print("Updated license url")

    # TODO: check preferred family/subfamily(16&17)

    return modified