예제 #1
0
    def _check_gdef_marks(self, mark_glyphs):
        self._log("Check gdef marks")

        if not mark_glyphs:
            self._log("No mark glyphs in target")
            return

        target_class_defs = _get_class_defs(self.target)
        test_class_defs = _get_class_defs(self.test)
        assert target_class_defs and test_class_defs

        differences = []
        for cp in mark_glyphs:
            if not cp in self.test_cmap:
                continue
            target_glyph = self.target_cmap[cp]
            test_glyph = self.test_cmap[cp]
            if target_glyph in target_class_defs and test_glyph not in test_class_defs:
                differences.append((cp, -1))
            else:
                target_glyph_class = target_class_defs[target_glyph]
                test_glyph_class = test_class_defs[test_glyph]
                if target_glyph_class == 3 and test_glyph_class != 3:
                    differences.append((cp, test_glyph_class))

        if differences:
            self._err("%d mark glyphs have classDef errors" % len(differences))
            missing_list = []
            incorrect_list = []
            for cp, gc in sorted(differences):
                if gc == -1:
                    self._err(self._cp_error_msg(cp, "has no classDef",
                                                 "does"))
                    missing_list.append(cp)
                else:
                    self._err(
                        self._cp_error_msg(
                            cp,
                            "has non-combining-mark glyph class %d" % gc,
                            "is correct",
                        ))
                    incorrect_list.append(cp)

            if missing_list:
                self._config("enable gdef/classdef/unlisted only cp %s" %
                             lint_config.write_int_ranges(missing_list, True))
            if incorrect_list:
                self._config(
                    "enable gdef/classdef/combining_mismatch only cp %s" %
                    lint_config.write_int_ranges(incorrect_list, True))
예제 #2
0
    def _check_gdef_combining(self):
        self._log('Check gdef combining')

        target_class_defs = _get_class_defs(self.target)
        test_class_defs = _get_class_defs(self.test)
        assert target_class_defs and test_class_defs

        differences = []
        for cp in self.target_chars:
            if not cp in self.test_cmap:
                continue
            target_glyph = self.target_cmap[cp]
            test_glyph = self.test_cmap[cp]
            target_class = target_class_defs.get(target_glyph, -1)
            test_class = test_class_defs.get(test_glyph, -1)
            if target_class != test_class:
                differences.append((cp, test_class, target_class))

        if differences:
            cp_list = []
            self._err('%d glyphs have classDef differences' % len(differences))
            for cp, test_class, target_class in sorted(differences):
                target_msg = 'has class %d' % target_class if target_class != -1 else 'not in classDef'
                test_msg = 'has class %d' % test_class if test_class != -1 else 'not in classDef'
                self._err(self._cp_error_msg(cp, test_msg, target_msg))
                cp_list.append(cp)

            self._config(
                'enable gdef/classdef/not_combining_mismatch only cp %s' %
                lint_config.write_int_ranges(cp_list, True))
예제 #3
0
  def _check_gdef_combining(self):
    self._log('Check gdef combining')

    target_class_defs = _get_class_defs(self.target)
    test_class_defs = _get_class_defs(self.test)
    assert target_class_defs and test_class_defs

    differences = []
    for cp in self.target_chars:
      if not cp in self.test_cmap:
        continue
      target_glyph = self.target_cmap[cp]
      test_glyph = self.test_cmap[cp]
      target_class = target_class_defs.get(target_glyph, -1)
      test_class = test_class_defs.get(test_glyph, -1)
      if target_class != test_class:
        differences.append((cp, test_class, target_class))

    if differences:
      cp_list = []
      self._err('%d glyphs have classDef differences' % len(differences))
      for cp, test_class, target_class in sorted(differences):
        target_msg = 'has class %d' % target_class if target_class != -1 else 'not in classDef'
        test_msg = 'has class %d' % test_class if test_class != -1 else 'not in classDef'
        self._err(self._cp_error_msg(cp, test_msg, target_msg))
        cp_list.append(cp)

      self._config('enable gdef/classdef/not_combining_mismatch only cp %s' %
                   lint_config.write_int_ranges(cp_list, True))
예제 #4
0
  def _check_gdef_marks(self, mark_glyphs):
    self._log('Check gdef marks')

    if not mark_glyphs:
      self._log('No mark glyphs in target')
      return

    target_class_defs = _get_class_defs(self.target)
    test_class_defs = _get_class_defs(self.test)
    assert target_class_defs and test_class_defs

    differences = []
    for cp in mark_glyphs:
      if not cp in self.test_cmap:
        continue
      target_glyph = self.target_cmap[cp]
      test_glyph = self.test_cmap[cp]
      if target_glyph in target_class_defs and test_glyph not in test_class_defs:
        differences.append((cp, -1))
      else:
        target_glyph_class = target_class_defs[target_glyph]
        test_glyph_class = test_class_defs[test_glyph]
        if target_glyph_class == 3 and test_glyph_class != 3:
          differences.append((cp, test_glyph_class))

    if differences:
      self._err('%d mark glyphs have classDef errors' % len(differences))
      missing_list = []
      incorrect_list = []
      for cp, gc in sorted(differences):
        if gc == -1:
          self._err(self._cp_error_msg(cp, 'has no classDef', 'does'))
          missing_list.append(cp)
        else:
          self._err(self._cp_error_msg(
              cp, 'has non-combining-mark glyph class %d' % gc, 'is correct'))
          incorrect_list.append(cp)

      if missing_list:
        self._config('enable gdef/classdef/unlisted only cp %s' %
                     lint_config.write_int_ranges(missing_list, True))
      if incorrect_list:
        self._config('enable gdef/classdef/combining_mismatch only cp %s' %
                     lint_config.write_int_ranges(incorrect_list, True))
예제 #5
0
    def check_cmaps(self):
        if self._skip('cmap'):
            return
        self._log('target cmap size: %d, test cmap size: %d' %
                  (len(self.target_cmap), len(self.test_cmap)))

        missing_chars = self.target_chars - set(self.test_cmap.keys())
        if missing_chars:
            self._logerr('Missing %d chars' % len(missing_chars))
            self._logerr(lint_config.write_int_ranges(missing_chars, True))
예제 #6
0
  def check_cmaps(self):
    if self._skip('cmap'):
      return
    self._log('target cmap size: %d, test cmap size: %d' % (
          len(self.target_cmap), len(self.test_cmap)))

    missing_chars = self.target_chars - set(self.test_cmap.keys())
    if missing_chars:
      self._logerr('Missing %d chars' % len(missing_chars))
      self._logerr(lint_config.write_int_ranges(missing_chars, True))
예제 #7
0
    def check_glyph_bounds(self):
        # Don't compare the actual bounds, but whether they exceed the limits when the target
        # font does not.
        if self._skip('bounds'):
            return

        target_glyf = self.target['glyf']
        test_glyf = self.test['glyf']

        target_max = self.target['OS/2'].usWinAscent
        test_max = self.test['OS/2'].usWinAscent
        target_min = -self.target['OS/2'].usWinDescent
        test_min = -self.test['OS/2'].usWinDescent

        # We need to align the glyph ids, but once we get past the cmap it gets more and more
        # complicated to do this.  For now we'll just check the directly mapped glyphs.
        differences = []
        for cp in self.target_chars:
            if cp not in self.test_cmap:
                continue
            target_glyph_name = self.target_cmap[cp]
            test_glyph_name = self.test_cmap[cp]
            target_glyph = target_glyf[target_glyph_name]
            test_glyph = test_glyf[test_glyph_name]
            target_ymin, target_ymax = render.get_glyph_cleaned_extents(
                target_glyph, target_glyf)
            test_ymin, test_ymax = render.get_glyph_cleaned_extents(
                test_glyph, test_glyf)
            target_exceeds_max = target_ymax > target_max
            target_exceeds_min = target_ymin < target_min
            test_exceeds_max = test_ymax > test_max
            test_exceeds_min = test_ymin < test_min
            max_failure = test_exceeds_max and not target_exceeds_max
            min_failure = test_exceeds_min and not target_exceeds_min
            if max_failure or min_failure:
                differences.append(
                    (cp, max_failure, test_ymax, min_failure, test_ymin))

        if not differences:
            self._config('disable bounds/glyph')
            return

        self._err('%d glyphs have bounds errors' % len(differences))
        self._err('glyph bounds limits max %d, min %d' % (test_max, test_min))

        max_failures = []
        min_failures = []
        for cp, max_failure, ymax, min_failure, ymin in sorted(differences):
            if max_failure:
                self._err(
                    self._cp_error_msg(cp, 'above max (%d)' % ymax, 'is not'))
                if self.emit_config:
                    test_gid = self._test_gid(cp)
                    max_failures.append(test_gid)
            if min_failure:
                self._err(
                    self._cp_error_msg(cp, 'below min (%d)' % ymin, 'is not'))
                if self.emit_config:
                    test_gid = self._test_gid(cp)
                    min_failures.append(test_gid)
        if self.emit_config:
            if max_failures:
                self._config('enable bounds/glyph/ymax only gid %s' %
                             lint_config.write_int_ranges(max_failures, False))
            if min_failures:
                self._config('enable bounds/glyph/ymin only gid %s' %
                             lint_config.write_int_ranges(min_failures, False))
예제 #8
0
  def check_glyph_bounds(self):
    # Don't compare the actual bounds, but whether they exceed the limits when the target
    # font does not.
    if self._skip('bounds'):
      return

    target_glyf = self.target['glyf']
    test_glyf = self.test['glyf']

    target_max = self.target['OS/2'].usWinAscent
    test_max = self.test['OS/2'].usWinAscent
    target_min = -self.target['OS/2'].usWinDescent
    test_min = -self.test['OS/2'].usWinDescent

    # We need to align the glyph ids, but once we get past the cmap it gets more and more
    # complicated to do this.  For now we'll just check the directly mapped glyphs.
    differences = []
    for cp in self.target_chars:
      if cp not in self.test_cmap:
        continue
      target_glyph_name = self.target_cmap[cp]
      test_glyph_name = self.test_cmap[cp]
      target_glyph = target_glyf[target_glyph_name]
      test_glyph = test_glyf[test_glyph_name]
      target_ymin, target_ymax = render.get_glyph_cleaned_extents(target_glyph, target_glyf)
      test_ymin, test_ymax = render.get_glyph_cleaned_extents(test_glyph, test_glyf)
      target_exceeds_max = target_ymax > target_max
      target_exceeds_min = target_ymin < target_min
      test_exceeds_max = test_ymax > test_max
      test_exceeds_min = test_ymin < test_min
      max_failure = test_exceeds_max and not target_exceeds_max
      min_failure = test_exceeds_min and not target_exceeds_min
      if max_failure or min_failure:
        differences.append((cp, max_failure, test_ymax, min_failure, test_ymin))

    if not differences:
      self._config('disable bounds/glyph')
      return

    self._err('%d glyphs have bounds errors' % len(differences))
    self._err('glyph bounds limits max %d, min %d' % (test_max, test_min))

    max_failures = []
    min_failures = []
    for cp, max_failure, ymax, min_failure, ymin in sorted(differences):
      if max_failure:
        self._err(self._cp_error_msg(cp, 'above max (%d)' % ymax, 'is not'))
        if self.emit_config:
          test_gid = self._test_gid(cp)
          max_failures.append(test_gid)
      if min_failure:
        self._err(self._cp_error_msg(cp, 'below min (%d)' % ymin, 'is not'))
        if self.emit_config:
          test_gid = self._test_gid(cp)
          min_failures.append(test_gid)
    if self.emit_config:
      if max_failures:
        self._config('enable bounds/glyph/ymax only gid %s' %
                     lint_config.write_int_ranges(max_failures, False))
      if min_failures:
        self._config('enable bounds/glyph/ymin only gid %s' %
                     lint_config.write_int_ranges(min_failures, False))