Example #1
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)
Example #2
0
    def test_version_numbers(self):
        "Tests the two version numbers of the font to be correct." ""
        for font in self.fonts:
            version = font_data.font_version(font)
            usable_part_of_version = version.split(';')[0]
            self.assertEqual(usable_part_of_version,
                             'Version ' + self.expected_version)

            revision = font_data.printable_font_revision(font, accuracy=3)
            self.assertEqual(revision, self.expected_version)
Example #3
0
    def test_version_numbers(self):
        "Tests the two version numbers of the font to be correct."""
        for font in self.fonts:
            version = font_data.font_version(font)
            usable_part_of_version = version.split(';')[0]
            self.assertEqual(usable_part_of_version,
                             'Version ' + self.expected_version)

            revision = font_data.printable_font_revision(font, accuracy=3)
            self.assertEqual(revision, self.expected_version)
Example #4
0
    def test_version_numbers(self):
        "Tests the two version numbers of the font to be correct."""
        for font in self.fonts:
            build_number = roboto_data.get_build_number()
            expected_version = '2.' + build_number
            version = font_data.font_version(font)
            usable_part_of_version = version.split(';')[0]
            self.assertEqual(usable_part_of_version,
                             'Version ' + expected_version)

            revision = font_data.printable_font_revision(font, accuracy=5)
            self.assertEqual(revision, expected_version)
Example #5
0
    def test_version_numbers(self):
        "Tests the two version numbers of the font to be correct." ""
        for font in self.fonts:
            build_number = roboto_data.get_build_number()
            expected_version = '2.' + build_number
            version = font_data.font_version(font)
            usable_part_of_version = version.split(';')[0]
            self.assertEqual(usable_part_of_version,
                             'Version ' + expected_version)

            revision = font_data.printable_font_revision(font, accuracy=5)
            self.assertEqual(revision, expected_version)
Example #6
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
Example #7
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
Example #8
0
def fix_revision(font):
    """Fix the revision of the font to match its version."""
    version = font_data.font_version(font)
    match = re.match(r'Version (\d{1,5})\.(\d{1,5})', version)
    major_version = match.group(1)
    minor_version = match.group(2)

    accuracy = len(minor_version)
    font_revision = font_data.printable_font_revision(font, accuracy)
    expected_font_revision = major_version + '.' + minor_version
    if font_revision != expected_font_revision:
        font['head'].fontRevision = float(expected_font_revision)
        print 'Fixed fontRevision to %s' % expected_font_revision
        return True

    return False
def fix_revision(font):
    """Fix the revision of the font to match its version."""
    version = font_data.font_version(font)
    match = re.match(r'Version (\d{1,5})\.(\d{1,5})', version)
    major_version = match.group(1)
    minor_version = match.group(2)

    accuracy = len(minor_version)
    font_revision = font_data.printable_font_revision(font, accuracy)
    expected_font_revision = major_version+'.'+minor_version
    if font_revision != expected_font_revision:
        font['head'].fontRevision = float(expected_font_revision)
        print 'Fixed fontRevision to %s' % expected_font_revision
        return True

    return False
Example #10
0
def check_spreadsheet(src_file):
  filenames = set()
  prev_script_name = None
  fontdata = {}
  filedata = {}
  with open(src_file) as csvfile:
    reader = csv.DictReader(csvfile)
    for index, row in enumerate(reader):
      font = row['Fonts'].replace('\xc2\xa0', ' ').strip()
      hinting = row['Hinting'].strip()
      status = row['Status'].strip()
      accepted_version = row['Accepted Version'].strip()
      note = row['Note'].strip()

      # family script style (variant UI) weight, mostly
      m = re.match(
          r'Noto (Kufi|Naskh|Color Emoji|Emoji|Sans|Serif|Nastaliq)'
          r'(?: (.*?))?'
          r'(?: (UI))?'
          r' (Thin|Light|DemiLight|Regular|Medium|Bold Italic'
          r'|Bold|Black|Italic)(?: \(merged\))?$',
          font)
      if not m:
        m = re.match(r'Noto (Sans) (Myanmar) (UI)(.*)', font)
        if not m:
          print 'could not parse Myanmar exception: "%s"' % font
          continue

      style, script, ui, weight = m.groups()

      weight = weight or 'Regular'
      weight = weight.replace(' ', '')
      ui = ui or ''
      script = script or ''
      script = re.sub('-| ', '', script)
      style = style.replace(' ', '')
      ext = 'ttf'
      if script == 'CJK':
        ext = 'ttc'
      elif script.startswith('TTC'):
        ext = 'ttc'
        script = ''
      elif script == '(LGC)':
        script = ''
      elif script == 'UI':
        ui = 'UI'
        script = ''
      elif script == 'Phagspa':
        script = 'PhagsPa'
      elif script == 'SumeroAkkadianCuneiform':
        script = 'Cuneiform'

      fontname = ''.join(['Noto', style, script, ui, '-', weight, '.', ext])
      # print '%s:\n--> %s\n--> %s' % (
      #    font, str((style, script, ui, weight)), fontname)

      if not hinting in [
          'hinted',
          'hinted (CFF)',
          'unhinted']:
        print 'unrecognized hinting value \'%s\' on line %d (%s)' % (
            hinting, index, fontname)
        continue
      hinted = 'hinted' if hinting in ['hinted', 'hinted (CFF)'] else 'unhinted'

      if not status in [
          'In finishing',
          'Released w. lint errors',
          'Approved & Released',
          'Approved & Not Released',
          'In design',
          'Design approved',
          'Design re-approved',
          'Released']:
        print 'unrecognized status value \'%s\' on line %d (%s)' % (
            status, index, fontname)
        continue

      expect_font = status in [
          'Released w. lint errors',
          'Approved & Released',
          'Approved & Not Released',
          'Released']

      data = (fontname, (index, font, style, script, ui, weight), hinted,
              status, accepted_version, note, expect_font)
      filedata[hinted + '/' + fontname] = data

    # ok, now let's see if we can find these files
    all_noto = noto_fonts.get_noto_fonts()
    notodata = {
        ('hinted' if f.is_hinted else 'unhinted') + 
        '/' + path.basename(f.filepath) : f
        for f in all_noto
        }
    noto_filenames = frozenset(notodata.keys())
    spreadsheet_filenames = frozenset(k for k in filedata if filedata[k][6])
    spreadsheet_extra = spreadsheet_filenames - noto_filenames
    spreadsheet_missing = noto_filenames - spreadsheet_filenames
    if spreadsheet_extra:
      print 'spreadsheet extra:\n  ' + '\n  '.join(
          sorted(spreadsheet_extra))
    if spreadsheet_missing:
      print 'spreadsheet missing:\n  ' + '\n  '.join(
          sorted(spreadsheet_missing))

    spreadsheet_match = spreadsheet_filenames & noto_filenames
    for filename in sorted(spreadsheet_match):
      data = filedata[filename]
      filepath = notodata[filename].filepath
      ttfont = ttLib.TTFont(filepath, fontNumber=0)
      font_version = font_data.printable_font_revision(ttfont)
      approved_version = data[4]
      if approved_version:
        warn = '!!!' if approved_version != font_version else ''
        print '%s%s version: %s approved: %s' % (
            warn, filename, font_version, approved_version)
      else:
        print '%s version: %s' % (filename, font_version)
Example #11
0
def check_spreadsheet(src_file):
    filenames = set()
    prev_script_name = None
    fontdata = {}
    filedata = {}
    with open(src_file) as csvfile:
        reader = csv.DictReader(csvfile)
        for index, row in enumerate(reader):
            font = row["Fonts"].replace("\xc2\xa0", " ").strip()
            hinting = row["Hinting"].strip()
            status = row["Status"].strip()
            accepted_version = row["Accepted Version"].strip()
            note = row["Note"].strip()

            # family script style (variant UI) weight, mostly
            m = re.match(
                r"Noto (Kufi|Naskh|Color Emoji|Emoji|Sans|Serif|Nastaliq|Rashi|Traditional)"
                r"(?: (.*?))?"
                r"(?: (UI))?"
                r" (Thin|Light|DemiLight|Regular|Medium|Bold Italic"
                r"|Bold|Black|Italic)(?: \(merged\))?$",
                font,
            )
            if not m:
                m = re.match(r"Noto (Sans) (Myanmar) (UI)(.*)", font)
                if not m:
                    print('could not parse Myanmar exception: "%s"' % font)
                    continue

            style, script, ui, weight = m.groups()

            weight = weight or "Regular"
            weight = weight.replace(" ", "")
            ui = ui or ""
            script = script or ""
            script = re.sub("-| ", "", script)
            style = style.replace(" ", "")
            ext = "ttf"
            if script == "CJK":
                ext = "ttc"
            elif script.startswith("TTC"):
                ext = "ttc"
                script = ""
            elif script == "(LGC)":
                script = ""
            elif script == "UI":
                ui = "UI"
                script = ""
            elif script == "Phagspa":
                script = "PhagsPa"
            elif script == "SumeroAkkadianCuneiform":
                script = "Cuneiform"

            fontname = "".join(["Noto", style, script, ui, "-", weight, ".", ext])
            # print('%s:\n--> %s\n--> %s' % (
            #    font, str((style, script, ui, weight)), fontname))

            if not hinting in ["hinted", "hinted (CFF)", "unhinted"]:
                print(
                    "unrecognized hinting value '%s' on line %d (%s)"
                    % (hinting, index, fontname)
                )
                continue
            hinted = "hinted" if hinting in ["hinted", "hinted (CFF)"] else "unhinted"

            if not status in [
                "In finishing",
                "Released w. lint errors",
                "Approved & Released",
                "Approved & Not Released",
                "In design",
                "Design approved",
                "Design re-approved",
                "Released",
            ]:
                print(
                    "unrecognized status value '%s' on line %d (%s)"
                    % (status, index, fontname)
                )
                continue

            expect_font = status in [
                "Released w. lint errors",
                "Approved & Released",
                "Approved & Not Released",
                "Released",
            ]

            data = (
                fontname,
                (index, font, style, script, ui, weight),
                hinted,
                status,
                accepted_version,
                note,
                expect_font,
            )
            filedata[hinted + "/" + fontname] = data

        # ok, now let's see if we can find these files
        all_noto = noto_fonts.get_noto_fonts()
        notodata = {
            ("hinted" if f.is_hinted else "unhinted")
            + "/"
            + path.basename(f.filepath): f
            for f in all_noto
        }
        noto_filenames = frozenset(notodata.keys())
        spreadsheet_filenames = frozenset(k for k in filedata if filedata[k][6])
        spreadsheet_extra = spreadsheet_filenames - noto_filenames
        spreadsheet_missing = noto_filenames - spreadsheet_filenames
        if spreadsheet_extra:
            print("spreadsheet extra:\n  " + "\n  ".join(sorted(spreadsheet_extra)))
        if spreadsheet_missing:
            print("spreadsheet missing:\n  " + "\n  ".join(sorted(spreadsheet_missing)))

        spreadsheet_match = spreadsheet_filenames & noto_filenames
        for filename in sorted(spreadsheet_match):
            data = filedata[filename]
            filepath = notodata[filename].filepath
            ttfont = ttLib.TTFont(filepath, fontNumber=0)
            font_version = font_data.printable_font_revision(ttfont)
            approved_version = data[4]
            if approved_version:
                warn = "!!!" if approved_version != font_version else ""
                print(
                    "%s%s version: %s approved: %s"
                    % (warn, filename, font_version, approved_version)
                )
            else:
                print("%s version: %s" % (filename, font_version))
Example #12
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.'
Example #13
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.'
Example #14
0
def check_spreadsheet(src_file):
    filenames = set()
    prev_script_name = None
    fontdata = {}
    filedata = {}
    with open(src_file) as csvfile:
        reader = csv.DictReader(csvfile)
        for index, row in enumerate(reader):
            font = row['Fonts'].replace('\xc2\xa0', ' ').strip()
            hinting = row['Hinting'].strip()
            status = row['Status'].strip()
            accepted_version = row['Accepted Version'].strip()
            note = row['Note'].strip()

            # family script style (variant UI) weight, mostly
            m = re.match(
                r'Noto (Kufi|Naskh|Color Emoji|Emoji|Sans|Serif|Nastaliq)'
                r'(?: (.*?))?'
                r'(?: (UI))?'
                r' (Thin|Light|DemiLight|Regular|Medium|Bold Italic'
                r'|Bold|Black|Italic)(?: \(merged\))?$', font)
            if not m:
                m = re.match(r'Noto (Sans) (Myanmar) (UI)(.*)', font)
                if not m:
                    print 'could not parse Myanmar exception: "%s"' % font
                    continue

            style, script, ui, weight = m.groups()

            weight = weight or 'Regular'
            weight = weight.replace(' ', '')
            ui = ui or ''
            script = script or ''
            script = re.sub('-| ', '', script)
            style = style.replace(' ', '')
            ext = 'ttf'
            if script == 'CJK':
                ext = 'ttc'
            elif script.startswith('TTC'):
                ext = 'ttc'
                script = ''
            elif script == '(LGC)':
                script = ''
            elif script == 'UI':
                ui = 'UI'
                script = ''
            elif script == 'Phagspa':
                script = 'PhagsPa'
            elif script == 'SumeroAkkadianCuneiform':
                script = 'Cuneiform'

            fontname = ''.join(
                ['Noto', style, script, ui, '-', weight, '.', ext])
            # print '%s:\n--> %s\n--> %s' % (
            #    font, str((style, script, ui, weight)), fontname)

            if not hinting in ['hinted', 'hinted (CFF)', 'unhinted']:
                print 'unrecognized hinting value \'%s\' on line %d (%s)' % (
                    hinting, index, fontname)
                continue
            hinted = 'hinted' if hinting in ['hinted', 'hinted (CFF)'
                                             ] else 'unhinted'

            if not status in [
                    'In finishing', 'Released w. lint errors',
                    'Approved & Released', 'Approved & Not Released',
                    'In design', 'Design approved', 'Design re-approved',
                    'Released'
            ]:
                print 'unrecognized status value \'%s\' on line %d (%s)' % (
                    status, index, fontname)
                continue

            expect_font = status in [
                'Released w. lint errors', 'Approved & Released',
                'Approved & Not Released', 'Released'
            ]

            data = (fontname, (index, font, style, script, ui, weight), hinted,
                    status, accepted_version, note, expect_font)
            filedata[hinted + '/' + fontname] = data

        # ok, now let's see if we can find these files
        all_noto = noto_fonts.get_noto_fonts()
        notodata = {('hinted' if f.is_hinted else 'unhinted') + '/' +
                    path.basename(f.filepath): f
                    for f in all_noto}
        noto_filenames = frozenset(notodata.keys())
        spreadsheet_filenames = frozenset(k for k in filedata
                                          if filedata[k][6])
        spreadsheet_extra = spreadsheet_filenames - noto_filenames
        spreadsheet_missing = noto_filenames - spreadsheet_filenames
        if spreadsheet_extra:
            print 'spreadsheet extra:\n  ' + '\n  '.join(
                sorted(spreadsheet_extra))
        if spreadsheet_missing:
            print 'spreadsheet missing:\n  ' + '\n  '.join(
                sorted(spreadsheet_missing))

        spreadsheet_match = spreadsheet_filenames & noto_filenames
        for filename in sorted(spreadsheet_match):
            data = filedata[filename]
            filepath = notodata[filename].filepath
            ttfont = ttLib.TTFont(filepath, fontNumber=0)
            font_version = font_data.printable_font_revision(ttfont)
            approved_version = data[4]
            if approved_version:
                warn = '!!!' if approved_version != font_version else ''
                print '%s%s version: %s approved: %s' % (
                    warn, filename, font_version, approved_version)
            else:
                print '%s version: %s' % (filename, font_version)
Example #15
0
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)