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))
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))
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))
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))
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))
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))
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))
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))