"""
Merge OpenType Layout tables (GDEF / GPOS / GSUB).
"""
from __future__ import print_function, division, absolute_import
import copy
from operator import ior
from fontTools.misc.py23 import *
from fontTools.misc.fixedTools import otRound
from fontTools.misc import classifyTools
from fontTools.ttLib.tables import otTables as ot
from fontTools.ttLib.tables import otBase as otBase
from fontTools.ttLib.tables.DefaultTable import DefaultTable
from fontTools.varLib import builder, models, varStore
from fontTools.varLib.models import nonNone, allNone, allEqual, allEqualTo
from fontTools.varLib.varStore import VarStoreInstancer
from functools import reduce
from fontTools.otlLib.builder import buildSinglePos


class Merger(object):

	def __init__(self, font=None):
		self.font = font

	@classmethod
	def merger(celf, clazzes, attrs=(None,)):
		assert celf != Merger, 'Subclass Merger instead.'
		if 'mergers' not in celf.__dict__:
			celf.mergers = {}
		if type(clazzes) == type:
			clazzes = (clazzes,)
		if type(attrs) == str:
			attrs = (attrs,)
		def wrapper(method):
			assert method.__name__ == 'merge'
			done = []
			for clazz in clazzes:
				if clazz in done: continue # Support multiple names of a clazz
				done.append(clazz)
				mergers = celf.mergers.setdefault(clazz, {})
				for attr in attrs:
					assert attr not in mergers, \
						"Oops, class '%s' has merge function for '%s' defined already." % (clazz.__name__, attr)
					mergers[attr] = method
			return None
		return wrapper

	@classmethod
	def mergersFor(celf, thing, _default={}):
		typ = type(thing)

		for celf in celf.mro():

			mergers = getattr(celf, 'mergers', None)
			if mergers is None:
				break;

			m = celf.mergers.get(typ, None)
			if m is not None:
				return m

		return _default

	def mergeObjects(self, out, lst, exclude=()):
		keys = sorted(vars(out).keys())
		assert all(keys == sorted(vars(v).keys()) for v in lst), \
			(keys, [sorted(vars(v).keys()) for v in lst])
		mergers = self.mergersFor(out)
		defaultMerger = mergers.get('*', self.__class__.mergeThings)
		try:
			for key in keys:
				if key in exclude: continue
				value = getattr(out, key)
				values = [getattr(table, key) for table in lst]
				mergerFunc = mergers.get(key, defaultMerger)
				mergerFunc(self, value, values)
		except Exception as e:
			e.args = e.args + ('.'+key,)
			raise

	def mergeLists(self, out, lst):
		assert allEqualTo(out, lst, len), (len(out), [len(v) for v in lst])
		for i,(value,values) in enumerate(zip(out, zip(*lst))):
			try:
				self.mergeThings(value, values)
			except Exception as e:
				e.args = e.args + ('[%d]' % i,)
				raise

	def mergeThings(self, out, lst):
		try:
			assert allEqualTo(out, lst, type), (out, lst)
			mergerFunc = self.mergersFor(out).get(None, None)
			if mergerFunc is not None:
				mergerFunc(self, out, lst)
			elif hasattr(out, '__dict__'):
				self.mergeObjects(out, lst)
			elif isinstance(out, list):
				self.mergeLists(out, lst)
			else:
				assert allEqualTo(out, lst), (out, lst)
		except Exception as e:
			e.args = e.args + (type(out).__name__,)
			raise

	def mergeTables(self, font, master_ttfs, tableTags):

		for tag in tableTags:
			if tag not in font: continue
			self.mergeThings(font[tag], [m[tag] if tag in m else None
						     for m in master_ttfs])

#
# Aligning merger
#
class AligningMerger(Merger):
	pass

@AligningMerger.merger(ot.GDEF, "GlyphClassDef")
def merge(merger, self, lst):
	if self is None:
		assert allNone(lst), (lst)
		return

	lst = [l.classDefs for l in lst]
	self.classDefs = {}
	# We only care about the .classDefs
	self = self.classDefs

	allKeys = set()
	allKeys.update(*[l.keys() for l in lst])
	for k in allKeys:
		allValues = nonNone(l.get(k) for l in lst)
		assert allEqual(allValues), allValues
		if not allValues:
			self[k] = None
		else:
			self[k] = allValues[0]

def _SinglePosUpgradeToFormat2(self):
	if self.Format == 2: return self

	ret = ot.SinglePos()
	ret.Format = 2
	ret.Coverage = self.Coverage
	ret.ValueFormat = self.ValueFormat
	ret.Value = [self.Value for g in ret.Coverage.glyphs]
	ret.ValueCount = len(ret.Value)

	return ret

def _merge_GlyphOrders(font, lst, values_lst=None, default=None):
	"""Takes font and list of glyph lists (must be sorted by glyph id), and returns
	two things:
	- Combined glyph list,
	- If values_lst is None, return input glyph lists, but padded with None when a glyph
	  was missing in a list.  Otherwise, return values_lst list-of-list, padded with None
	  to match combined glyph lists.
	"""
	if values_lst is None:
		dict_sets = [set(l) for l in lst]
	else:
		dict_sets = [{g:v for g,v in zip(l,vs)} for l,vs in zip(lst,values_lst)]
	combined = set()
	combined.update(*dict_sets)

	sortKey = font.getReverseGlyphMap().__getitem__
	order = sorted(combined, key=sortKey)
	# Make sure all input glyphsets were in proper order
	assert all(sorted(vs, key=sortKey) == vs for vs in lst)
	del combined

	paddedValues = None
	if values_lst is None:
		padded = [[glyph if glyph in dict_set else default
			   for glyph in order]
			  for dict_set in dict_sets]
	else:
		assert len(lst) == len(values_lst)
		padded = [[dict_set[glyph] if glyph in dict_set else default
			   for glyph in order]
			  for dict_set in dict_sets]
	return order, padded

def _Lookup_SinglePos_get_effective_value(subtables, glyph):
	for self in subtables:
		if self is None or \
		   type(self) != ot.SinglePos or \
		   self.Coverage is None or \
		   glyph not in self.Coverage.glyphs:
			continue
		if self.Format == 1:
			return self.Value
		elif self.Format == 2:
			return self.Value[self.Coverage.glyphs.index(glyph)]
		else:
			assert 0
	return None

def _Lookup_PairPos_get_effective_value_pair(subtables, firstGlyph, secondGlyph):
	for self in subtables:
		if self is None or \
		   type(self) != ot.PairPos or \
		   self.Coverage is None or \
		   firstGlyph not in self.Coverage.glyphs:
			continue
		if self.Format == 1:
			ps = self.PairSet[self.Coverage.glyphs.index(firstGlyph)]
			pvr = ps.PairValueRecord
			for rec in pvr: # TODO Speed up
				if rec.SecondGlyph == secondGlyph:
					return rec
			continue
		elif self.Format == 2:
			klass1 = self.ClassDef1.classDefs.get(firstGlyph, 0)
			klass2 = self.ClassDef2.classDefs.get(secondGlyph, 0)
			return self.Class1Record[klass1].Class2Record[klass2]
		else:
			assert 0
	return None

@AligningMerger.merger(ot.SinglePos)
def merge(merger, self, lst):
	self.ValueFormat = valueFormat = reduce(int.__or__, [l.ValueFormat for l in lst], 0)
	assert len(lst) == 1 or (valueFormat & ~0xF == 0), valueFormat

	# If all have same coverage table and all are format 1,
	coverageGlyphs = self.Coverage.glyphs
	if all(v.Format == 1 for v in lst) and all(coverageGlyphs == v.Coverage.glyphs for v in lst):
		self.Value = otBase.ValueRecord(valueFormat)
		merger.mergeThings(self.Value, [v.Value for v in lst])
		self.ValueFormat = self.Value.getFormat()
		return

	# Upgrade everything to Format=2
	self.Format = 2
	lst = [_SinglePosUpgradeToFormat2(v) for v in lst]

	# Align them
	glyphs, padded = _merge_GlyphOrders(merger.font,
					    [v.Coverage.glyphs for v in lst],
					    [v.Value for v in lst])

	self.Coverage.glyphs = glyphs
	self.Value = [otBase.ValueRecord(valueFormat) for g in glyphs]
	self.ValueCount = len(self.Value)

	for i,values in enumerate(padded):
		for j,glyph in enumerate(glyphs):
			if values[j] is not None: continue
			# Fill in value from other subtables
			# Note!!! This *might* result in behavior change if ValueFormat2-zeroedness
			# is different between used subtable and current subtable!
			# TODO(behdad) Check and warn if that happens?
			v = _Lookup_SinglePos_get_effective_value(merger.lookup_subtables[i], glyph)
			if v is None:
				v = otBase.ValueRecord(valueFormat)
			values[j] = v

	merger.mergeLists(self.Value, padded)

	# Merge everything else; though, there shouldn't be anything else. :)
	merger.mergeObjects(self, lst,
			    exclude=('Format', 'Coverage', 'Value', 'ValueCount'))
	self.ValueFormat = reduce(int.__or__, [v.getFormat() for v in self.Value], 0)

@AligningMerger.merger(ot.PairSet)
def merge(merger, self, lst):
	# Align them
	glyphs, padded = _merge_GlyphOrders(merger.font,
				[[v.SecondGlyph for v in vs.PairValueRecord] for vs in lst],
				[vs.PairValueRecord for vs in lst])

	self.PairValueRecord = pvrs = []
	for glyph in glyphs:
		pvr = ot.PairValueRecord()
		pvr.SecondGlyph = glyph
		pvr.Value1 = otBase.ValueRecord(merger.valueFormat1) if merger.valueFormat1 else None
		pvr.Value2 = otBase.ValueRecord(merger.valueFormat2) if merger.valueFormat2 else None
		pvrs.append(pvr)
	self.PairValueCount = len(self.PairValueRecord)

	for i,values in enumerate(padded):
		for j,glyph in enumerate(glyphs):
			# Fill in value from other subtables
			v = ot.PairValueRecord()
			v.SecondGlyph = glyph
			if values[j] is not None:
				vpair = values[j]
			else:
				vpair = _Lookup_PairPos_get_effective_value_pair(merger.lookup_subtables[i], self._firstGlyph, glyph)
			if vpair is None:
				v1, v2 = None, None
			else:
				v1, v2 = vpair.Value1, vpair.Value2
			v.Value1 = otBase.ValueRecord(merger.valueFormat1, src=v1) if merger.valueFormat1 else None
			v.Value2 = otBase.ValueRecord(merger.valueFormat2, src=v2) if merger.valueFormat2 else None
			values[j] = v
	del self._firstGlyph

	merger.mergeLists(self.PairValueRecord, padded)

def _PairPosFormat1_merge(self, lst, merger):
	assert allEqual([l.ValueFormat2 == 0 for l in lst if l.PairSet]), "Report bug against fonttools."

	# Merge everything else; makes sure Format is the same.
	merger.mergeObjects(self, lst,
			    exclude=('Coverage',
				     'PairSet', 'PairSetCount',
				     'ValueFormat1', 'ValueFormat2'))

	empty = ot.PairSet()
	empty.PairValueRecord = []
	empty.PairValueCount = 0

	# Align them
	glyphs, padded = _merge_GlyphOrders(merger.font,
					    [v.Coverage.glyphs for v in lst],
					    [v.PairSet for v in lst],
					    default=empty)

	self.Coverage.glyphs = glyphs
	self.PairSet = [ot.PairSet() for g in glyphs]
	self.PairSetCount = len(self.PairSet)
	for glyph, ps in zip(glyphs, self.PairSet):
		ps._firstGlyph = glyph

	merger.mergeLists(self.PairSet, padded)

def _ClassDef_invert(self, allGlyphs=None):

	if isinstance(self, dict):
		classDefs = self
	else:
		classDefs = self.classDefs if self and self.classDefs else {}
	m = max(classDefs.values()) if classDefs else 0

	ret = []
	for _ in range(m + 1):
		ret.append(set())

	for k,v in classDefs.items():
		ret[v].add(k)

	# Class-0 is special.  It's "everything else".
	if allGlyphs is None:
		ret[0] = None
	else:
		# Limit all classes to glyphs in allGlyphs.
		# Collect anything without a non-zero class into class=zero.
		ret[0] = class0 = set(allGlyphs)
		for s in ret[1:]:
			s.intersection_update(class0)
			class0.difference_update(s)

	return ret

def _ClassDef_merge_classify(lst, allGlyphses=None):
	self = ot.ClassDef()
	self.classDefs = classDefs = {}
	allGlyphsesWasNone = allGlyphses is None
	if allGlyphsesWasNone:
		allGlyphses = [None] * len(lst)

	classifier = classifyTools.Classifier()
	for classDef,allGlyphs in zip(lst, allGlyphses):
		sets = _ClassDef_invert(classDef, allGlyphs)
		if allGlyphs is None:
			sets = sets[1:]
		classifier.update(sets)
	classes = classifier.getClasses()

	if allGlyphsesWasNone:
		classes.insert(0, set())

	for i,classSet in enumerate(classes):
		if i == 0:
			continue
		for g in classSet:
			classDefs[g] = i

	return self, classes

# It's stupid that we need to do this here.  Just need to, to match test
# expecatation results, since ttx prints out format of ClassDef (and Coverage)
# even though it should not.
def _ClassDef_calculate_Format(self, font):
	fmt = 2
	ranges = self._getClassRanges(font)
	if ranges:
		startGlyph = ranges[0][1]
		endGlyph = ranges[-1][3]
		glyphCount = endGlyph - startGlyph + 1
		if len(ranges) * 3 >= glyphCount + 1:
			# Format 1 is more compact
			fmt = 1
	self.Format = fmt

def _PairPosFormat2_align_matrices(self, lst, font, transparent=False):

	matrices = [l.Class1Record for l in lst]

	# Align first classes
	self.ClassDef1, classes = _ClassDef_merge_classify([l.ClassDef1 for l in lst], [l.Coverage.glyphs for l in lst])
	_ClassDef_calculate_Format(self.ClassDef1, font)
	self.Class1Count = len(classes)
	new_matrices = []
	for l,matrix in zip(lst, matrices):
		nullRow = None
		coverage = set(l.Coverage.glyphs)
		classDef1 = l.ClassDef1.classDefs
		class1Records = []
		for classSet in classes:
			exemplarGlyph = next(iter(classSet))
			if exemplarGlyph not in coverage:
				# Follow-up to e6125b353e1f54a0280ded5434b8e40d042de69f,
				# Fixes https://github.com/googlei18n/fontmake/issues/470
				# Again, revert 8d441779e5afc664960d848f62c7acdbfc71d7b9
				# when merger becomes selfless.
				nullRow = None
				if nullRow is None:
					nullRow = ot.Class1Record()
					class2records = nullRow.Class2Record = []
					# TODO: When merger becomes selfless, revert e6125b353e1f54a0280ded5434b8e40d042de69f
					for _ in range(l.Class2Count):
						if transparent:
							rec2 = None
						else:
							rec2 = ot.Class2Record()
							rec2.Value1 = otBase.ValueRecord(self.ValueFormat1) if self.ValueFormat1 else None
							rec2.Value2 = otBase.ValueRecord(self.ValueFormat2) if self.ValueFormat2 else None
						class2records.append(rec2)
				rec1 = nullRow
			else:
				klass = classDef1.get(exemplarGlyph, 0)
				rec1 = matrix[klass] # TODO handle out-of-range?
			class1Records.append(rec1)
		new_matrices.append(class1Records)
	matrices = new_matrices
	del new_matrices

	# Align second classes
	self.ClassDef2, classes = _ClassDef_merge_classify([l.ClassDef2 for l in lst])
	_ClassDef_calculate_Format(self.ClassDef2, font)
	self.Class2Count = len(classes)
	new_matrices = []
	for l,matrix in zip(lst, matrices):
		classDef2 = l.ClassDef2.classDefs
		class1Records = []
		for rec1old in matrix:
			oldClass2Records = rec1old.Class2Record
			rec1new = ot.Class1Record()
			class2Records = rec1new.Class2Record = []
			for classSet in classes:
				if not classSet: # class=0
					rec2 = oldClass2Records[0]
				else:
					exemplarGlyph = next(iter(classSet))
					klass = classDef2.get(exemplarGlyph, 0)
					rec2 = oldClass2Records[klass]
				class2Records.append(copy.deepcopy(rec2))
			class1Records.append(rec1new)
		new_matrices.append(class1Records)
	matrices = new_matrices
	del new_matrices

	return matrices

def _PairPosFormat2_merge(self, lst, merger):
	assert allEqual([l.ValueFormat2 == 0 for l in lst if l.Class1Record]), "Report bug against fonttools."

	merger.mergeObjects(self, lst,
			    exclude=('Coverage',
				     'ClassDef1', 'Class1Count',
				     'ClassDef2', 'Class2Count',
				     'Class1Record',
				     'ValueFormat1', 'ValueFormat2'))

	# Align coverages
	glyphs, _ = _merge_GlyphOrders(merger.font,
				       [v.Coverage.glyphs for v in lst])
	self.Coverage.glyphs = glyphs

	# Currently, if the coverage of PairPosFormat2 subtables are different,
	# we do NOT bother walking down the subtable list when filling in new
	# rows for alignment.  As such, this is only correct if current subtable
	# is the last subtable in the lookup.  Ensure that.
	#
	# Note that our canonicalization process merges trailing PairPosFormat2's,
	# so in reality this is rare.
	for l,subtables in zip(lst,merger.lookup_subtables):
		if l.Coverage.glyphs != glyphs:
			assert l == subtables[-1]

	matrices = _PairPosFormat2_align_matrices(self, lst, merger.font)

	self.Class1Record = list(matrices[0]) # TODO move merger to be selfless
	merger.mergeLists(self.Class1Record, matrices)

@AligningMerger.merger(ot.PairPos)
def merge(merger, self, lst):
	merger.valueFormat1 = self.ValueFormat1 = reduce(int.__or__, [l.ValueFormat1 for l in lst], 0)
	merger.valueFormat2 = self.ValueFormat2 = reduce(int.__or__, [l.ValueFormat2 for l in lst], 0)

	if self.Format == 1:
		_PairPosFormat1_merge(self, lst, merger)
	elif self.Format == 2:
		_PairPosFormat2_merge(self, lst, merger)
	else:
		assert False

	del merger.valueFormat1, merger.valueFormat2

	# Now examine the list of value records, and update to the union of format values,
	# as merge might have created new values.
	vf1 = 0
	vf2 = 0
	if self.Format == 1:
		for pairSet in self.PairSet:
			for pairValueRecord in pairSet.PairValueRecord:
				pv1 = pairValueRecord.Value1
				if pv1 is not None:
					vf1 |= pv1.getFormat()
				pv2 = pairValueRecord.Value2
				if pv2 is not None:
					vf2 |= pv2.getFormat()
	elif self.Format == 2:
		for class1Record in self.Class1Record:
			for class2Record in class1Record.Class2Record:
				pv1 = class2Record.Value1
				if pv1 is not None:
					vf1 |= pv1.getFormat()
				pv2 = class2Record.Value2
				if pv2 is not None:
					vf2 |= pv2.getFormat()
	self.ValueFormat1 = vf1
	self.ValueFormat2 = vf2

def _MarkBasePosFormat1_merge(self, lst, merger, Mark='Mark', Base='Base'):
	self.ClassCount = max(l.ClassCount for l in lst)

	MarkCoverageGlyphs, MarkRecords = \
		_merge_GlyphOrders(merger.font,
				   [getattr(l, Mark+'Coverage').glyphs for l in lst],
				   [getattr(l, Mark+'Array').MarkRecord for l in lst])
	getattr(self, Mark+'Coverage').glyphs = MarkCoverageGlyphs

	BaseCoverageGlyphs, BaseRecords = \
		_merge_GlyphOrders(merger.font,
				   [getattr(l, Base+'Coverage').glyphs for l in lst],
				   [getattr(getattr(l, Base+'Array'), Base+'Record') for l in lst])
	getattr(self, Base+'Coverage').glyphs = BaseCoverageGlyphs

	# MarkArray
	records = []
	for g,glyphRecords in zip(MarkCoverageGlyphs, zip(*MarkRecords)):
		allClasses = [r.Class for r in glyphRecords if r is not None]

		# TODO Right now we require that all marks have same class in
		# all masters that cover them.  This is not required.
		#
		# We can relax that by just requiring that all marks that have
		# the same class in a master, have the same class in every other
		# master.  Indeed, if, say, a sparse master only covers one mark,
		# that mark probably will get class 0, which would possibly be
		# different from its class in other masters.
		#
		# We can even go further and reclassify marks to support any
		# input.  But, since, it's unlikely that two marks being both,
		# say, "top" in one master, and one being "top" and other being
		# "top-right" in another master, we shouldn't do that, as any
		# failures in that case will probably signify mistakes in the
		# input masters.

		assert allEqual(allClasses), allClasses
		if not allClasses:
			rec = None
		else:
			rec = ot.MarkRecord()
			rec.Class = allClasses[0]
			allAnchors = [None if r is None else r.MarkAnchor for r in glyphRecords]
			if allNone(allAnchors):
				anchor = None
			else:
				anchor = ot.Anchor()
				anchor.Format = 1
				merger.mergeThings(anchor, allAnchors)
			rec.MarkAnchor = anchor
		records.append(rec)
	array = ot.MarkArray()
	array.MarkRecord = records
	array.MarkCount = len(records)
	setattr(self, Mark+"Array", array)

	# BaseArray
	records = []
	for g,glyphRecords in zip(BaseCoverageGlyphs, zip(*BaseRecords)):
		if allNone(glyphRecords):
			rec = None
		else:
			rec = getattr(ot, Base+'Record')()
			anchors = []
			setattr(rec, Base+'Anchor', anchors)
			glyphAnchors = [[] if r is None else getattr(r, Base+'Anchor')
					for r in glyphRecords]
			for l in glyphAnchors:
				l.extend([None] * (self.ClassCount - len(l)))
			for allAnchors in zip(*glyphAnchors):
				if allNone(allAnchors):
					anchor = None
				else:
					anchor = ot.Anchor()
					anchor.Format = 1
					merger.mergeThings(anchor, allAnchors)
				anchors.append(anchor)
		records.append(rec)
	array = getattr(ot, Base+'Array')()
	setattr(array, Base+'Record', records)
	setattr(array, Base+'Count', len(records))
	setattr(self, Base+'Array', array)

@AligningMerger.merger(ot.MarkBasePos)
def merge(merger, self, lst):
	assert allEqualTo(self.Format, (l.Format for l in lst))
	if self.Format == 1:
		_MarkBasePosFormat1_merge(self, lst, merger)
	else:
		assert False

@AligningMerger.merger(ot.MarkMarkPos)
def merge(merger, self, lst):
	assert allEqualTo(self.Format, (l.Format for l in lst))
	if self.Format == 1:
		_MarkBasePosFormat1_merge(self, lst, merger, 'Mark1', 'Mark2')
	else:
		assert False


def _PairSet_flatten(lst, font):
	self = ot.PairSet()
	self.Coverage = ot.Coverage()
	self.Coverage.Format = 1

	# Align them
	glyphs, padded = _merge_GlyphOrders(font,
				[[v.SecondGlyph for v in vs.PairValueRecord] for vs in lst],
				[vs.PairValueRecord for vs in lst])

	self.Coverage.glyphs = glyphs
	self.PairValueRecord = pvrs = []
	for values in zip(*padded):
		for v in values:
			if v is not None:
				pvrs.append(v)
				break
		else:
			assert False
	self.PairValueCount = len(self.PairValueRecord)

	return self

def _Lookup_PairPosFormat1_subtables_flatten(lst, font):
	assert allEqual([l.ValueFormat2 == 0 for l in lst if l.PairSet]), "Report bug against fonttools."

	self = ot.PairPos()
	self.Format = 1
	self.Coverage = ot.Coverage()
	self.Coverage.Format = 1
	self.ValueFormat1 = reduce(int.__or__, [l.ValueFormat1 for l in lst], 0)
	self.ValueFormat2 = reduce(int.__or__, [l.ValueFormat2 for l in lst], 0)

	# Align them
	glyphs, padded = _merge_GlyphOrders(font,
					    [v.Coverage.glyphs for v in lst],
					    [v.PairSet for v in lst])

	self.Coverage.glyphs = glyphs
	self.PairSet = [_PairSet_flatten([v for v in values if v is not None], font)
		        for values in zip(*padded)]
	self.PairSetCount = len(self.PairSet)
	return self

def _Lookup_PairPosFormat2_subtables_flatten(lst, font):
	assert allEqual([l.ValueFormat2 == 0 for l in lst if l.Class1Record]), "Report bug against fonttools."

	self = ot.PairPos()
	self.Format = 2
	self.Coverage = ot.Coverage()
	self.Coverage.Format = 1
	self.ValueFormat1 = reduce(int.__or__, [l.ValueFormat1 for l in lst], 0)
	self.ValueFormat2 = reduce(int.__or__, [l.ValueFormat2 for l in lst], 0)

	# Align them
	glyphs, _ = _merge_GlyphOrders(font,
				       [v.Coverage.glyphs for v in lst])
	self.Coverage.glyphs = glyphs

	matrices = _PairPosFormat2_align_matrices(self, lst, font, transparent=True)

	matrix = self.Class1Record = []
	for rows in zip(*matrices):
		row = ot.Class1Record()
		matrix.append(row)
		row.Class2Record = []
		row = row.Class2Record
		for cols in zip(*list(r.Class2Record for r in rows)):
			col = next(iter(c for c in cols if c is not None))
			row.append(col)

	return self

def _Lookup_PairPos_subtables_canonicalize(lst, font):
	"""Merge multiple Format1 subtables at the beginning of lst,
	and merge multiple consecutive Format2 subtables that have the same
	Class2 (ie. were split because of offset overflows).  Returns new list."""
	lst = list(lst)

	l = len(lst)
	i = 0
	while i < l and lst[i].Format == 1:
		i += 1
	lst[:i] = [_Lookup_PairPosFormat1_subtables_flatten(lst[:i], font)]

	l = len(lst)
	i = l
	while i > 0 and lst[i - 1].Format == 2:
		i -= 1
	lst[i:] = [_Lookup_PairPosFormat2_subtables_flatten(lst[i:], font)]

	return lst

def _Lookup_SinglePos_subtables_flatten(lst, font, min_inclusive_rec_format):
	glyphs, _ = _merge_GlyphOrders(font,
		[v.Coverage.glyphs for v in lst], None)
	num_glyphs = len(glyphs)
	new = ot.SinglePos()
	new.Format = 2
	new.ValueFormat = min_inclusive_rec_format
	new.Coverage = ot.Coverage()
	new.Coverage.glyphs = glyphs
	new.ValueCount = num_glyphs
	new.Value = [None] * num_glyphs
	for singlePos in lst:
		if singlePos.Format == 1:
			val_rec = singlePos.Value
			for gname in singlePos.Coverage.glyphs:
				i = glyphs.index(gname)
				new.Value[i] = copy.deepcopy(val_rec)
		elif singlePos.Format == 2:
			for j, gname in enumerate(singlePos.Coverage.glyphs):
				val_rec = singlePos.Value[j]
				i = glyphs.index(gname)
				new.Value[i] = copy.deepcopy(val_rec)
	return [new]

@AligningMerger.merger(ot.Lookup)
def merge(merger, self, lst):
	subtables = merger.lookup_subtables = [l.SubTable for l in lst]

	# Remove Extension subtables
	for l,sts in list(zip(lst,subtables))+[(self,self.SubTable)]:
		if not sts:
			continue
		if sts[0].__class__.__name__.startswith('Extension'):
			assert allEqual([st.__class__ for st in sts])
			assert allEqual([st.ExtensionLookupType for st in sts])
			l.LookupType = sts[0].ExtensionLookupType
			new_sts = [st.ExtSubTable for st in sts]
			del sts[:]
			sts.extend(new_sts)

	isPairPos = self.SubTable and isinstance(self.SubTable[0], ot.PairPos)

	if isPairPos:
		# AFDKO and feaLib sometimes generate two Format1 subtables instead of one.
		# Merge those before continuing.
		# https://github.com/fonttools/fonttools/issues/719
		self.SubTable = _Lookup_PairPos_subtables_canonicalize(self.SubTable, merger.font)
		subtables = merger.lookup_subtables = [_Lookup_PairPos_subtables_canonicalize(st, merger.font) for st in subtables]
	else:
		isSinglePos = self.SubTable and isinstance(self.SubTable[0], ot.SinglePos)
		if isSinglePos:
			numSubtables = [len(st) for st in subtables]
			if not all([nums == numSubtables[0] for nums in numSubtables]):
				# Flatten list of SinglePos subtables to single Format 2 subtable,
				# with all value records set to the rec format type.
				# We use buildSinglePos() to optimize the lookup after merging.
				valueFormatList = [t.ValueFormat for st in subtables for t in st]
				# Find the minimum value record that can accomodate all the singlePos subtables.
				mirf = reduce(ior, valueFormatList)
				self.SubTable = _Lookup_SinglePos_subtables_flatten(self.SubTable, merger.font, mirf)
				subtables = merger.lookup_subtables = [
					_Lookup_SinglePos_subtables_flatten(st, merger.font, mirf) for st in subtables]
				flattened = True
			else:
				flattened = False

	merger.mergeLists(self.SubTable, subtables)
	self.SubTableCount = len(self.SubTable)

	if isPairPos:
		# If format-1 subtable created during canonicalization is empty, remove it.
		assert len(self.SubTable) >= 1 and self.SubTable[0].Format == 1
		if not self.SubTable[0].Coverage.glyphs:
			self.SubTable.pop(0)
			self.SubTableCount -= 1

		# If format-2 subtable created during canonicalization is empty, remove it.
		assert len(self.SubTable) >= 1 and self.SubTable[-1].Format == 2
		if not self.SubTable[-1].Coverage.glyphs:
			self.SubTable.pop(-1)
			self.SubTableCount -= 1

	elif isSinglePos and flattened:
		singlePosTable = self.SubTable[0]
		glyphs = singlePosTable.Coverage.glyphs
		# We know that singlePosTable is Format 2, as this is set
		# in _Lookup_SinglePos_subtables_flatten.
		singlePosMapping = {
			gname: valRecord
			for gname, valRecord in zip(glyphs, singlePosTable.Value)
		}
		self.SubTable = buildSinglePos(singlePosMapping, merger.font.getReverseGlyphMap())
	merger.mergeObjects(self, lst, exclude=['SubTable', 'SubTableCount'])

	del merger.lookup_subtables


#
# InstancerMerger
#

class InstancerMerger(AligningMerger):
	"""A merger that takes multiple master fonts, and instantiates
	an instance."""

	def __init__(self, font, model, location):
		Merger.__init__(self, font)
		self.model = model
		self.location = location
		self.scalars = model.getScalars(location)

@InstancerMerger.merger(ot.CaretValue)
def merge(merger, self, lst):
	assert self.Format == 1
	Coords = [a.Coordinate for a in lst]
	model = merger.model
	scalars = merger.scalars
	self.Coordinate = otRound(model.interpolateFromMastersAndScalars(Coords, scalars))

@InstancerMerger.merger(ot.Anchor)
def merge(merger, self, lst):
	assert self.Format == 1
	XCoords = [a.XCoordinate for a in lst]
	YCoords = [a.YCoordinate for a in lst]
	model = merger.model
	scalars = merger.scalars
	self.XCoordinate = otRound(model.interpolateFromMastersAndScalars(XCoords, scalars))
	self.YCoordinate = otRound(model.interpolateFromMastersAndScalars(YCoords, scalars))

@InstancerMerger.merger(otBase.ValueRecord)
def merge(merger, self, lst):
	model = merger.model
	scalars = merger.scalars
	# TODO Handle differing valueformats
	for name, tableName in [('XAdvance','XAdvDevice'),
				('YAdvance','YAdvDevice'),
				('XPlacement','XPlaDevice'),
				('YPlacement','YPlaDevice')]:

		assert not hasattr(self, tableName)

		if hasattr(self, name):
			values = [getattr(a, name, 0) for a in lst]
			value = otRound(model.interpolateFromMastersAndScalars(values, scalars))
			setattr(self, name, value)


#
# MutatorMerger
#

class MutatorMerger(AligningMerger):
	"""A merger that takes a variable font, and instantiates
	an instance.  While there's no "merging" to be done per se,
	the operation can benefit from many operations that the
	aligning merger does."""

	def __init__(self, font, location):
		Merger.__init__(self, font)
		self.location = location

		store = None
		if 'GDEF' in font:
			gdef = font['GDEF'].table
			if gdef.Version >= 0x00010003:
				store = gdef.VarStore

		self.instancer = VarStoreInstancer(store, font['fvar'].axes, location)

@MutatorMerger.merger(ot.CaretValue)
def merge(merger, self, lst):

	# Hack till we become selfless.
	self.__dict__ = lst[0].__dict__.copy()

	if self.Format != 3:
		return

	instancer = merger.instancer
	dev = self.DeviceTable
	del self.DeviceTable
	if dev:
		assert dev.DeltaFormat == 0x8000
		varidx = (dev.StartSize << 16) + dev.EndSize
		delta = otRound(instancer[varidx])
		self.Coordinate  += delta

	self.Format = 1

@MutatorMerger.merger(ot.Anchor)
def merge(merger, self, lst):

	# Hack till we become selfless.
	self.__dict__ = lst[0].__dict__.copy()

	if self.Format != 3:
		return

	instancer = merger.instancer
	for v in "XY":
		tableName = v+'DeviceTable'
		if not hasattr(self, tableName):
			continue
		dev = getattr(self, tableName)
		delattr(self, tableName)
		if dev is None:
			continue

		assert dev.DeltaFormat == 0x8000
		varidx = (dev.StartSize << 16) + dev.EndSize
		delta = otRound(instancer[varidx])

		attr = v+'Coordinate'
		setattr(self, attr, getattr(self, attr) + delta)

	self.Format = 1

@MutatorMerger.merger(otBase.ValueRecord)
def merge(merger, self, lst):

	# Hack till we become selfless.
	self.__dict__ = lst[0].__dict__.copy()

	instancer = merger.instancer
	# TODO Handle differing valueformats
	for name, tableName in [('XAdvance','XAdvDevice'),
				('YAdvance','YAdvDevice'),
				('XPlacement','XPlaDevice'),
				('YPlacement','YPlaDevice')]:

		if not hasattr(self, tableName):
			continue
		dev = getattr(self, tableName)
		delattr(self, tableName)
		if dev is None:
			continue

		assert dev.DeltaFormat == 0x8000
		varidx = (dev.StartSize << 16) + dev.EndSize
		delta = otRound(instancer[varidx])

		setattr(self, name, getattr(self, name) + delta)


#
# VariationMerger
#

class VariationMerger(AligningMerger):
	"""A merger that takes multiple master fonts, and builds a
	variable font."""

	def __init__(self, model, axisTags, font):
		Merger.__init__(self, font)
		self.store_builder = varStore.OnlineVarStoreBuilder(axisTags)
		self.setModel(model)

	def setModel(self, model):
		self.model = model
		self.store_builder.setModel(model)

	def mergeThings(self, out, lst):
		masterModel = None
		if None in lst:
			if allNone(lst):
				assert out is None, (out, lst)
				return
			masterModel = self.model
			model, lst = masterModel.getSubModel(lst)
			self.setModel(model)

		super(VariationMerger, self).mergeThings(out, lst)

		if masterModel:
			self.setModel(masterModel)


def buildVarDevTable(store_builder, master_values):
	if allEqual(master_values):
		return master_values[0], None
	base, varIdx = store_builder.storeMasters(master_values)
	return base, builder.buildVarDevTable(varIdx)

@VariationMerger.merger(ot.CaretValue)
def merge(merger, self, lst):
	assert self.Format == 1
	self.Coordinate, DeviceTable = buildVarDevTable(merger.store_builder, [a.Coordinate for a in lst])
	if DeviceTable:
		self.Format = 3
		self.DeviceTable = DeviceTable

@VariationMerger.merger(ot.Anchor)
def merge(merger, self, lst):
	assert self.Format == 1
	self.XCoordinate, XDeviceTable = buildVarDevTable(merger.store_builder, [a.XCoordinate for a in lst])
	self.YCoordinate, YDeviceTable = buildVarDevTable(merger.store_builder, [a.YCoordinate for a in lst])
	if XDeviceTable or YDeviceTable:
		self.Format = 3
		self.XDeviceTable = XDeviceTable
		self.YDeviceTable = YDeviceTable

@VariationMerger.merger(otBase.ValueRecord)
def merge(merger, self, lst):
	for name, tableName in [('XAdvance','XAdvDevice'),
				('YAdvance','YAdvDevice'),
				('XPlacement','XPlaDevice'),
				('YPlacement','YPlaDevice')]:

		if hasattr(self, name):
			value, deviceTable = buildVarDevTable(merger.store_builder,
							      [getattr(a, name, 0) for a in lst])
			setattr(self, name, value)
			if deviceTable:
				setattr(self, tableName, deviceTable)
