#!/usr/bin/env python3
# Copyright 2013,2016 The Font Bakery Authors.
# Copyright 2017 The Google Fonts Tools Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# See AUTHORS.txt for the list of Authors and LICENSE.txt for the License.
#
"""
Check a hinted font will successfully transfer
  vtt instructions to an unhinted font.
"""
from argparse import (ArgumentParser,
                      RawTextHelpFormatter)
from fontTools.ttLib import TTFont
import logging


def font_glyphs(font):
  '''return a dict of glyphs objects for font

  {'a': <glyf object>, 'b': <glyf object>}'''
  return {g: font['glyf'][g] for g in font['glyf'].glyphs}


def glyphs_points(font):
  '''return a dict of glyphs coordinates/composites for each font

  {'a': [(0,0), (10,10)], 'b': [(10,10, (20,20))]},
  '''
  res = {}
  for glyph in font:
    if hasattr(font[glyph], 'coordinates'):
      res[glyph] = font[glyph].coordinates
    elif font[glyph].isComposite():
      res[glyph] = [c.glyphName for c in font[glyph].components]
    else:
      res[glyph] = None
  return res


def compare_glyph_count(font1, name1, name2):
  if font1:
    logging.warning('%s missing glyphs against %s:\n%s' % (
      name1,
      name2,
      ', '.join(font1)
    ))
  else:
    logging.info('%s %s glyphs match' % (name1, name2))


parser = ArgumentParser(description=__doc__,
                        formatter_class=RawTextHelpFormatter)
parser.add_argument('hinted', help='Hinted font')
parser.add_argument('unhinted', help='Unhinted font')
parser.add_argument('--count', action="store_true", default=True,
                    help="Check fonts have the same glyph count")
parser.add_argument('--compatible', action="store_true", default=True,
                    help="Check glyphs share same coordinates and composites")

logging.getLogger().setLevel(logging.DEBUG)


def main(args=None):
  args = parser.parse_args(args)

  hinted = TTFont(args.hinted)
  unhinted = TTFont(args.unhinted)

  hinted_glyphs = font_glyphs(hinted)
  unhinted_glyphs = font_glyphs(unhinted)

  if args.count:
    logging.debug('Comparing glyph counts:')

    hinted_missing = set(unhinted_glyphs.keys()) - set(hinted_glyphs.keys())
    unhinted_missing = set(hinted_glyphs.keys()) - set(unhinted_glyphs.keys())

    compare_glyph_count(hinted_missing, args.hinted, args.unhinted)
    compare_glyph_count(unhinted_missing, args.unhinted, args.hinted)

  if args.compatible:
    logging.debug('Check glyph structures match')

    hinted_glyph_points = glyphs_points(hinted_glyphs)
    unhinted_glyph_points = glyphs_points(unhinted_glyphs)

    shared_glyphs = set(unhinted_glyphs) & set(hinted_glyphs.keys())

    incompatible_glyphs = []
    for glyph in shared_glyphs:
      if unhinted_glyph_points[glyph] != hinted_glyph_points[glyph]:
        incompatible_glyphs.append(glyph)

    if incompatible_glyphs:
      logging.warning('Incompatible glyphs between %s & %s:\n%s' % (
        args.hinted,
        args.unhinted,
        ', '.join(incompatible_glyphs)
        )
      )
    else:
      logging.info('Glyph sets are compatible')


if __name__ == '__main__':
  main()
