Merge pull request #3248 from googlefonts/connected_components

[repacker] Keep connected subgraphs in the same space.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dee9a46..295cff8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -437,6 +437,7 @@
 ## Define harfbuzz-subset library
 if (HB_BUILD_SUBSET)
   add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
+  list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-subset.h)
   add_dependencies(harfbuzz-subset harfbuzz)
   target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
 
@@ -702,6 +703,11 @@
       FRAMEWORK DESTINATION Library/Frameworks
     )
   endif ()
+  if (HB_BUILD_SUBSET)
+    install(TARGETS harfbuzz-subset
+      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+  )
+  endif ()
   if (HB_BUILD_UTILS)
     if (WIN32 AND BUILD_SHARED_LIBS)
       install(TARGETS harfbuzz-subset
diff --git a/docs/repacker.md b/docs/repacker.md
new file mode 100644
index 0000000..b7aacc4
--- /dev/null
+++ b/docs/repacker.md
@@ -0,0 +1,265 @@
+# Introduction
+
+Several tables in the opentype format are formed internally by a graph of subtables. Parent node's
+reference their children through the use of positive offsets, which are typically 16 bits wide.
+Since offsets are always positive this forms a directed acyclic graph. For storage in the font file
+the graph must be given a topological ordering and then the subtables packed in serial according to
+that ordering. Since 16 bit offsets have a maximum value of 65,535 if the distance between a parent
+subtable and a child is more then 65,535 bytes then it's not possible for the offset to encode that
+edge.
+
+For many fonts with complex layout rules (such as Arabic) it's not unusual for the tables containing
+layout rules ([GSUB/GPOS](https://docs.microsoft.com/en-us/typography/opentype/spec/gsub)) to be
+larger than 65kb. As a result these types of fonts are susceptible to offset overflows when
+serializing to the binary font format.
+
+Offset overflows can happen for a variety of reasons and require different strategies to resolve:
+*  Simple overflows can often be resolved with a different topological ordering.
+*  If a subtable has many parents this can result in the link from furthest parent(s)
+   being at risk for overflows. In these cases it's possible to duplicate the shared subtable which
+   allows it to be placed closer to it's parent.
+*  If subtables exist which are themselves larger than 65kb it's not possible for any offsets to point
+   past them. In these cases the subtable can usually be split into two smaller subtables to allow
+   for more flexibility in the ordering.
+*  In GSUB/GPOS overflows from Lookup subtables can be resolved by changing the Lookup to an extension
+   lookup which uses a 32 bit offset instead of 16 bit offset.
+   
+In general there isn't a simple solution to produce an optimal topological ordering for a given graph.
+Finding an ordering which doesn't overflow is a NP hard problem. Existing solutions use heuristics
+which attempt a combination of the above strategies to attempt to find a non-overflowing configuration.
+   
+The harfbuzz subsetting library
+[includes a repacking algorithm](https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-repacker.hh)
+which is used to resolve offset overflows that are present in the subsetted tables it produces. This
+document provides a deep dive into how the harfbuzz repacking algorithm works.
+
+Other implementations exist, such as in
+[fontTools](https://github.com/fonttools/fonttools/blob/7af43123d49c188fcef4e540fa94796b3b44e858/Lib/fontTools/ttLib/tables/otBase.py#L72), however these are not covered in this document.
+
+# Foundations
+
+There's four key pieces to the harfbuzz approach:
+
+*  Subtable Graph: a table's internal structure is abstraced out into a lightweight graph
+   representation where each subtable is a node and each offset forms an edge. The nodes only need
+   to know how many bytes the corresponding subtable occupies. This lightweight representation can
+   be easily modified to test new ordering's and strategies as the repacking algorithm iterates.
+
+*  [Topological sorting algorithm](https://en.wikipedia.org/wiki/Topological_sorting): an algorithm
+   which given a graph gives a linear sorting of the nodes such that all offsets will be positive.
+   
+*  Overflow check: given a graph and a topological sorting it checks if there will be any overflows
+   in any of the offsets. If there are overflows it returns a list of (parent, child) tuples that
+   will overflow. Since the graph has information on the size of each subtable it's straightforward
+   to calculate the final position of each subtable and then check if any offsets to it will
+   overflow.
+   
+*  Offset resolution strategies: given a particular occurence of an overflow these strategies
+   modify the graph to attempt to resolve the overflow.
+   
+# High Level Algorithm
+
+```
+def repack(graph):
+  graph.topological_sort()
+
+  if (graph.will_overflow())
+    assign_spaces(graph)
+    graph.topological_sort()
+
+  while (overflows = graph.will_overflow()):
+    for overflow in overflows:
+      apply_offset_resolution_strategy (overflow, graph)
+    graph.topological_sort()
+```
+
+The actual code for this processing loop can be found in the function hb_resolve_overflows () of
+[hb-repacker.hh](https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-repacker.hh).
+
+# Topological Sorting Algorithms
+
+The harfbuzz repacker uses two different algorithms for topological sorting:
+*  [Kahn's Algorithm](https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm)
+*  Sorting by shortest distance
+
+Kahn's algorithm is approximately twice as fast as the shortest distance sort so that is attempted
+first (only on the first topological sort). If it fails to eliminate overflows then shortest distance
+sort will be used for all subsequent topological sorting operations.
+   
+## Shortest Distance Sort
+
+This algorithm orders the nodes based on total distance to each node. Nodes with a shorter distance
+are ordered first.
+
+The "weight" of an edge is the sum of the size of the sub-table being pointed to plus 2^16 for a 16 bit
+offset and 2^32 for a 32 bit offset.
+
+The distance of a node is the sum of all weights along the shortest path from the root to that node
+plus a priority modifier (used to change where nodes are placed by moving increasing or
+decreasing the effective distance). Ties between nodes with the same distance are broken based
+on the order of the offset in the sub table bytes.
+
+The shortest distance to each node is determined using
+[Djikstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm). Then the topological
+ordering is produce by applying a modified version of Kahn's algorithm that uses a priority queue
+based on the shortest distance to each node.
+
+## Optimizing the Sorting
+
+The topological sorting operation is the core of the repacker and is run on each iteration so it needs
+to be as fast as possible. There's a few things that are done to speed up subsequent sorting
+operations:
+
+*  The number of incoming edges to each node is cached. This is required by the Kahn's algorithm
+   portion of boths sorts. Where possible when the graph is modified we manually update the cached
+   edge counts of affected nodes.
+   
+*  The distance to each node is cached. Where possible when the graph is modified we manually update
+   the cached distances of any affected nodes.
+
+Caching these values allows the repacker to avoid recalculating them for the full graph on each
+iteration.
+
+The other important factor to speed is a fast priority queue which is a core datastructure to
+the topological sorting algorithm. Currently a basic heap based queue is used. Heap based queue's
+don't support fast priority decreases, but that can be worked around by just adding redundant entries
+to the priority queue and filtering the older ones out when poppping off entries. This is based
+on the recommendations in
+[a study of the practical performance of priority queues in Dijkstra's algorithm](https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf)
+
+## Special Handling of 32 bit Offsets
+
+If a graph contains multiple 32 bit offsets then the shortest distance sorting will be likely be
+suboptimal. For example consider the case where a graph contains two 32 bit offsets that each point
+to a subgraph which are not connected to each other. The shortest distance sort will interleave the
+subtables of the two subgraphs, potentially resulting in overflows. Since each of these subgraphs are
+independent of each other, and 32 bit offsets can point extremely long distances a better strategy is
+to pack the first subgraph in it's entirety and then have the second subgraph packed after with the 32
+bit offset pointing over the first subgraph. For example given the graph:
+
+
+```
+a--- b -- d -- f
+ \
+  \_ c -- e -- g
+```
+
+Where the links from a to b and a to c are 32 bit offsets, the shortest distance sort would be:
+
+```
+a, b, c, d, e, f, g
+
+```
+
+If nodes d and e have a combined size greater than 65kb then the offset from d to f will overflow.
+A better ordering is:
+
+```
+a, b, d, f, c, e, g
+```
+
+The ability for 32 bit offsets to point long distances is utilized to jump over the subgraph of
+b which gives the remaining 16 bit offsets a better chance of not overflowing.
+
+The above is an ideal situation where the subgraphs are disconnected from each other, in practice
+this is often not this case. So this idea can be generalized as follows:
+
+If there is a subgraph that is only reachable from one or more 32 bit offsets, then:
+*  That subgraph can be treated as an indepedent unit and all nodes of the subgraph packed in isolation
+   from the rest of the graph.
+*  In a table that occupies less than 4gb of space (in practice all fonts), that packed independent
+   subgraph can be placed anywhere after the parent nodes without overflowing the 32 bit offsets from
+   the parent nodes.
+
+The sorting algorithm incorporates this via a "space" modifier that can be applied to nodes in the
+graph. By default all nodes are treated as being in space zero. If a node is given a non-zero space, n,
+then the computed distance to the node will be modified by adding `n * 2^32`. This will cause that
+node and it's descendants to be packed between all nodes in space n-1 and space n+1. Resulting in a
+topological sort like:
+
+```
+| space 0 subtables | space 1 subtables | .... | space n subtables |
+```
+
+The assign_spaces() step in the high level algorithm is responsible for identifying independent
+subgraphs and assigning unique spaces to each one. More information on the space assignment can be
+found in the next section.
+
+
+# Offset Resolution Strategies
+
+## Space Assignment
+
+The goal of space assignment is to find connected subgraphs that are only reachable via 32 bit offsets
+and then assign each such subgraph to a unique non-zero space. The algorithm is roughly:
+
+1.  Collect the set, `S`, of nodes that are children of 32 bit offsets.
+
+2.  Do a directed traversal from each node in `S` and collect all encountered nodes into set `T`.
+    Mark all nodes in the graph that are not in `T` as being in space 0.
+
+3.  Set `next_space = 1`.
+
+4.  While set `S` is not empty:
+
+    a.  Pick a node `n` in set `S` then perform an undirected graph traversal and find the set `Q` of
+        nodes that are reachable from `n`.
+       
+    b.  During traversal if a node, `m`, has a edge to a node in space 0 then `m` must be duplicated
+        to disconnect it from space 0.
+  
+    d.  Remove all nodes in `Q` from `S` and assign all nodes in `Q` to `next_space`.
+       
+       
+    c.  Increment `next_space` by one.
+
+
+## Manual Iterative Resolutions
+
+For each overflow in each iteration the algorithm will attempt to apply offset overflow resolution
+strategies to eliminate the overflow. The type of strategy applied is dependant on the characteristics
+of the overflowing link:
+
+*  If the overflowing offset is inside a space other than space 0 and the subgraph space has more
+   than one 32 bit offset pointing into the subgraph then subdivide the space by moving subgraph
+   from one of the 32 bit offsets into a new space via the duplication of shared nodes.
+
+*  If the overflowing offset is pointing to a subtable with more than one incoming edge: duplicate
+   the node so that the overflowing offset is pointing at it's own copy of that node.
+   
+*  Otherwise, attempt to move the child subtable closer to it's parent. This is accomplished by
+   raising the priority of all children of the parent. Next time the topological sort is run the
+   children will be ordered closer to the parent.
+   
+# Test Cases
+
+The harfbuzz repacker has tests defined using generic graphs: https://github.com/harfbuzz/harfbuzz/blob/main/src/test-repacker.cc
+   
+# Future Improvments
+
+The above resolution strategies are not sufficient to resolve all overflows. For example consider
+the case where a single subtable is 65k and the graph structure requires an offset to point over it.
+
+The current harfbuzz implementation is suitable for the vast majority of subsetting related overflows.
+Subsetting related overflows are typically easy to solve since all subsets are derived from a font
+that was originally overflow free. A more general purpose version of the algorithm suitable for font
+creation purposes will likely need some additional offset resolution strategies:
+
+*  Currently only children nodes are moved to resolve offsets. However, in many cases moving a parent
+   node closer to it's children will have less impact on the size of other offsets. Thus the algorithm
+   should use a heuristic (based on parent and child subtable sizes) to decide if the children's
+   priority should be increased or the parent's priority decreased.
+   
+*  Many subtables can be split into two smaller subtables without impacting the overall functionality.
+   This should be done when an overflow is the result of a very large table which can't be moved
+   to avoid offsets pointing over it.
+   
+*  Lookup subtables in GSUB/GPOS can be upgraded to extension lookups which uses a 32 bit offset.
+   Overflows from a Lookup subtable to it's child should be resolved by converting to an extension
+   lookup.
+   
+Once additional resolution strategies are added to the algorithm it's likely that we'll need to
+switch to using a [backtracking algorithm](https://en.wikipedia.org/wiki/Backtracking) to explore
+the various combinations of resolution strategies until a non-overflowing combination is found. This
+will require the ability to restore the graph to an earlier state. It's likely that using a stack
+of undoable resolution commands could be used to accomplish this.
diff --git a/meson.build b/meson.build
index 389c49c..da426ed 100644
--- a/meson.build
+++ b/meson.build
@@ -96,7 +96,8 @@
                       fallback: ['glib', 'libglib_dep'])
 gobject_dep = dependency('gobject-2.0', required: get_option('gobject'),
                          fallback: ['glib', 'libgobject_dep'])
-graphite2_dep = dependency('graphite2', required: get_option('graphite'))
+graphite2_dep = dependency('graphite2', required: get_option('graphite2'))
+graphite_dep = dependency('graphite2', required: get_option('graphite'))
 
 icu_dep = null_dep
 if not get_option('icu').disabled()
@@ -188,7 +189,7 @@
   conf.set('HAVE_CHAFA', 1)
 endif
 
-if graphite2_dep.found()
+if graphite2_dep.found() or graphite_dep.found()
   conf.set('HAVE_GRAPHITE2', 1)
 endif
 
diff --git a/meson_options.txt b/meson_options.txt
index cd4526b..9ebba72 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -10,6 +10,8 @@
 option('icu', type: 'feature', value: 'auto',
   description: 'Enable ICU library unicode functions')
 option('graphite', type: 'feature', value: 'disabled',
+  description: 'Deprecated use graphite2 option instead')
+option('graphite2', type: 'feature', value: 'disabled',
   description: 'Enable Graphite2 complementary shaper')
 option('freetype', type: 'feature', value: 'auto',
   description: 'Enable freetype interop helpers')
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 28fbf2c..699dfdc 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -143,6 +143,7 @@
 	hb-ot-tag-table.hh \
 	hb-ot-tag.cc \
 	hb-ot-var-avar-table.hh \
+	hb-ot-var-common.hh \
 	hb-ot-var-fvar-table.hh \
 	hb-ot-var-gvar-table.hh \
 	hb-ot-var-hvar-table.hh \
diff --git a/src/gen-use-table.py b/src/gen-use-table.py
index 9303003..34540ca 100755
--- a/src/gen-use-table.py
+++ b/src/gen-use-table.py
@@ -1,33 +1,37 @@
 #!/usr/bin/env python3
 # flake8: noqa: F821
 
-"""usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt ArabicShaping.txt Blocks.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
+"""usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
 
 Input files:
 * https://unicode.org/Public/UCD/latest/ucd/IndicSyllabicCategory.txt
 * https://unicode.org/Public/UCD/latest/ucd/IndicPositionalCategory.txt
-* https://unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
 * https://unicode.org/Public/UCD/latest/ucd/ArabicShaping.txt
+* https://unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
+* https://unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
 * https://unicode.org/Public/UCD/latest/ucd/Blocks.txt
+* https://unicode.org/Public/UCD/latest/ucd/Scripts.txt
 * ms-use/IndicSyllabicCategory-Additional.txt
 * ms-use/IndicPositionalCategory-Additional.txt
 """
 
 import sys
 
-if len (sys.argv) != 8:
+if len (sys.argv) != 10:
 	sys.exit (__doc__)
 
-DISABLED_BLOCKS = [
-	'Samaritan',
-	'Thai',
+DISABLED_SCRIPTS = {
+	'Arabic',
 	'Lao',
-]
+	'Samaritan',
+	'Syriac',
+	'Thai',
+}
 
 files = [open (x, encoding='utf-8') for x in sys.argv[1:]]
 
-headers = [[f.readline () for i in range (2)] for j,f in enumerate(files) if j != 2]
-for j in range(5, 7):
+headers = [[f.readline () for i in range (2)] for j,f in enumerate(files) if j != 4]
+for j in range(7, 9):
 	for line in files[j]:
 		line = line.rstrip()
 		if not line:
@@ -38,16 +42,8 @@
 data = [{} for _ in files]
 values = [{} for _ in files]
 for i, f in enumerate (files):
-	extended = False
-
 	for line in f:
 
-		# TODO: https://github.com/MicrosoftDocs/typography-issues/issues/522
-		if extended and line.startswith ('# ') and line.find (';'):
-			line = line[2:]
-		elif 'USE_Syllabic_Category' in line:
-			extended = True
-
 		j = line.find ('#')
 		if j >= 0:
 			line = line[:j]
@@ -63,25 +59,26 @@
 		else:
 			end = int (uu[1], 16)
 
-		t = fields[1 if i not in [2, 3] else 2]
+		t = fields[1 if i not in [2, 4] else 2]
 
-		if i == 3:
+		if i == 2:
 			t = 'jt_' + t
-		elif i == 5 and t == 'Consonant_Final_Modifier':
+		elif i == 3 and t != 'Default_Ignorable_Code_Point':
+			continue
+		elif i == 7 and t == 'Consonant_Final_Modifier':
 			# TODO: https://github.com/MicrosoftDocs/typography-issues/issues/336
 			t = 'Syllable_Modifier'
-		elif i == 6 and t == 'NA':
+		elif i == 8 and t == 'NA':
 			t = 'Not_Applicable'
 
-		i0 = i if i < 5 else i - 5
+		i0 = i if i < 7 else i - 7
 		for u in range (start, end + 1):
 			data[i0][u] = t
 		values[i0][t] = values[i0].get (t, 0) + end - start + 1
 
-defaults = ('Other', 'Not_Applicable', 'Cn', 'jt_X', 'No_Block')
+defaults = ('Other', 'Not_Applicable', 'jt_X', '', 'Cn', 'No_Block', 'Unknown')
 
 # TODO Characters that are not in Unicode Indic files, but used in USE
-data[0][0x0640] = defaults[0]
 data[0][0x1B61] = defaults[0]
 data[0][0x1B63] = defaults[0]
 data[0][0x1B64] = defaults[0]
@@ -91,29 +88,6 @@
 data[0][0x1B69] = defaults[0]
 data[0][0x1B6A] = defaults[0]
 data[0][0x2060] = defaults[0]
-for u in range (0x07CA, 0x07EA + 1):
-	data[0][u] = defaults[0]
-data[0][0x07FA] = defaults[0]
-for u in range (0x0840, 0x0858 + 1):
-	data[0][u] = defaults[0]
-for u in range (0x1887, 0x18A8 + 1):
-	data[0][u] = defaults[0]
-data[0][0x18AA] = defaults[0]
-for u in range (0xA840, 0xA872 + 1):
-	data[0][u] = defaults[0]
-for u in range (0x10B80, 0x10B91 + 1):
-	data[0][u] = defaults[0]
-for u in range (0x10BA9, 0x10BAE + 1):
-	data[0][u] = defaults[0]
-data[0][0x10FB0] = defaults[0]
-for u in range (0x10FB2, 0x10FB6 + 1):
-	data[0][u] = defaults[0]
-for u in range (0x10FB8, 0x10FBF + 1):
-	data[0][u] = defaults[0]
-for u in range (0x10FC1, 0x10FC4 + 1):
-	data[0][u] = defaults[0]
-for u in range (0x10FC9, 0x10FCB + 1):
-	data[0][u] = defaults[0]
 # TODO https://github.com/harfbuzz/harfbuzz/pull/1685
 data[0][0x1B5B] = 'Consonant_Placeholder'
 data[0][0x1B5C] = 'Consonant_Placeholder'
@@ -132,12 +106,12 @@
 combined = {}
 for i,d in enumerate (data):
 	for u,v in d.items ():
-		if i >= 2 and not u in combined:
-			continue
 		if not u in combined:
+			if i >= 4:
+				continue
 			combined[u] = list (defaults)
 		combined[u][i] = v
-combined = {k:v for k,v in combined.items() if v[4] not in DISABLED_BLOCKS}
+combined = {k: v for k, v in combined.items() if v[6] not in DISABLED_SCRIPTS}
 data = combined
 del combined
 
@@ -237,7 +211,7 @@
 globals().update(property_values)
 
 
-def is_BASE(U, UISC, UGC, AJT):
+def is_BASE(U, UISC, UDI, UGC, AJT):
 	return (UISC in [Number, Consonant, Consonant_Head_Letter,
 			Tone_Letter,
 			Vowel_Independent,
@@ -246,77 +220,79 @@
 		AJT in [jt_C, jt_D, jt_L, jt_R] and UISC != Joiner or
 		(UGC == Lo and UISC in [Avagraha, Bindu, Consonant_Final, Consonant_Medial,
 					Consonant_Subjoined, Vowel, Vowel_Dependent]))
-def is_BASE_NUM(U, UISC, UGC, AJT):
+def is_BASE_NUM(U, UISC, UDI, UGC, AJT):
 	return UISC == Brahmi_Joining_Number
-def is_BASE_OTHER(U, UISC, UGC, AJT):
+def is_BASE_OTHER(U, UISC, UDI, UGC, AJT):
 	if UISC == Consonant_Placeholder: return True
 	return U in [0x2015, 0x2022, 0x25FB, 0x25FC, 0x25FD, 0x25FE]
-def is_CONS_FINAL(U, UISC, UGC, AJT):
+def is_CGJ(U, UISC, UDI, UGC, AJT):
+	# Also includes VARIATION_SELECTOR, WJ, and ZWJ
+	return U == 0x200D or UDI and UGC in [Mc, Me, Mn]
+def is_CONS_FINAL(U, UISC, UDI, UGC, AJT):
 	return ((UISC == Consonant_Final and UGC != Lo) or
 		UISC == Consonant_Succeeding_Repha)
-def is_CONS_FINAL_MOD(U, UISC, UGC, AJT):
+def is_CONS_FINAL_MOD(U, UISC, UDI, UGC, AJT):
 	return UISC == Syllable_Modifier
-def is_CONS_MED(U, UISC, UGC, AJT):
+def is_CONS_MED(U, UISC, UDI, UGC, AJT):
 	# Consonant_Initial_Postfixed is new in Unicode 11; not in the spec.
 	return (UISC == Consonant_Medial and UGC != Lo or
 		UISC == Consonant_Initial_Postfixed)
-def is_CONS_MOD(U, UISC, UGC, AJT):
+def is_CONS_MOD(U, UISC, UDI, UGC, AJT):
 	return (UISC in [Nukta, Gemination_Mark, Consonant_Killer] and
-		not is_SYM_MOD(U, UISC, UGC, AJT))
-def is_CONS_SUB(U, UISC, UGC, AJT):
+		not is_SYM_MOD(U, UISC, UDI, UGC, AJT))
+def is_CONS_SUB(U, UISC, UDI, UGC, AJT):
 	return UISC == Consonant_Subjoined and UGC != Lo
-def is_CONS_WITH_STACKER(U, UISC, UGC, AJT):
+def is_CONS_WITH_STACKER(U, UISC, UDI, UGC, AJT):
 	return UISC == Consonant_With_Stacker
-def is_HALANT(U, UISC, UGC, AJT):
+def is_HALANT(U, UISC, UDI, UGC, AJT):
 	return (UISC in [Virama, Invisible_Stacker]
-		and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC, AJT)
-		and not is_SAKOT(U, UISC, UGC, AJT))
-def is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC, AJT):
-	# https://github.com/harfbuzz/harfbuzz/issues/1102
+		and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UDI, UGC, AJT)
+		and not is_SAKOT(U, UISC, UDI, UGC, AJT))
+def is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UDI, UGC, AJT):
+	# Split off of HALANT
 	# https://github.com/harfbuzz/harfbuzz/issues/1379
-	return U in [0x11046, 0x1134D]
-def is_HALANT_NUM(U, UISC, UGC, AJT):
+	return U == 0x1134D
+def is_HALANT_NUM(U, UISC, UDI, UGC, AJT):
 	return UISC == Number_Joiner
-def is_HIEROGLYPH(U, UISC, UGC, AJT):
+def is_HIEROGLYPH(U, UISC, UDI, UGC, AJT):
 	return UISC == Hieroglyph
-def is_HIEROGLYPH_JOINER(U, UISC, UGC, AJT):
+def is_HIEROGLYPH_JOINER(U, UISC, UDI, UGC, AJT):
 	return UISC == Hieroglyph_Joiner
-def is_HIEROGLYPH_SEGMENT_BEGIN(U, UISC, UGC, AJT):
+def is_HIEROGLYPH_SEGMENT_BEGIN(U, UISC, UDI, UGC, AJT):
 	return UISC == Hieroglyph_Segment_Begin
-def is_HIEROGLYPH_SEGMENT_END(U, UISC, UGC, AJT):
+def is_HIEROGLYPH_SEGMENT_END(U, UISC, UDI, UGC, AJT):
 	return UISC == Hieroglyph_Segment_End
-def is_ZWNJ(U, UISC, UGC, AJT):
+def is_ZWNJ(U, UISC, UDI, UGC, AJT):
 	return UISC == Non_Joiner
-def is_OTHER(U, UISC, UGC, AJT):
+def is_OTHER(U, UISC, UDI, UGC, AJT):
+	# Also includes BASE_IND, Rsv, and SYM
 	return ((UGC in [Cn, Po] or UISC in [Consonant_Dead, Joiner, Modifying_Letter, Other])
-		and not is_BASE(U, UISC, UGC, AJT)
-		and not is_BASE_OTHER(U, UISC, UGC, AJT)
-		and not is_SYM(U, UISC, UGC, AJT)
-		and not is_SYM_MOD(U, UISC, UGC, AJT)
+		and not is_BASE(U, UISC, UDI, UGC, AJT)
+		and not is_BASE_OTHER(U, UISC, UDI, UGC, AJT)
+		and not is_CGJ(U, UISC, UDI, UGC, AJT)
+		and not is_SYM_MOD(U, UISC, UDI, UGC, AJT)
 	)
-def is_REPHA(U, UISC, UGC, AJT):
+def is_REPHA(U, UISC, UDI, UGC, AJT):
 	return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed]
-def is_SAKOT(U, UISC, UGC, AJT):
+def is_SAKOT(U, UISC, UDI, UGC, AJT):
+	# Split off of HALANT
 	return U == 0x1A60
-def is_SYM(U, UISC, UGC, AJT):
-	if U in [0x25CC, 0x1E14F]: return False
-	return UGC in [So, Sc] and U not in [0x0F01, 0x1B62, 0x1B68]
-def is_SYM_MOD(U, UISC, UGC, AJT):
+def is_SYM_MOD(U, UISC, UDI, UGC, AJT):
 	return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
-def is_VOWEL(U, UISC, UGC, AJT):
+def is_VOWEL(U, UISC, UDI, UGC, AJT):
 	# https://github.com/harfbuzz/harfbuzz/issues/376
 	return (UISC == Pure_Killer or
 		(UGC != Lo and UISC in [Vowel, Vowel_Dependent] and U not in [0xAA29]))
-def is_VOWEL_MOD(U, UISC, UGC, AJT):
+def is_VOWEL_MOD(U, UISC, UDI, UGC, AJT):
 	# https://github.com/harfbuzz/harfbuzz/issues/376
 	return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or
 		(UGC != Lo and (UISC == Bindu or U in [0xAA29])))
 
-# CGJ, VS, WJ, and ZWJ are handled in find_syllables
 use_mapping = {
 	'B':	is_BASE,
 	'N':	is_BASE_NUM,
 	'GB':	is_BASE_OTHER,
+	'CGJ':	is_CGJ,
 	'F':	is_CONS_FINAL,
 	'FM':	is_CONS_FINAL_MOD,
 	'M':	is_CONS_MED,
@@ -333,7 +309,6 @@
 	'ZWNJ':	is_ZWNJ,
 	'O':	is_OTHER,
 	'R':	is_REPHA,
-	'S':	is_SYM,
 	'Sk':	is_SAKOT,
 	'SM':	is_SYM_MOD,
 	'V':	is_VOWEL,
@@ -387,7 +362,7 @@
 def map_to_use(data):
 	out = {}
 	items = use_mapping.items()
-	for U,(UISC,UIPC,UGC,AJT,UBlock) in data.items():
+	for U, (UISC, UIPC, AJT, UDI, UGC, UBlock, _) in data.items():
 
 		# Resolve Indic_Syllabic_Category
 
@@ -408,8 +383,8 @@
 		# TODO: https://github.com/microsoft/font-tools/issues/1
 		if U == 0xA982: UISC = Consonant_Succeeding_Repha
 
-		values = [k for k,v in items if v(U,UISC,UGC,AJT)]
-		assert len(values) == 1, "%s %s %s %s %s" % (hex(U), UISC, UGC, AJT, values)
+		values = [k for k,v in items if v(U, UISC, UDI, UGC, AJT)]
+		assert len(values) == 1, "%s %s %s %s %s %s" % (hex(U), UISC, UDI, UGC, AJT, values)
 		USE = values[0]
 
 		# Resolve Indic_Positional_Category
@@ -430,12 +405,12 @@
 		if 0x11131 <= U <= 0x11132: UIPC = Top
 
 		assert (UIPC in [Not_Applicable, Visual_Order_Left] or U == 0x0F7F or
-			USE in use_positions), "%s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC, AJT)
+			USE in use_positions), "%s %s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UDI, UGC, AJT)
 
 		pos_mapping = use_positions.get(USE, None)
 		if pos_mapping:
 			values = [k for k,v in pos_mapping.items() if v and UIPC in v]
-			assert len(values) == 1, "%s %s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC, AJT, values)
+			assert len(values) == 1, "%s %s %s %s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UDI, UGC, AJT, values)
 			USE = USE + values[0]
 
 		out[U] = (USE, UBlock)
@@ -448,7 +423,7 @@
 print ("/*")
 print (" * The following table is generated by running:")
 print (" *")
-print (" *   {} IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt ArabicShaping.txt Blocks.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt".format (sys.argv[0]))
+print (" *   {} IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt".format (sys.argv[0]))
 print (" *")
 print (" * on files with these headers:")
 print (" *")
diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh
index 73909c2..5722acb 100644
--- a/src/hb-ot-color-colr-table.hh
+++ b/src/hb-ot-color-colr-table.hh
@@ -30,6 +30,7 @@
 
 #include "hb-open-type.hh"
 #include "hb-ot-layout-common.hh"
+#include "hb-ot-var-common.hh"
 
 /*
  * COLR -- Color
@@ -42,7 +43,7 @@
 #endif
 
 #ifndef COLRV1_ENABLE_SUBSETTING
-#define COLRV1_ENABLE_SUBSETTING 0
+#define COLRV1_ENABLE_SUBSETTING 1
 #endif
 
 namespace OT {
@@ -163,15 +164,31 @@
 template <typename T>
 struct Variable
 {
+  Variable<T>* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (c->embed (this));
+  }
+
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  { value.closurev1 (c); }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    if (!value.subset (c)) return_trace (false);
+    return_trace (c->serializer->embed (varIdxBase));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (c->check_struct (this) && value.sanitize (c));
   }
 
   protected:
   T      value;
-  VarIdx varIdx;
+  VarIdx varIdxBase;
   public:
   DEFINE_SIZE_STATIC (4 + T::static_size);
 };
@@ -179,10 +196,25 @@
 template <typename T>
 struct NoVariable
 {
+  NoVariable<T>* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (c->embed (this));
+  }
+
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  { value.closurev1 (c); }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    return_trace (value.subset (c));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (c->check_struct (this) && value.sanitize (c));
   }
 
   T      value;
@@ -192,9 +224,11 @@
 
 // Color structures
 
-template <template<typename> class Var>
-struct ColorIndex
+struct ColorStop
 {
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  { c->add_palette_index (paletteIndex); }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
@@ -210,32 +244,11 @@
     return_trace (c->check_struct (this));
   }
 
+  F2DOT14	stopOffset;
   HBUINT16	paletteIndex;
-  Var<F2DOT14>	alpha;
+  F2DOT14	alpha;
   public:
-  DEFINE_SIZE_STATIC (2 + Var<F2DOT14>::static_size);
-};
-
-template <template<typename> class Var>
-struct ColorStop
-{
-  bool subset (hb_subset_context_t *c) const
-  {
-    TRACE_SUBSET (this);
-    if (unlikely (!c->serializer->embed (stopOffset))) return_trace (false);
-    return_trace (color.subset (c));
-  }
-
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  Var<F2DOT14>		stopOffset;
-  ColorIndex<Var>		color;
-  public:
-  DEFINE_SIZE_STATIC (Var<F2DOT14>::static_size + ColorIndex<Var>::static_size);
+  DEFINE_SIZE_STATIC (2 + 2 * F2DOT14::static_size);
 };
 
 struct Extend : HBUINT8
@@ -252,6 +265,12 @@
 template <template<typename> class Var>
 struct ColorLine
 {
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  {
+    for (const auto &stop : stops.iter ())
+      stop.closurev1 (c);
+  }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
@@ -276,8 +295,8 @@
                   stops.sanitize (c));
   }
 
-  Extend			extend;
-  Array16Of<ColorStop<Var>>	stops;
+  Extend	extend;
+  Array16Of<Var<ColorStop>>	stops;
   public:
   DEFINE_SIZE_ARRAY_SIZED (3, stops);
 };
@@ -331,7 +350,6 @@
   DEFINE_SIZE_STATIC (1);
 };
 
-template <template<typename> class Var>
 struct Affine2x3
 {
   bool sanitize (hb_sanitize_context_t *c) const
@@ -340,14 +358,14 @@
     return_trace (c->check_struct (this));
   }
 
-  Var<HBFixed> xx;
-  Var<HBFixed> yx;
-  Var<HBFixed> xy;
-  Var<HBFixed> yy;
-  Var<HBFixed> dx;
-  Var<HBFixed> dy;
+  HBFixed xx;
+  HBFixed yx;
+  HBFixed xy;
+  HBFixed yy;
+  HBFixed dx;
+  HBFixed dy;
   public:
-  DEFINE_SIZE_STATIC (6 * Var<HBFixed>::static_size);
+  DEFINE_SIZE_STATIC (6 * HBFixed::static_size);
 };
 
 struct PaintColrLayers
@@ -373,22 +391,23 @@
 
   HBUINT8	format; /* format = 1 */
   HBUINT8	numLayers;
-  HBUINT32	firstLayerIndex;  /* index into COLRv1::layersV1 */
+  HBUINT32	firstLayerIndex;  /* index into COLRv1::layerList */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
-template <template<typename> class Var>
 struct PaintSolid
 {
   void closurev1 (hb_colrv1_closure_context_t* c) const
-  { c->add_palette_index (color.paletteIndex); }
+  { c->add_palette_index (paletteIndex); }
 
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    if (unlikely (!c->serializer->embed (format))) return_trace (false);
-    return_trace (color.subset (c));
+    auto *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex),
+                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -397,20 +416,18 @@
     return_trace (c->check_struct (this));
   }
 
-  HBUINT8		format; /* format = 2(noVar) or 3(Var)*/
-  ColorIndex<Var>	color;
+  HBUINT8	format; /* format = 2(noVar) or 3(Var)*/
+  HBUINT16	paletteIndex;
+  F2DOT14	alpha;
   public:
-  DEFINE_SIZE_STATIC (1 + ColorIndex<Var>::static_size);
+  DEFINE_SIZE_STATIC (3 + F2DOT14::static_size);
 };
 
 template <template<typename> class Var>
 struct PaintLinearGradient
 {
   void closurev1 (hb_colrv1_closure_context_t* c) const
-  {
-    for (const auto &stop : (this+colorLine).stops.iter ())
-      c->add_palette_index (stop.color.paletteIndex);
-  }
+  { (this+colorLine).closurev1 (c); }
 
   bool subset (hb_subset_context_t *c) const
   {
@@ -430,19 +447,22 @@
   HBUINT8			format; /* format = 4(noVar) or 5 (Var) */
   Offset24To<ColorLine<Var>>	colorLine; /* Offset (from beginning of PaintLinearGradient
                                             * table) to ColorLine subtable. */
-  Var<FWORD>			x0;
-  Var<FWORD>			y0;
-  Var<FWORD>			x1;
-  Var<FWORD>			y1;
-  Var<FWORD>			x2;
-  Var<FWORD>			y2;
+  FWORD			x0;
+  FWORD			y0;
+  FWORD			x1;
+  FWORD			y1;
+  FWORD			x2;
+  FWORD			y2;
   public:
-  DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
+  DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size);
 };
 
 template <template<typename> class Var>
 struct PaintRadialGradient
 {
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  { (this+colorLine).closurev1 (c); }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
@@ -452,12 +472,6 @@
     return_trace (out->colorLine.serialize_subset (c, colorLine, this));
   }
 
-  void closurev1 (hb_colrv1_closure_context_t* c) const
-  {
-    for (const auto &stop : (this+colorLine).stops.iter ())
-      c->add_palette_index (stop.color.paletteIndex);
-  }
-
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -467,19 +481,22 @@
   HBUINT8			format; /* format = 6(noVar) or 7 (Var) */
   Offset24To<ColorLine<Var>>	colorLine; /* Offset (from beginning of PaintRadialGradient
                                             * table) to ColorLine subtable. */
-  Var<FWORD>			x0;
-  Var<FWORD>			y0;
-  Var<UFWORD>			radius0;
-  Var<FWORD>			x1;
-  Var<FWORD>			y1;
-  Var<UFWORD>			radius1;
+  FWORD			x0;
+  FWORD			y0;
+  UFWORD		radius0;
+  FWORD			x1;
+  FWORD			y1;
+  UFWORD		radius1;
   public:
-  DEFINE_SIZE_STATIC (4 + 6 * Var<FWORD>::static_size);
+  DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size);
 };
 
 template <template<typename> class Var>
 struct PaintSweepGradient
 {
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  { (this+colorLine).closurev1 (c); }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
@@ -489,12 +506,6 @@
     return_trace (out->colorLine.serialize_subset (c, colorLine, this));
   }
 
-  void closurev1 (hb_colrv1_closure_context_t* c) const
-  {
-    for (const auto &stop : (this+colorLine).stops.iter ())
-      c->add_palette_index (stop.color.paletteIndex);
-  }
-
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -504,12 +515,12 @@
   HBUINT8			format; /* format = 8(noVar) or 9 (Var) */
   Offset24To<ColorLine<Var>>	colorLine; /* Offset (from beginning of PaintSweepGradient
                                             * table) to ColorLine subtable. */
-  Var<FWORD>			centerX;
-  Var<FWORD>			centerY;
-  Var<HBFixed>			startAngle;
-  Var<HBFixed>			endAngle;
+  FWORD			centerX;
+  FWORD			centerY;
+  F2DOT14		startAngle;
+  F2DOT14		endAngle;
   public:
-  DEFINE_SIZE_STATIC (2 * Var<FWORD>::static_size + 2 * Var<HBFixed>::static_size);
+  DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size + 2 * F2DOT14::static_size);
 };
 
 struct Paint;
@@ -580,24 +591,25 @@
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (this);
     if (unlikely (!out)) return_trace (false);
-
+    if (!out->transform.serialize_copy (c->serializer, transform, this)) return_trace (false);
     return_trace (out->src.serialize_subset (c, src, this));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && src.sanitize (c, this));
+    return_trace (c->check_struct (this) &&
+                  src.sanitize (c, this) &&
+                  transform.sanitize (c, this));
   }
 
-  HBUINT8		format; /* format = 12(noVar) or 13 (Var) */
-  Offset24To<Paint>	src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */
-  Affine2x3<Var>	transform;
+  HBUINT8			format; /* format = 12(noVar) or 13 (Var) */
+  Offset24To<Paint>		src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */
+  Offset24To<Var<Affine2x3>>	transform;
   public:
-  DEFINE_SIZE_STATIC (4 + Affine2x3<Var>::static_size);
+  DEFINE_SIZE_STATIC (7);
 };
 
-template <template<typename> class Var>
 struct PaintTranslate
 {
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
@@ -619,14 +631,13 @@
 
   HBUINT8		format; /* format = 14(noVar) or 15 (Var) */
   Offset24To<Paint>	src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */
-  Var<HBFixed>		dx;
-  Var<HBFixed>		dy;
+  FWORD		dx;
+  FWORD		dy;
   public:
-  DEFINE_SIZE_STATIC (4 + Var<HBFixed>::static_size);
+  DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size);
 };
 
-template <template<typename> class Var>
-struct PaintRotate
+struct PaintScale
 {
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
@@ -646,15 +657,150 @@
   }
 
   HBUINT8		format; /* format = 16 (noVar) or 17(Var) */
-  Offset24To<Paint>	src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */
-  Var<HBFixed>		angle;
-  Var<HBFixed>		centerX;
-  Var<HBFixed>		centerY;
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintScale table) to Paint subtable. */
+  F2DOT14		scaleX;
+  F2DOT14		scaleY;
   public:
-  DEFINE_SIZE_STATIC (4 + 3 * Var<HBFixed>::static_size);
+  DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size);
 };
 
-template <template<typename> class Var>
+struct PaintScaleAroundCenter
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 18 (noVar) or 19(Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintScaleAroundCenter table) to Paint subtable. */
+  F2DOT14	scaleX;
+  F2DOT14	scaleY;
+  FWORD		centerX;
+  FWORD		centerY;
+  public:
+  DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size);
+};
+
+struct PaintScaleUniform
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 20 (noVar) or 21(Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintScaleUniform table) to Paint subtable. */
+  F2DOT14		scale;
+  public:
+  DEFINE_SIZE_STATIC (4 + F2DOT14::static_size);
+};
+
+struct PaintScaleUniformAroundCenter
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 22 (noVar) or 23(Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintScaleUniformAroundCenter table) to Paint subtable. */
+  F2DOT14	scale;
+  FWORD		centerX;
+  FWORD		centerY;
+  public:
+  DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size);
+};
+
+struct PaintRotate
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 24 (noVar) or 25(Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */
+  F2DOT14		angle;
+  public:
+  DEFINE_SIZE_STATIC (4 + F2DOT14::static_size);
+};
+
+struct PaintRotateAroundCenter
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 26 (noVar) or 27(Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintRotateAroundCenter table) to Paint subtable. */
+  F2DOT14	angle;
+  FWORD		centerX;
+  FWORD		centerY;
+  public:
+  DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size);
+};
+
 struct PaintSkew
 {
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
@@ -674,14 +820,41 @@
     return_trace (c->check_struct (this) && src.sanitize (c, this));
   }
 
-  HBUINT8		format; /* format = 18(noVar) or 19 (Var) */
+  HBUINT8		format; /* format = 28(noVar) or 29 (Var) */
   Offset24To<Paint>	src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */
-  Var<HBFixed>		xSkewAngle;
-  Var<HBFixed>		ySkewAngle;
-  Var<HBFixed>		centerX;
-  Var<HBFixed>		centerY;
+  F2DOT14		xSkewAngle;
+  F2DOT14		ySkewAngle;
   public:
-  DEFINE_SIZE_STATIC (4 + 4 * Var<HBFixed>::static_size);
+  DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size);
+};
+
+struct PaintSkewAroundCenter
+{
+  HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->src.serialize_subset (c, src, this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && src.sanitize (c, this));
+  }
+
+  HBUINT8		format; /* format = 30(noVar) or 31 (Var) */
+  Offset24To<Paint>	src; /* Offset (from beginning of PaintSkewAroundCenter table) to Paint subtable. */
+  F2DOT14	xSkewAngle;
+  F2DOT14	ySkewAngle;
+  FWORD		centerX;
+  FWORD		centerY;
+  public:
+  DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size);
 };
 
 struct PaintComposite
@@ -706,7 +879,7 @@
                   backdrop.sanitize (c, this));
   }
 
-  HBUINT8		format; /* format = 20 */
+  HBUINT8		format; /* format = 32 */
   Offset24To<Paint>	src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */
   CompositeMode		mode;   /* If mode is unrecognized use COMPOSITE_CLEAR */
   Offset24To<Paint>	backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */
@@ -714,6 +887,175 @@
   DEFINE_SIZE_STATIC (8);
 };
 
+struct ClipBoxFormat1
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT8	format; /* format = 1(noVar) or 2(Var)*/
+  FWORD		xMin;
+  FWORD		yMin;
+  FWORD		xMax;
+  FWORD		yMax;
+  public:
+  DEFINE_SIZE_STATIC (1 + 4 * FWORD::static_size);
+};
+
+struct ClipBoxFormat2 : Variable<ClipBoxFormat1> {};
+
+struct ClipBox
+{
+  ClipBox* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    switch (u.format) {
+    case 1: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format1)));
+    case 2: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format2)));
+    default:return_trace (nullptr);
+    }
+  }
+
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT8		format;         /* Format identifier */
+  ClipBoxFormat1	format1;
+  ClipBoxFormat2	format2;
+  } u;
+};
+
+struct ClipRecord
+{
+  ClipRecord* copy (hb_serialize_context_t *c, const void *base) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->embed (this);
+    if (unlikely (!out)) return_trace (nullptr);
+    if (!out->clipBox.serialize_copy (c, clipBox, base)) return_trace (nullptr);
+    return_trace (out);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && clipBox.sanitize (c, base));
+  }
+
+  public:
+  HBUINT16		startGlyphID;  // first gid clip applies to
+  HBUINT16		endGlyphID;    // last gid clip applies to, inclusive
+  Offset24To<ClipBox>	clipBox;   // Box or VarBox
+  public:
+  DEFINE_SIZE_STATIC (7);
+};
+
+struct ClipList
+{
+  unsigned serialize_clip_records (hb_serialize_context_t *c,
+                                   const hb_set_t& gids,
+                                   const hb_map_t& gid_offset_map) const
+  {
+    TRACE_SERIALIZE (this);
+    unsigned count  = 0;
+
+    hb_codepoint_t start_gid= gids.get_min ();
+    hb_codepoint_t prev_gid = start_gid;
+
+    unsigned offset = gid_offset_map.get (start_gid);
+    unsigned prev_offset = offset;
+    for (const hb_codepoint_t _ : gids.iter ())
+    {
+      if (_ == start_gid) continue;
+      
+      offset = gid_offset_map.get (_);
+      if (_ == prev_gid + 1 &&  offset == prev_offset)
+      {
+        prev_gid = _;
+        continue;
+      }
+
+      ClipRecord record;
+      record.startGlyphID = start_gid;
+      record.endGlyphID = prev_gid;
+      record.clipBox = prev_offset;
+
+      if (!c->copy (record, this)) return_trace (0);
+      count++;
+
+      start_gid = _;
+      prev_gid = _;
+      prev_offset = offset;
+    }
+
+    //last one
+    {
+      ClipRecord record;
+      record.startGlyphID = start_gid;
+      record.endGlyphID = prev_gid;
+      record.clipBox = prev_offset;
+      if (!c->copy (record, this)) return_trace (0);
+      count++;
+    }
+    return_trace (count);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    if (!c->serializer->check_assign (out->format, format, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
+
+    const hb_set_t& glyphset = *c->plan->_glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    
+    hb_map_t new_gid_offset_map;
+    hb_set_t new_gids;
+    for (const ClipRecord& record : clips.iter ())
+    {
+      unsigned start_gid = record.startGlyphID;
+      unsigned end_gid = record.endGlyphID;
+      for (unsigned gid = start_gid; gid <= end_gid; gid++)
+      {
+        if (!glyphset.has (gid) || !glyph_map.has (gid)) continue;
+        unsigned new_gid = glyph_map.get (gid);
+        new_gid_offset_map.set (new_gid, record.clipBox);
+        new_gids.add (new_gid);
+      }
+    }
+
+    unsigned count = serialize_clip_records (c->serializer, new_gids, new_gid_offset_map);
+    if (!count) return_trace (false);
+    return_trace (c->serializer->check_assign (out->clips.len, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && clips.sanitize (c, this));
+  }
+
+  HBUINT8			format;  // Set to 1.
+  Array32Of<ClipRecord>		clips;  // Clip records, sorted by startGlyphID
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (5, clips);
+};
+
 struct Paint
 {
   template <typename context_t, typename ...Ts>
@@ -742,37 +1084,61 @@
     case 18: return_trace (c->dispatch (u.paintformat18, hb_forward<Ts> (ds)...));
     case 19: return_trace (c->dispatch (u.paintformat19, hb_forward<Ts> (ds)...));
     case 20: return_trace (c->dispatch (u.paintformat20, hb_forward<Ts> (ds)...));
+    case 21: return_trace (c->dispatch (u.paintformat21, hb_forward<Ts> (ds)...));
+    case 22: return_trace (c->dispatch (u.paintformat22, hb_forward<Ts> (ds)...));
+    case 23: return_trace (c->dispatch (u.paintformat23, hb_forward<Ts> (ds)...));
+    case 24: return_trace (c->dispatch (u.paintformat24, hb_forward<Ts> (ds)...));
+    case 25: return_trace (c->dispatch (u.paintformat25, hb_forward<Ts> (ds)...));
+    case 26: return_trace (c->dispatch (u.paintformat26, hb_forward<Ts> (ds)...));
+    case 27: return_trace (c->dispatch (u.paintformat27, hb_forward<Ts> (ds)...));
+    case 28: return_trace (c->dispatch (u.paintformat28, hb_forward<Ts> (ds)...));
+    case 29: return_trace (c->dispatch (u.paintformat29, hb_forward<Ts> (ds)...));
+    case 30: return_trace (c->dispatch (u.paintformat30, hb_forward<Ts> (ds)...));
+    case 31: return_trace (c->dispatch (u.paintformat31, hb_forward<Ts> (ds)...));
+    case 32: return_trace (c->dispatch (u.paintformat32, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
 
   protected:
   union {
-  HBUINT8				format;
-  PaintColrLayers			paintformat1;
-  PaintSolid<NoVariable>		paintformat2;
-  PaintSolid<Variable>			paintformat3;
-  PaintLinearGradient<NoVariable>	paintformat4;
-  PaintLinearGradient<Variable>		paintformat5;
-  PaintRadialGradient<NoVariable>	paintformat6;
-  PaintRadialGradient<Variable>		paintformat7;
-  PaintSweepGradient<NoVariable>	paintformat8;
-  PaintSweepGradient<Variable>		paintformat9;
-  PaintGlyph				paintformat10;
-  PaintColrGlyph			paintformat11;
-  PaintTransform<NoVariable>		paintformat12;
-  PaintTransform<Variable>		paintformat13;
-  PaintTranslate<NoVariable>		paintformat14;
-  PaintTranslate<Variable>		paintformat15;
-  PaintRotate<NoVariable>		paintformat16;
-  PaintRotate<Variable>			paintformat17;
-  PaintSkew<NoVariable>			paintformat18;
-  PaintSkew<Variable>			paintformat19;
-  PaintComposite			paintformat20;
+  HBUINT8					format;
+  PaintColrLayers				paintformat1;
+  PaintSolid					paintformat2;
+  Variable<PaintSolid>				paintformat3;
+  PaintLinearGradient<NoVariable>		paintformat4;
+  Variable<PaintLinearGradient<Variable>>	paintformat5;
+  PaintRadialGradient<NoVariable>		paintformat6;
+  Variable<PaintRadialGradient<Variable>>	paintformat7;
+  PaintSweepGradient<NoVariable>		paintformat8;
+  Variable<PaintSweepGradient<Variable>>	paintformat9;
+  PaintGlyph					paintformat10;
+  PaintColrGlyph				paintformat11;
+  PaintTransform<NoVariable>			paintformat12;
+  PaintTransform<Variable>			paintformat13;
+  PaintTranslate				paintformat14;
+  Variable<PaintTranslate>			paintformat15;
+  PaintScale					paintformat16;
+  Variable<PaintScale>				paintformat17;
+  PaintScaleAroundCenter			paintformat18;
+  Variable<PaintScaleAroundCenter>		paintformat19;
+  PaintScaleUniform				paintformat20;
+  Variable<PaintScaleUniform>			paintformat21;
+  PaintScaleUniformAroundCenter			paintformat22;
+  Variable<PaintScaleUniformAroundCenter>	paintformat23;
+  PaintRotate					paintformat24;
+  Variable<PaintRotate>				paintformat25;
+  PaintRotateAroundCenter			paintformat26;
+  Variable<PaintRotateAroundCenter>		paintformat27;
+  PaintSkew					paintformat28;
+  Variable<PaintSkew>				paintformat29;
+  PaintSkewAroundCenter				paintformat30;
+  Variable<PaintSkewAroundCenter>		paintformat31;
+  PaintComposite				paintformat32;
   } u;
 };
 
-struct BaseGlyphV1Record
+struct BaseGlyphPaintRecord
 {
   int cmp (hb_codepoint_t g) const
   { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
@@ -798,13 +1164,13 @@
 
   public:
   HBGlyphID16		glyphId;    /* Glyph ID of reference glyph */
-  Offset32To<Paint>	paint;      /* Offset (from beginning of BaseGlyphV1Record array) to Paint,
+  Offset32To<Paint>	paint;      /* Offset (from beginning of BaseGlyphPaintRecord array) to Paint,
                                      * Typically PaintColrLayers */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
-struct BaseGlyphV1List : SortedArray32Of<BaseGlyphV1Record>
+struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
 {
   bool subset (hb_subset_context_t *c) const
   {
@@ -828,11 +1194,11 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (SortedArray32Of<BaseGlyphV1Record>::sanitize (c, this));
+    return_trace (SortedArray32Of<BaseGlyphPaintRecord>::sanitize (c, this));
   }
 };
 
-struct LayerV1List : Array32OfOffset32To<Paint>
+struct LayerList : Array32OfOffset32To<Paint>
 {
   const Paint& get_paint (unsigned i) const
   { return this+(*this)[i]; }
@@ -952,24 +1318,24 @@
     hb_set_t visited_glyphs;
 
     hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices);
-    const BaseGlyphV1List &baseglyphV1_records = this+baseGlyphsV1List;
+    const BaseGlyphList &baseglyph_paintrecords = this+baseGlyphList;
 
-    for (const BaseGlyphV1Record &baseglyphV1record: baseglyphV1_records.iter ())
+    for (const BaseGlyphPaintRecord &baseglyph_paintrecord: baseglyph_paintrecords.iter ())
     {
-      unsigned gid = baseglyphV1record.glyphId;
+      unsigned gid = baseglyph_paintrecord.glyphId;
       if (!glyphset->has (gid)) continue;
 
-      const Paint &paint = &baseglyphV1_records+baseglyphV1record.paint;
+      const Paint &paint = &baseglyph_paintrecords+baseglyph_paintrecord.paint;
       paint.dispatch (&c);
     }
     hb_set_union (glyphset, &visited_glyphs);
   }
 
-  const LayerV1List& get_layerV1List () const
-  { return (this+layersV1); }
+  const LayerList& get_layerList () const
+  { return (this+layerList); }
 
-  const BaseGlyphV1List& get_baseglyphV1List () const
-  { return (this+baseGlyphsV1List); }
+  const BaseGlyphList& get_baseglyphList () const
+  { return (this+baseGlyphList); }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -979,8 +1345,10 @@
                   (this+layersZ).sanitize (c, numLayers) &&
                   (version == 0 ||
 		   (COLRV1_ENABLE_SUBSETTING && version == 1 &&
-		    baseGlyphsV1List.sanitize (c, this) &&
-		    layersV1.sanitize (c, this) &&
+		    baseGlyphList.sanitize (c, this) &&
+		    layerList.sanitize (c, this) &&
+		    clipList.sanitize (c, this) &&
+		    varIdxMap.sanitize (c, this) &&
 		    varStore.sanitize (c, this))));
   }
 
@@ -996,19 +1364,17 @@
     if (unlikely (base_it.len () != layer_it.len ()))
       return_trace (false);
 
-    if (unlikely (!c->extend_min (this))) return_trace (false);
     this->version = version;
     numLayers = 0;
     numBaseGlyphs = base_it.len ();
-    if (base_it.len () == 0)
+    if (numBaseGlyphs == 0)
     {
       baseGlyphsZ = 0;
       layersZ = 0;
       return_trace (true);
     }
-    baseGlyphsZ = COLR::min_size;
-    layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size;
 
+    c->push ();
     for (const hb_item_type<BaseIterator> _ : + base_it.iter ())
     {
       auto* record = c->embed (_);
@@ -1016,10 +1382,14 @@
       record->firstLayerIdx = numLayers;
       numLayers += record->numLayers;
     }
+    c->add_link (baseGlyphsZ, c->pop_pack ());
 
+    c->push ();
     for (const hb_item_type<LayerIterator>& _ : + layer_it.iter ())
       _.as_array ().copy (c);
 
+    c->add_link (layersZ, c->pop_pack ());
+
     return_trace (true);
   }
 
@@ -1033,9 +1403,9 @@
     return record;
   }
 
-  const BaseGlyphV1Record* get_base_glyphV1_record (hb_codepoint_t gid) const
+  const BaseGlyphPaintRecord* get_base_glyph_paintrecord (hb_codepoint_t gid) const
   {
-    const BaseGlyphV1Record* record = &(this+baseGlyphsV1List).bsearch ((unsigned) gid);
+    const BaseGlyphPaintRecord* record = &(this+baseGlyphList).bsearch ((unsigned) gid);
     if ((record && (hb_codepoint_t) record->glyphId != gid))
       record = nullptr;
     return record;
@@ -1101,23 +1471,26 @@
       return_trace (false);
 
     COLR *colr_prime = c->serializer->start_embed<COLR> ();
-    bool ret = colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it);
+    if (unlikely (!c->serializer->extend_min (colr_prime)))  return_trace (false);
 
-    if (version == 0) return_trace (ret);
+    if (version == 0)
+    return_trace (colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it));
+
     auto snap = c->serializer->snapshot ();
-    if (!c->serializer->allocate_size<void> (3 * HBUINT32::static_size)) return_trace (false);
-    if (!colr_prime->baseGlyphsV1List.serialize_subset (c, baseGlyphsV1List, this))
+    if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false);
+    if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this))
     {
       if (c->serializer->in_error ()) return_trace (false);
       //no more COLRv1 glyphs: downgrade to version 0
       c->serializer->revert (snap);
-      colr_prime->version = 0;
-      return_trace (true);
+      return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
     }
 
-    if (!colr_prime->layersV1.serialize_subset (c, layersV1, this)) return_trace (false);
+    if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
 
-    colr_prime->varStore = 0;
+    colr_prime->layerList.serialize_subset (c, layerList, this);
+    colr_prime->clipList.serialize_subset (c, clipList, this);
+    colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
     //TODO: subset varStore once it's implemented in fonttools
     return_trace (true);
   }
@@ -1131,8 +1504,10 @@
 		layersZ;	/* Offset to Layer Records. */
   HBUINT16	numLayers;	/* Number of Layer Records. */
   // Version-1 additions
-  Offset32To<BaseGlyphV1List>		baseGlyphsV1List;
-  Offset32To<LayerV1List>		layersV1;
+  Offset32To<BaseGlyphList>		baseGlyphList;
+  Offset32To<LayerList>			layerList;
+  Offset32To<ClipList>			clipList;   // Offset to ClipList table (may be NULL)
+  Offset32To<DeltaSetIndexMap>		varIdxMap;  // Offset to DeltaSetIndexMap table (may be NULL)
   Offset32To<VariationStore>		varStore;
   public:
   DEFINE_SIZE_MIN (14);
diff --git a/src/hb-ot-color-colrv1-closure.hh b/src/hb-ot-color-colrv1-closure.hh
index 4124efe..ca85ba6 100644
--- a/src/hb-ot-color-colrv1-closure.hh
+++ b/src/hb-ot-color-colrv1-closure.hh
@@ -40,7 +40,7 @@
 HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const
 {
   c->add_layer_indices (firstLayerIndex, numLayers);
-  const LayerV1List &paint_offset_lists = c->get_colr_table ()->get_layerV1List ();
+  const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
   for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
   {
     const Paint &paint = hb_addressof (paint_offset_lists) + paint_offset_lists[i];
@@ -57,37 +57,44 @@
 HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
 {
   const COLR *colr_table = c->get_colr_table ();
-  const BaseGlyphV1Record* baseglyphV1_record = colr_table->get_base_glyphV1_record (gid);
-  if (!baseglyphV1_record) return;
+  const BaseGlyphPaintRecord* baseglyph_paintrecord = colr_table->get_base_glyph_paintrecord (gid);
+  if (!baseglyph_paintrecord) return;
   c->add_glyph (gid);
 
-  const BaseGlyphV1List &baseglyphV1_list = colr_table->get_baseglyphV1List ();
-  (&baseglyphV1_list+baseglyphV1_record->paint).dispatch (c);
+  const BaseGlyphList &baseglyph_list = colr_table->get_baseglyphList ();
+  (&baseglyph_list+baseglyph_paintrecord->paint).dispatch (c);
 }
 
 template <template<typename> class Var>
 HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{
-  (this+src).dispatch (c);
-}
+{ (this+src).dispatch (c); }
 
-template <template<typename> class Var>
-HB_INTERNAL void PaintTranslate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{
-  (this+src).dispatch (c);
-}
+HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
 
-template <template<typename> class Var>
-HB_INTERNAL void PaintRotate<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{
-  (this+src).dispatch (c);
-}
+HB_INTERNAL void PaintScale::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
 
-template <template<typename> class Var>
-HB_INTERNAL void PaintSkew<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{
-  (this+src).dispatch (c);
-}
+HB_INTERNAL void PaintScaleAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintScaleUniform::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintScaleUniformAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintRotateAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
+
+HB_INTERNAL void PaintSkewAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+{ (this+src).dispatch (c); }
 
 HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
 {
diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 517e603..6b419ea 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -1118,7 +1118,7 @@
       while (it)
       {
         auto item = *(it++);
-        operation_count +=
+        operation_count =
             add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
       }
 
diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh
index ac588e3..20991aa 100644
--- a/src/hb-ot-head-table.hh
+++ b/src/hb-ot-head-table.hh
@@ -72,12 +72,14 @@
     UNDERLINE	= 1u<<2,
     OUTLINE	= 1u<<3,
     SHADOW	= 1u<<4,
-    CONDENSED	= 1u<<5
+    CONDENSED	= 1u<<5,
+    EXPANDED	= 1u<<6,
   };
 
   bool is_bold () const      { return macStyle & BOLD; }
   bool is_italic () const    { return macStyle & ITALIC; }
   bool is_condensed () const { return macStyle & CONDENSED; }
+  bool is_expanded () const  { return macStyle & EXPANDED; }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 1e53920..ac8f6ea 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1220,9 +1220,9 @@
 						record_size);
     if (record)
     {
-      /* Note the intentional use of "|" instead of short-circuit "||". */
-      if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
-	  valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
+      bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
+      bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+      if (applied_first || applied_second)
 	buffer->unsafe_to_break (buffer->idx, pos + 1);
       if (len2)
 	pos++;
@@ -1560,9 +1560,9 @@
     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
 
     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-    /* Note the intentional use of "|" instead of short-circuit "||". */
-    if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) |
-	valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]))
+    bool applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
+    bool applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+    if (applied_first || applied_second)
       buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
 
     buffer->idx = skippy_iter.idx;
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index a1cd274..9b958a8 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -1210,15 +1210,14 @@
 
 struct LookupRecord
 {
-  LookupRecord* copy (hb_serialize_context_t *c,
-		      const hb_map_t         *lookup_map) const
+  bool serialize (hb_serialize_context_t *c,
+		  const hb_map_t         *lookup_map) const
   {
     TRACE_SERIALIZE (this);
     auto *out = c->embed (*this);
-    if (unlikely (!out)) return_trace (nullptr);
+    if (unlikely (!out)) return_trace (false);
 
-    out->lookupListIndex = hb_map_get (lookup_map, lookupListIndex);
-    return_trace (out);
+    return_trace (c->check_assign (out->lookupListIndex, lookup_map->get (lookupListIndex), HB_SERIALIZE_ERROR_INT_OVERFLOW));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -1235,6 +1234,24 @@
   DEFINE_SIZE_STATIC (4);
 };
 
+static unsigned serialize_lookuprecord_array (hb_serialize_context_t *c,
+					      const hb_array_t<const LookupRecord> lookupRecords,
+					      const hb_map_t *lookup_map)
+{
+  unsigned count = 0;
+  for (const LookupRecord& r : lookupRecords)
+  {
+    if (!lookup_map->has (r.lookupListIndex))
+      continue;
+
+    if (!r.serialize (c, lookup_map))
+      return 0;
+
+    count++;
+  }
+  return count;
+}
+
 enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 };
 
 static void context_closure_recurse_lookups (hb_closure_context_t *c,
@@ -1605,8 +1622,6 @@
     if (unlikely (!c->extend_min (out))) return_trace (false);
 
     out->inputCount = inputCount;
-    out->lookupCount = lookupCount;
-
     const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
     for (const auto org : input)
     {
@@ -1617,17 +1632,9 @@
 
     const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
 						       (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
-    for (unsigned i = 0; i < (unsigned) lookupCount; i++)
-    {
-      if (!lookup_map->has (lookupRecord[i].lookupListIndex))
-      {
-        out->lookupCount--;
-        continue;
-      }
-      c->copy (lookupRecord[i], lookup_map);
-    }
-
-    return_trace (true);
+   
+    unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (lookupCount), lookup_map);
+    return_trace (c->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
   }
 
   bool subset (hb_subset_context_t *c,
@@ -2226,7 +2233,6 @@
 
     out->format = format;
     out->glyphCount = glyphCount;
-    out->lookupCount = lookupCount;
 
     auto coverages = coverageZ.as_array (glyphCount);
 
@@ -2238,19 +2244,12 @@
       if (!o->serialize_subset (c, offset, this)) return_trace (false);
     }
 
-    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    const UnsizedArrayOf<LookupRecord>& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount));
     const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
-    for (unsigned i = 0; i < (unsigned) lookupCount; i++)
-    {
-      if (!lookup_map->has (lookupRecord[i].lookupListIndex))
-      {
-        out->lookupCount--;
-        continue;
-      }
-      c->serializer->copy (lookupRecord[i], lookup_map);
-    }
+    
 
-    return_trace (true);
+    unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (lookupCount), lookup_map);
+    return_trace (c->serializer->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -2539,15 +2538,15 @@
       c->copy ((HBUINT16) g);
   }
 
-  ChainRule* copy (hb_serialize_context_t *c,
-		   const hb_map_t *lookup_map,
-		   const hb_map_t *backtrack_map,
-		   const hb_map_t *input_map = nullptr,
-		   const hb_map_t *lookahead_map = nullptr) const
+  bool serialize (hb_serialize_context_t *c,
+		  const hb_map_t *lookup_map,
+		  const hb_map_t *backtrack_map,
+		  const hb_map_t *input_map = nullptr,
+		  const hb_map_t *lookahead_map = nullptr) const
   {
     TRACE_SERIALIZE (this);
     auto *out = c->start_embed (this);
-    if (unlikely (!out)) return_trace (nullptr);
+    if (unlikely (!out)) return_trace (false);
 
     const hb_map_t *mapping = backtrack_map;
     serialize_array (c, backtrack.len, + backtrack.iter ()
@@ -2566,19 +2565,10 @@
     const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
 
     HBUINT16* lookupCount = c->embed (&(lookupRecord.len));
-    if (!lookupCount) return_trace (nullptr);
+    if (!lookupCount) return_trace (false);
 
-    for (unsigned i = 0; i < lookupRecord.len; i++)
-    {
-      if (!lookup_map->has (lookupRecord[i].lookupListIndex))
-      {
-        (*lookupCount)--;
-        continue;
-      }
-      if (!c->copy (lookupRecord[i], lookup_map)) return_trace (nullptr);
-    }
-
-    return_trace (out);
+    unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (), lookup_map);
+    return_trace (c->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
   }
 
   bool subset (hb_subset_context_t *c,
@@ -2600,7 +2590,7 @@
 	  !hb_all (lookahead, glyphset))
 	return_trace (false);
 
-      copy (c->serializer, lookup_map, c->plan->glyph_map);
+      serialize (c->serializer, lookup_map, c->plan->glyph_map);
     }
     else
     {
@@ -2609,7 +2599,7 @@
 	  !hb_all (lookahead, lookahead_map))
 	return_trace (false);
 
-      copy (c->serializer, lookup_map, backtrack_map, input_map, lookahead_map);
+      serialize (c->serializer, lookup_map, backtrack_map, input_map, lookahead_map);
     }
 
     return_trace (true);
@@ -3318,22 +3308,12 @@
 
     const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
     const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
-    hb_set_t lookup_indices;
-    for (unsigned i = 0; i < (unsigned) lookupRecord.len; i++)
-      if (lookup_map->has (lookupRecord[i].lookupListIndex))
-        lookup_indices.add (i);
+  
+    HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookupRecord.len);
+    if (!lookupCount) return_trace (false);
 
-    HBUINT16 lookupCount;
-    lookupCount = lookup_indices.get_population ();
-    if (!c->serializer->copy (lookupCount)) return_trace (false);
-
-    for (unsigned i : lookup_indices.iter ())
-    {
-      if (!c->serializer->copy (lookupRecord[i], lookup_map))
-        return_trace (false);
-    }
-
-    return_trace (true);
+    unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (), lookup_map);
+    return_trace (c->serializer->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh
index bcc014e..b15d053 100644
--- a/src/hb-ot-layout.hh
+++ b/src/hb-ot-layout.hh
@@ -187,7 +187,7 @@
  * - General_Category: 5 bits.
  * - A bit each for:
  *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
- *   * Whether it's one of the three Mongolian Free Variation Selectors,
+ *   * Whether it's one of the four Mongolian Free Variation Selectors,
  *     CGJ, or other characters that are hidden but should not be ignored
  *     like most other Default_Ignorable()s do during matching.
  *   * Whether it's a grapheme continuation.
@@ -202,7 +202,7 @@
 enum hb_unicode_props_flags_t {
   UPROPS_MASK_GEN_CAT	= 0x001Fu,
   UPROPS_MASK_IGNORABLE	= 0x0020u,
-  UPROPS_MASK_HIDDEN	= 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, or TAG characters */
+  UPROPS_MASK_HIDDEN	= 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters */
   UPROPS_MASK_CONTINUATION=0x0080u,
 
   /* If GEN_CAT=FORMAT, top byte masks: */
@@ -236,7 +236,7 @@
        * FVSes are GC=Mn, we have use a separate bit to remember them.
        * Fixes:
        * https://github.com/harfbuzz/harfbuzz/issues/234 */
-      else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
+      else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x180Bu, 0x180Du, 0x180Fu, 0x180Fu))) props |= UPROPS_MASK_HIDDEN;
       /* TAG characters need similar treatment. Fixes:
        * https://github.com/harfbuzz/harfbuzz/issues/463 */
       else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh
index f9c5a83..c2e365d 100644
--- a/src/hb-ot-math-table.hh
+++ b/src/hb-ot-math-table.hh
@@ -836,12 +836,16 @@
   void collect_coverage_and_indices (hb_sorted_vector_t<hb_codepoint_t>& new_coverage,
                                      const Offset16To<Coverage>& coverage,
                                      unsigned i,
+                                     unsigned end_index,
                                      hb_set_t& indices,
                                      const hb_set_t& glyphset,
                                      const hb_map_t& glyph_map) const
   {
+    if (!coverage) return;
+
     for (const auto _ : (this+coverage).iter ())
     {
+      if (i >= end_index) return;
       if (glyphset.has (_))
       {
         unsigned new_gid = glyph_map.get (_);
@@ -866,8 +870,8 @@
     hb_sorted_vector_t<hb_codepoint_t> new_vert_coverage;
     hb_sorted_vector_t<hb_codepoint_t> new_hori_coverage;
     hb_set_t indices;
-    collect_coverage_and_indices (new_vert_coverage, vertGlyphCoverage, 0, indices, glyphset, glyph_map);
-    collect_coverage_and_indices (new_hori_coverage, horizGlyphCoverage, vertGlyphCount, indices, glyphset, glyph_map);
+    collect_coverage_and_indices (new_vert_coverage, vertGlyphCoverage, 0, vertGlyphCount, indices, glyphset, glyph_map);
+    collect_coverage_and_indices (new_hori_coverage, horizGlyphCoverage, vertGlyphCount, vertGlyphCount + horizGlyphCount, indices, glyphset, glyph_map);
     
     if (!c->serializer->check_assign (out->vertGlyphCount, new_vert_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
       return_trace (false);
diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
index 1f8c141..222c5d6 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -349,7 +349,7 @@
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 1; i < count; i++)
-    if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du)))
+    if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du, 0x180Fu, 0x180Fu)))
       info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
 }
 
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 0983a32..4a8781c 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -202,9 +202,6 @@
   for (; i < INDIC_NUM_FEATURES; i++)
     map->add_feature (indic_features[i]);
 
-  map->enable_feature (HB_TAG('c','a','l','t'));
-  map->enable_feature (HB_TAG('c','l','i','g'));
-
   map->add_gsub_pause (_hb_clear_syllables);
 }
 
diff --git a/src/hb-ot-shape-complex-use-machine.hh b/src/hb-ot-shape-complex-use-machine.hh
index bb046a7..c3920b2 100644
--- a/src/hb-ot-shape-complex-use-machine.hh
+++ b/src/hb-ot-shape-complex-use-machine.hh
@@ -41,7 +41,6 @@
 #define USE(Cat) use_syllable_machine_ex_##Cat
 
 enum use_syllable_type_t {
-  use_independent_cluster,
   use_virama_terminated_cluster,
   use_sakot_terminated_cluster,
   use_standard_cluster,
@@ -54,8 +53,9 @@
 };
 
 
-#line 58 "hb-ot-shape-complex-use-machine.hh"
+#line 57 "hb-ot-shape-complex-use-machine.hh"
 #define use_syllable_machine_ex_B 1u
+#define use_syllable_machine_ex_CGJ 6u
 #define use_syllable_machine_ex_CMAbv 31u
 #define use_syllable_machine_ex_CMBlw 32u
 #define use_syllable_machine_ex_CS 43u
@@ -78,7 +78,6 @@
 #define use_syllable_machine_ex_N 4u
 #define use_syllable_machine_ex_O 0u
 #define use_syllable_machine_ex_R 18u
-#define use_syllable_machine_ex_S 19u
 #define use_syllable_machine_ex_SB 51u
 #define use_syllable_machine_ex_SE 52u
 #define use_syllable_machine_ex_SMAbv 41u
@@ -96,280 +95,278 @@
 #define use_syllable_machine_ex_ZWNJ 14u
 
 
-#line 100 "hb-ot-shape-complex-use-machine.hh"
+#line 99 "hb-ot-shape-complex-use-machine.hh"
 static const unsigned char _use_syllable_machine_trans_keys[] = {
-	1u, 1u, 1u, 1u, 0u, 51u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u, 
+	0u, 51u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u, 
 	24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 
 	1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 
-	11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u, 
-	22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 
-	24u, 48u, 24u, 48u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 
-	22u, 48u, 11u, 48u, 1u, 48u, 1u, 1u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u, 
-	41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0
+	11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 
+	23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 
+	24u, 48u, 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 
+	22u, 48u, 11u, 48u, 1u, 48u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u, 41u, 42u, 
+	42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0
 };
 
 static const char _use_syllable_machine_key_spans[] = {
-	1, 1, 52, 38, 38, 1, 27, 26, 
+	52, 2, 1, 38, 38, 1, 27, 26, 
 	24, 23, 22, 2, 1, 25, 25, 25, 
 	1, 25, 26, 26, 26, 27, 27, 27, 
-	38, 48, 1, 1, 38, 2, 1, 38, 
-	27, 26, 24, 23, 22, 2, 1, 25, 
-	25, 25, 25, 26, 26, 26, 27, 27, 
-	27, 38, 48, 1, 1, 1, 48, 38, 
-	2, 1, 5, 3, 4, 3
+	38, 48, 1, 1, 38, 38, 1, 27, 
+	26, 24, 23, 22, 2, 1, 25, 25, 
+	25, 1, 25, 26, 26, 26, 27, 27, 
+	27, 38, 48, 1, 1, 48, 38, 2, 
+	1, 5, 3, 4, 3
 };
 
 static const short _use_syllable_machine_index_offsets[] = {
-	0, 2, 4, 57, 96, 135, 137, 165, 
-	192, 217, 241, 264, 267, 269, 295, 321, 
-	347, 349, 375, 402, 429, 456, 484, 512, 
-	540, 579, 628, 630, 632, 671, 674, 676, 
-	715, 743, 770, 795, 819, 842, 845, 847, 
-	873, 899, 925, 951, 978, 1005, 1032, 1060, 
-	1088, 1116, 1155, 1204, 1206, 1208, 1210, 1259, 
-	1298, 1301, 1303, 1309, 1313, 1318
+	0, 53, 56, 58, 97, 136, 138, 166, 
+	193, 218, 242, 265, 268, 270, 296, 322, 
+	348, 350, 376, 403, 430, 457, 485, 513, 
+	541, 580, 629, 631, 633, 672, 711, 713, 
+	741, 768, 793, 817, 840, 843, 845, 871, 
+	897, 923, 925, 951, 978, 1005, 1032, 1060, 
+	1088, 1116, 1155, 1204, 1206, 1208, 1257, 1296, 
+	1299, 1301, 1307, 1311, 1316
 };
 
 static const char _use_syllable_machine_indicies[] = {
-	1, 0, 2, 0, 3, 4, 5, 5, 
-	6, 7, 5, 5, 5, 5, 5, 1, 
-	8, 9, 5, 5, 5, 5, 10, 11, 
-	5, 5, 12, 13, 14, 15, 16, 17, 
-	18, 12, 19, 20, 21, 22, 23, 24, 
-	5, 25, 26, 27, 5, 28, 29, 30, 
-	31, 32, 33, 34, 8, 35, 5, 36, 
-	5, 38, 39, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 40, 41, 42, 43, 
-	44, 45, 46, 40, 47, 4, 48, 49, 
-	50, 51, 37, 52, 53, 54, 37, 37, 
-	37, 37, 55, 56, 57, 58, 39, 37, 
-	38, 39, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 40, 41, 42, 43, 44, 
-	45, 46, 40, 47, 48, 48, 49, 50, 
-	51, 37, 52, 53, 54, 37, 37, 37, 
-	37, 55, 56, 57, 58, 39, 37, 38, 
-	59, 40, 41, 42, 43, 44, 37, 37, 
-	37, 37, 37, 37, 49, 50, 51, 37, 
-	52, 53, 54, 37, 37, 37, 37, 41, 
-	56, 57, 58, 60, 37, 41, 42, 43, 
-	44, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 52, 53, 54, 37, 37, 
-	37, 37, 37, 56, 57, 58, 60, 37, 
-	42, 43, 44, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 56, 57, 58, 
-	37, 43, 44, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 56, 57, 58, 
-	37, 44, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 56, 57, 58, 37, 
-	56, 57, 37, 57, 37, 42, 43, 44, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 52, 53, 54, 37, 37, 37, 
-	37, 37, 56, 57, 58, 60, 37, 42, 
-	43, 44, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 53, 54, 37, 
-	37, 37, 37, 37, 56, 57, 58, 60, 
-	37, 42, 43, 44, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	54, 37, 37, 37, 37, 37, 56, 57, 
-	58, 60, 37, 62, 61, 42, 43, 44, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 56, 57, 58, 60, 37, 41, 
-	42, 43, 44, 37, 37, 37, 37, 37, 
-	37, 49, 50, 51, 37, 52, 53, 54, 
-	37, 37, 37, 37, 41, 56, 57, 58, 
-	60, 37, 41, 42, 43, 44, 37, 37, 
-	37, 37, 37, 37, 37, 50, 51, 37, 
-	52, 53, 54, 37, 37, 37, 37, 41, 
-	56, 57, 58, 60, 37, 41, 42, 43, 
-	44, 37, 37, 37, 37, 37, 37, 37, 
-	37, 51, 37, 52, 53, 54, 37, 37, 
-	37, 37, 41, 56, 57, 58, 60, 37, 
-	40, 41, 42, 43, 44, 37, 46, 40, 
-	37, 37, 37, 49, 50, 51, 37, 52, 
-	53, 54, 37, 37, 37, 37, 41, 56, 
-	57, 58, 60, 37, 40, 41, 42, 43, 
-	44, 37, 37, 40, 37, 37, 37, 49, 
-	50, 51, 37, 52, 53, 54, 37, 37, 
-	37, 37, 41, 56, 57, 58, 60, 37, 
-	40, 41, 42, 43, 44, 45, 46, 40, 
-	37, 37, 37, 49, 50, 51, 37, 52, 
-	53, 54, 37, 37, 37, 37, 41, 56, 
-	57, 58, 60, 37, 38, 39, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 40, 
-	41, 42, 43, 44, 45, 46, 40, 47, 
-	37, 48, 49, 50, 51, 37, 52, 53, 
-	54, 37, 37, 37, 37, 55, 56, 57, 
-	58, 39, 37, 38, 59, 59, 59, 59, 
-	59, 59, 59, 59, 59, 59, 59, 59, 
-	59, 59, 59, 59, 59, 59, 59, 59, 
-	59, 41, 42, 43, 44, 59, 59, 59, 
-	59, 59, 59, 59, 59, 59, 59, 52, 
-	53, 54, 59, 59, 59, 59, 59, 56, 
-	57, 58, 60, 59, 64, 63, 6, 65, 
-	38, 39, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 40, 41, 42, 43, 44, 
-	45, 46, 40, 47, 4, 48, 49, 50, 
-	51, 37, 52, 53, 54, 37, 11, 66, 
-	37, 55, 56, 57, 58, 39, 37, 11, 
-	66, 67, 66, 67, 1, 69, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 12, 
-	13, 14, 15, 16, 17, 18, 12, 19, 
-	21, 21, 22, 23, 24, 68, 25, 26, 
-	27, 68, 68, 68, 68, 31, 32, 33, 
-	34, 69, 68, 12, 13, 14, 15, 16, 
-	68, 68, 68, 68, 68, 68, 22, 23, 
-	24, 68, 25, 26, 27, 68, 68, 68, 
-	68, 13, 32, 33, 34, 70, 68, 13, 
-	14, 15, 16, 68, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 25, 26, 27, 
-	68, 68, 68, 68, 68, 32, 33, 34, 
-	70, 68, 14, 15, 16, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 32, 
-	33, 34, 68, 15, 16, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 32, 
-	33, 34, 68, 16, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 32, 33, 
-	34, 68, 32, 33, 68, 33, 68, 14, 
-	15, 16, 68, 68, 68, 68, 68, 68, 
-	68, 68, 68, 68, 25, 26, 27, 68, 
-	68, 68, 68, 68, 32, 33, 34, 70, 
-	68, 14, 15, 16, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 26, 
-	27, 68, 68, 68, 68, 68, 32, 33, 
-	34, 70, 68, 14, 15, 16, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 68, 
-	68, 68, 27, 68, 68, 68, 68, 68, 
-	32, 33, 34, 70, 68, 14, 15, 16, 
-	68, 68, 68, 68, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 68, 
-	68, 68, 32, 33, 34, 70, 68, 13, 
-	14, 15, 16, 68, 68, 68, 68, 68, 
-	68, 22, 23, 24, 68, 25, 26, 27, 
-	68, 68, 68, 68, 13, 32, 33, 34, 
-	70, 68, 13, 14, 15, 16, 68, 68, 
-	68, 68, 68, 68, 68, 23, 24, 68, 
-	25, 26, 27, 68, 68, 68, 68, 13, 
-	32, 33, 34, 70, 68, 13, 14, 15, 
-	16, 68, 68, 68, 68, 68, 68, 68, 
-	68, 24, 68, 25, 26, 27, 68, 68, 
-	68, 68, 13, 32, 33, 34, 70, 68, 
-	12, 13, 14, 15, 16, 68, 18, 12, 
-	68, 68, 68, 22, 23, 24, 68, 25, 
-	26, 27, 68, 68, 68, 68, 13, 32, 
-	33, 34, 70, 68, 12, 13, 14, 15, 
-	16, 68, 68, 12, 68, 68, 68, 22, 
-	23, 24, 68, 25, 26, 27, 68, 68, 
-	68, 68, 13, 32, 33, 34, 70, 68, 
-	12, 13, 14, 15, 16, 17, 18, 12, 
-	68, 68, 68, 22, 23, 24, 68, 25, 
-	26, 27, 68, 68, 68, 68, 13, 32, 
-	33, 34, 70, 68, 1, 69, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 12, 
-	13, 14, 15, 16, 17, 18, 12, 19, 
-	68, 21, 22, 23, 24, 68, 25, 26, 
-	27, 68, 68, 68, 68, 31, 32, 33, 
-	34, 69, 68, 1, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 68, 
-	68, 13, 14, 15, 16, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 68, 25, 
-	26, 27, 68, 68, 68, 68, 68, 32, 
-	33, 34, 70, 68, 1, 71, 72, 68, 
-	9, 68, 4, 68, 68, 68, 4, 68, 
-	68, 68, 68, 68, 1, 69, 9, 68, 
-	68, 68, 68, 68, 68, 68, 68, 12, 
-	13, 14, 15, 16, 17, 18, 12, 19, 
-	20, 21, 22, 23, 24, 68, 25, 26, 
-	27, 68, 28, 29, 68, 31, 32, 33, 
-	34, 69, 68, 1, 69, 68, 68, 68, 
-	68, 68, 68, 68, 68, 68, 12, 13, 
-	14, 15, 16, 17, 18, 12, 19, 20, 
-	21, 22, 23, 24, 68, 25, 26, 27, 
-	68, 68, 68, 68, 31, 32, 33, 34, 
-	69, 68, 28, 29, 68, 29, 68, 4, 
-	71, 71, 71, 4, 71, 74, 73, 35, 
-	73, 35, 74, 73, 74, 73, 35, 73, 
-	36, 73, 0
+	0, 1, 2, 2, 3, 4, 2, 2, 
+	2, 2, 2, 5, 6, 7, 2, 2, 
+	2, 2, 8, 2, 2, 2, 9, 10, 
+	11, 12, 13, 14, 15, 9, 16, 17, 
+	18, 19, 20, 21, 2, 22, 23, 24, 
+	2, 25, 26, 27, 28, 29, 30, 31, 
+	6, 32, 2, 33, 2, 0, 35, 34, 
+	35, 34, 37, 38, 36, 36, 36, 36, 
+	36, 36, 36, 36, 36, 39, 40, 41, 
+	42, 43, 44, 45, 39, 46, 1, 47, 
+	48, 49, 50, 36, 51, 52, 53, 36, 
+	36, 36, 36, 54, 55, 56, 57, 38, 
+	36, 37, 38, 36, 36, 36, 36, 36, 
+	36, 36, 36, 36, 39, 40, 41, 42, 
+	43, 44, 45, 39, 46, 47, 47, 48, 
+	49, 50, 36, 51, 52, 53, 36, 36, 
+	36, 36, 54, 55, 56, 57, 38, 36, 
+	37, 58, 39, 40, 41, 42, 43, 36, 
+	36, 36, 36, 36, 36, 48, 49, 50, 
+	36, 51, 52, 53, 36, 36, 36, 36, 
+	40, 55, 56, 57, 59, 36, 40, 41, 
+	42, 43, 36, 36, 36, 36, 36, 36, 
+	36, 36, 36, 36, 51, 52, 53, 36, 
+	36, 36, 36, 36, 55, 56, 57, 59, 
+	36, 41, 42, 43, 36, 36, 36, 36, 
+	36, 36, 36, 36, 36, 36, 36, 36, 
+	36, 36, 36, 36, 36, 36, 55, 56, 
+	57, 36, 42, 43, 36, 36, 36, 36, 
+	36, 36, 36, 36, 36, 36, 36, 36, 
+	36, 36, 36, 36, 36, 36, 55, 56, 
+	57, 36, 43, 36, 36, 36, 36, 36, 
+	36, 36, 36, 36, 36, 36, 36, 36, 
+	36, 36, 36, 36, 36, 55, 56, 57, 
+	36, 55, 56, 36, 56, 36, 41, 42, 
+	43, 36, 36, 36, 36, 36, 36, 36, 
+	36, 36, 36, 51, 52, 53, 36, 36, 
+	36, 36, 36, 55, 56, 57, 59, 36, 
+	41, 42, 43, 36, 36, 36, 36, 36, 
+	36, 36, 36, 36, 36, 36, 52, 53, 
+	36, 36, 36, 36, 36, 55, 56, 57, 
+	59, 36, 41, 42, 43, 36, 36, 36, 
+	36, 36, 36, 36, 36, 36, 36, 36, 
+	36, 53, 36, 36, 36, 36, 36, 55, 
+	56, 57, 59, 36, 61, 60, 41, 42, 
+	43, 36, 36, 36, 36, 36, 36, 36, 
+	36, 36, 36, 36, 36, 36, 36, 36, 
+	36, 36, 36, 55, 56, 57, 59, 36, 
+	40, 41, 42, 43, 36, 36, 36, 36, 
+	36, 36, 48, 49, 50, 36, 51, 52, 
+	53, 36, 36, 36, 36, 40, 55, 56, 
+	57, 59, 36, 40, 41, 42, 43, 36, 
+	36, 36, 36, 36, 36, 36, 49, 50, 
+	36, 51, 52, 53, 36, 36, 36, 36, 
+	40, 55, 56, 57, 59, 36, 40, 41, 
+	42, 43, 36, 36, 36, 36, 36, 36, 
+	36, 36, 50, 36, 51, 52, 53, 36, 
+	36, 36, 36, 40, 55, 56, 57, 59, 
+	36, 39, 40, 41, 42, 43, 36, 45, 
+	39, 36, 36, 36, 48, 49, 50, 36, 
+	51, 52, 53, 36, 36, 36, 36, 40, 
+	55, 56, 57, 59, 36, 39, 40, 41, 
+	42, 43, 36, 36, 39, 36, 36, 36, 
+	48, 49, 50, 36, 51, 52, 53, 36, 
+	36, 36, 36, 40, 55, 56, 57, 59, 
+	36, 39, 40, 41, 42, 43, 44, 45, 
+	39, 36, 36, 36, 48, 49, 50, 36, 
+	51, 52, 53, 36, 36, 36, 36, 40, 
+	55, 56, 57, 59, 36, 37, 38, 36, 
+	36, 36, 36, 36, 36, 36, 36, 36, 
+	39, 40, 41, 42, 43, 44, 45, 39, 
+	46, 36, 47, 48, 49, 50, 36, 51, 
+	52, 53, 36, 36, 36, 36, 54, 55, 
+	56, 57, 38, 36, 37, 58, 58, 58, 
+	58, 58, 58, 58, 58, 58, 58, 58, 
+	58, 58, 58, 58, 58, 58, 58, 58, 
+	58, 58, 40, 41, 42, 43, 58, 58, 
+	58, 58, 58, 58, 58, 58, 58, 58, 
+	51, 52, 53, 58, 58, 58, 58, 58, 
+	55, 56, 57, 59, 58, 63, 62, 3, 
+	64, 37, 38, 36, 36, 36, 36, 36, 
+	36, 36, 36, 36, 39, 40, 41, 42, 
+	43, 44, 45, 39, 46, 1, 47, 48, 
+	49, 50, 36, 51, 52, 53, 36, 0, 
+	35, 36, 54, 55, 56, 57, 38, 36, 
+	5, 6, 65, 65, 65, 65, 65, 65, 
+	65, 65, 65, 9, 10, 11, 12, 13, 
+	14, 15, 9, 16, 18, 18, 19, 20, 
+	21, 65, 22, 23, 24, 65, 65, 65, 
+	65, 28, 29, 30, 31, 6, 65, 5, 
+	65, 9, 10, 11, 12, 13, 65, 65, 
+	65, 65, 65, 65, 19, 20, 21, 65, 
+	22, 23, 24, 65, 65, 65, 65, 10, 
+	29, 30, 31, 66, 65, 10, 11, 12, 
+	13, 65, 65, 65, 65, 65, 65, 65, 
+	65, 65, 65, 22, 23, 24, 65, 65, 
+	65, 65, 65, 29, 30, 31, 66, 65, 
+	11, 12, 13, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 29, 30, 31, 
+	65, 12, 13, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 29, 30, 31, 
+	65, 13, 65, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 29, 30, 31, 65, 
+	29, 30, 65, 30, 65, 11, 12, 13, 
+	65, 65, 65, 65, 65, 65, 65, 65, 
+	65, 65, 22, 23, 24, 65, 65, 65, 
+	65, 65, 29, 30, 31, 66, 65, 11, 
+	12, 13, 65, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 23, 24, 65, 
+	65, 65, 65, 65, 29, 30, 31, 66, 
+	65, 11, 12, 13, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 65, 65, 65, 
+	24, 65, 65, 65, 65, 65, 29, 30, 
+	31, 66, 65, 67, 65, 11, 12, 13, 
+	65, 65, 65, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 65, 65, 65, 
+	65, 65, 29, 30, 31, 66, 65, 10, 
+	11, 12, 13, 65, 65, 65, 65, 65, 
+	65, 19, 20, 21, 65, 22, 23, 24, 
+	65, 65, 65, 65, 10, 29, 30, 31, 
+	66, 65, 10, 11, 12, 13, 65, 65, 
+	65, 65, 65, 65, 65, 20, 21, 65, 
+	22, 23, 24, 65, 65, 65, 65, 10, 
+	29, 30, 31, 66, 65, 10, 11, 12, 
+	13, 65, 65, 65, 65, 65, 65, 65, 
+	65, 21, 65, 22, 23, 24, 65, 65, 
+	65, 65, 10, 29, 30, 31, 66, 65, 
+	9, 10, 11, 12, 13, 65, 15, 9, 
+	65, 65, 65, 19, 20, 21, 65, 22, 
+	23, 24, 65, 65, 65, 65, 10, 29, 
+	30, 31, 66, 65, 9, 10, 11, 12, 
+	13, 65, 65, 9, 65, 65, 65, 19, 
+	20, 21, 65, 22, 23, 24, 65, 65, 
+	65, 65, 10, 29, 30, 31, 66, 65, 
+	9, 10, 11, 12, 13, 14, 15, 9, 
+	65, 65, 65, 19, 20, 21, 65, 22, 
+	23, 24, 65, 65, 65, 65, 10, 29, 
+	30, 31, 66, 65, 5, 6, 65, 65, 
+	65, 65, 65, 65, 65, 65, 65, 9, 
+	10, 11, 12, 13, 14, 15, 9, 16, 
+	65, 18, 19, 20, 21, 65, 22, 23, 
+	24, 65, 65, 65, 65, 28, 29, 30, 
+	31, 6, 65, 5, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 65, 65, 65, 65, 
+	65, 10, 11, 12, 13, 65, 65, 65, 
+	65, 65, 65, 65, 65, 65, 65, 22, 
+	23, 24, 65, 65, 65, 65, 65, 29, 
+	30, 31, 66, 65, 68, 65, 7, 65, 
+	1, 65, 65, 65, 1, 65, 65, 65, 
+	65, 65, 5, 6, 7, 65, 65, 65, 
+	65, 65, 65, 65, 65, 9, 10, 11, 
+	12, 13, 14, 15, 9, 16, 17, 18, 
+	19, 20, 21, 65, 22, 23, 24, 65, 
+	25, 26, 65, 28, 29, 30, 31, 6, 
+	65, 5, 6, 65, 65, 65, 65, 65, 
+	65, 65, 65, 65, 9, 10, 11, 12, 
+	13, 14, 15, 9, 16, 17, 18, 19, 
+	20, 21, 65, 22, 23, 24, 65, 65, 
+	65, 65, 28, 29, 30, 31, 6, 65, 
+	25, 26, 65, 26, 65, 1, 69, 69, 
+	69, 1, 69, 71, 70, 32, 70, 32, 
+	71, 70, 71, 70, 32, 70, 33, 70, 
+	0
 };
 
 static const char _use_syllable_machine_trans_targs[] = {
-	2, 31, 42, 2, 3, 2, 26, 28, 
-	51, 52, 54, 29, 32, 33, 34, 35, 
-	36, 46, 47, 48, 55, 49, 43, 44, 
-	45, 39, 40, 41, 56, 57, 58, 50, 
-	37, 38, 2, 59, 61, 2, 4, 5, 
-	6, 7, 8, 9, 10, 21, 22, 23, 
-	24, 18, 19, 20, 13, 14, 15, 25, 
-	11, 12, 2, 2, 16, 2, 17, 2, 
-	27, 2, 30, 2, 2, 0, 1, 2, 
-	53, 2, 60
+	1, 3, 0, 26, 28, 29, 30, 51, 
+	53, 31, 32, 33, 34, 35, 46, 47, 
+	48, 54, 49, 43, 44, 45, 38, 39, 
+	40, 55, 56, 57, 50, 36, 37, 0, 
+	58, 60, 0, 2, 0, 4, 5, 6, 
+	7, 8, 9, 10, 21, 22, 23, 24, 
+	18, 19, 20, 13, 14, 15, 25, 11, 
+	12, 0, 0, 16, 0, 17, 0, 27, 
+	0, 0, 41, 42, 52, 0, 0, 59
 };
 
 static const char _use_syllable_machine_trans_actions[] = {
-	1, 2, 2, 5, 0, 6, 0, 0, 
-	0, 0, 2, 0, 2, 2, 0, 0, 
-	0, 2, 2, 2, 2, 2, 2, 2, 
-	2, 2, 2, 2, 0, 0, 0, 2, 
-	0, 0, 7, 0, 0, 8, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 9, 10, 0, 11, 0, 12, 
-	0, 13, 0, 14, 15, 0, 0, 16, 
-	0, 17, 0
-};
-
-static const char _use_syllable_machine_to_state_actions[] = {
 	0, 0, 3, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 4, 
+	0, 0, 5, 0, 6, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 7, 8, 0, 9, 0, 10, 0, 
+	11, 12, 0, 0, 0, 13, 14, 0
+};
+
+static const char _use_syllable_machine_to_state_actions[] = {
+	1, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0
 };
 
 static const char _use_syllable_machine_from_state_actions[] = {
-	0, 0, 4, 0, 0, 0, 0, 0, 
+	2, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0
+	0, 0, 0, 0, 0
 };
 
 static const short _use_syllable_machine_eof_trans[] = {
-	1, 1, 0, 38, 38, 60, 38, 38, 
-	38, 38, 38, 38, 38, 38, 38, 38, 
-	62, 38, 38, 38, 38, 38, 38, 38, 
-	38, 60, 64, 66, 38, 68, 68, 69, 
-	69, 69, 69, 69, 69, 69, 69, 69, 
-	69, 69, 69, 69, 69, 69, 69, 69, 
-	69, 69, 69, 72, 69, 69, 69, 69, 
-	69, 69, 72, 74, 74, 74
+	0, 35, 35, 37, 37, 59, 37, 37, 
+	37, 37, 37, 37, 37, 37, 37, 37, 
+	61, 37, 37, 37, 37, 37, 37, 37, 
+	37, 59, 63, 65, 37, 66, 66, 66, 
+	66, 66, 66, 66, 66, 66, 66, 66, 
+	66, 66, 66, 66, 66, 66, 66, 66, 
+	66, 66, 66, 66, 66, 66, 66, 66, 
+	66, 70, 71, 71, 71
 };
 
-static const int use_syllable_machine_start = 2;
-static const int use_syllable_machine_first_final = 2;
+static const int use_syllable_machine_start = 0;
+static const int use_syllable_machine_first_final = 0;
 static const int use_syllable_machine_error = -1;
 
-static const int use_syllable_machine_en_main = 2;
+static const int use_syllable_machine_en_main = 0;
 
 
-#line 59 "hb-ot-shape-complex-use-machine.rl"
+#line 58 "hb-ot-shape-complex-use-machine.rl"
 
 
 
-#line 176 "hb-ot-shape-complex-use-machine.rl"
+#line 179 "hb-ot-shape-complex-use-machine.rl"
 
 
 #define found_syllable(syllable_type) \
@@ -422,8 +419,8 @@
 
 
 static bool
-not_standard_default_ignorable (const hb_glyph_info_t &i)
-{ return !(i.use_category() == USE(O) && _hb_glyph_info_is_default_ignorable (&i)); }
+not_ccs_default_ignorable (const hb_glyph_info_t &i)
+{ return !(i.use_category() == USE(CGJ) && _hb_glyph_info_is_default_ignorable (&i)); }
 
 static inline void
 find_syllables_use (hb_buffer_t *buffer)
@@ -432,13 +429,13 @@
   auto p =
     + hb_iter (info, buffer->len)
     | hb_enumerate
-    | hb_filter ([] (const hb_glyph_info_t &i) { return not_standard_default_ignorable (i); },
+    | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
 		 hb_second)
     | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
 		 {
 		   if (p.second.use_category() == USE(ZWNJ))
 		     for (unsigned i = p.first + 1; i < buffer->len; ++i)
-		       if (not_standard_default_ignorable (info[i]))
+		       if (not_ccs_default_ignorable (info[i]))
 			 return !_hb_glyph_info_is_unicode_mark (&info[i]);
 		   return true;
 		 })
@@ -452,7 +449,7 @@
   unsigned int act HB_UNUSED;
   int cs;
   
-#line 456 "hb-ot-shape-complex-use-machine.hh"
+#line 453 "hb-ot-shape-complex-use-machine.hh"
 	{
 	cs = use_syllable_machine_start;
 	ts = 0;
@@ -460,12 +457,12 @@
 	act = 0;
 	}
 
-#line 260 "hb-ot-shape-complex-use-machine.rl"
+#line 263 "hb-ot-shape-complex-use-machine.rl"
 
 
   unsigned int syllable_serial = 1;
   
-#line 469 "hb-ot-shape-complex-use-machine.hh"
+#line 466 "hb-ot-shape-complex-use-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -475,11 +472,11 @@
 		goto _test_eof;
 _resume:
 	switch ( _use_syllable_machine_from_state_actions[cs] ) {
-	case 4:
+	case 2:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 483 "hb-ot-shape-complex-use-machine.hh"
+#line 480 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 	_keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -497,76 +494,64 @@
 		goto _again;
 
 	switch ( _use_syllable_machine_trans_actions[_trans] ) {
-	case 2:
-#line 1 "NONE"
-	{te = p+1;}
-	break;
-	case 5:
-#line 163 "hb-ot-shape-complex-use-machine.rl"
-	{te = p+1;{ found_syllable (use_independent_cluster); }}
-	break;
-	case 9:
-#line 166 "hb-ot-shape-complex-use-machine.rl"
+	case 7:
+#line 169 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (use_standard_cluster); }}
 	break;
-	case 7:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
+	case 4:
+#line 174 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (use_broken_cluster); }}
 	break;
-	case 6:
-#line 172 "hb-ot-shape-complex-use-machine.rl"
+	case 3:
+#line 175 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (use_non_cluster); }}
 	break;
-	case 10:
-#line 164 "hb-ot-shape-complex-use-machine.rl"
+	case 8:
+#line 167 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_virama_terminated_cluster); }}
 	break;
-	case 11:
-#line 165 "hb-ot-shape-complex-use-machine.rl"
+	case 9:
+#line 168 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
 	break;
-	case 8:
-#line 166 "hb-ot-shape-complex-use-machine.rl"
+	case 6:
+#line 169 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_standard_cluster); }}
 	break;
-	case 13:
-#line 167 "hb-ot-shape-complex-use-machine.rl"
+	case 11:
+#line 170 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
 	break;
-	case 12:
-#line 168 "hb-ot-shape-complex-use-machine.rl"
+	case 10:
+#line 171 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_numeral_cluster); }}
 	break;
-	case 14:
-#line 169 "hb-ot-shape-complex-use-machine.rl"
+	case 5:
+#line 172 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_symbol_cluster); }}
 	break;
-	case 17:
-#line 170 "hb-ot-shape-complex-use-machine.rl"
+	case 14:
+#line 173 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
 	break;
-	case 15:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
+	case 12:
+#line 174 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_broken_cluster); }}
 	break;
-	case 16:
-#line 172 "hb-ot-shape-complex-use-machine.rl"
+	case 13:
+#line 175 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (use_non_cluster); }}
 	break;
-	case 1:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
-	{{p = ((te))-1;}{ found_syllable (use_broken_cluster); }}
-	break;
-#line 561 "hb-ot-shape-complex-use-machine.hh"
+#line 546 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 _again:
 	switch ( _use_syllable_machine_to_state_actions[cs] ) {
-	case 3:
+	case 1:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 570 "hb-ot-shape-complex-use-machine.hh"
+#line 555 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 	if ( ++p != pe )
@@ -582,7 +567,7 @@
 
 	}
 
-#line 265 "hb-ot-shape-complex-use-machine.rl"
+#line 268 "hb-ot-shape-complex-use-machine.rl"
 
 }
 
diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl
index 00d82b4..9e0d98d 100644
--- a/src/hb-ot-shape-complex-use-machine.rl
+++ b/src/hb-ot-shape-complex-use-machine.rl
@@ -39,7 +39,6 @@
 #define USE(Cat) use_syllable_machine_ex_##Cat
 
 enum use_syllable_type_t {
-  use_independent_cluster,
   use_virama_terminated_cluster,
   use_sakot_terminated_cluster,
   use_standard_cluster,
@@ -68,13 +67,13 @@
 export B	= 1; # BASE
 export N	= 4; # BASE_NUM
 export GB	= 5; # BASE_OTHER
+export CGJ	= 6; # CGJ
 export SUB	= 11; # CONS_SUB
 export H	= 12; # HALANT
 
 export HN	= 13; # HALANT_NUM
 export ZWNJ	= 14; # Zero width non-joiner
 export R	= 18; # REPHA
-export S	= 19; # SYM
 export CS	= 43; # CONS_WITH_STACKER
 export HVM	= 44; # HALANT_OR_VOWEL_MODIFIER
 export Sk	= 48; # SAKOT
@@ -133,34 +132,38 @@
 numeral_cluster_tail = (HN N)+;
 symbol_cluster_tail = SMAbv+ SMBlw* | SMBlw+;
 
-virama_terminated_cluster =
-	complex_syllable_start
+virama_terminated_cluster_tail =
 	consonant_modifiers
 	h
 ;
-sakot_terminated_cluster =
+virama_terminated_cluster =
 	complex_syllable_start
+	virama_terminated_cluster_tail
+;
+sakot_terminated_cluster_tail =
 	complex_syllable_middle
 	Sk
 ;
+sakot_terminated_cluster =
+	complex_syllable_start
+	sakot_terminated_cluster_tail
+;
 standard_cluster =
 	complex_syllable_start
 	complex_syllable_tail
 ;
 broken_cluster =
 	R?
-	(complex_syllable_tail | number_joiner_terminated_cluster_tail | numeral_cluster_tail | symbol_cluster_tail)
+	(complex_syllable_tail | number_joiner_terminated_cluster_tail | numeral_cluster_tail | symbol_cluster_tail | virama_terminated_cluster_tail | sakot_terminated_cluster_tail)
 ;
 
 number_joiner_terminated_cluster = N number_joiner_terminated_cluster_tail;
 numeral_cluster = N numeral_cluster_tail?;
-symbol_cluster = (S | GB) symbol_cluster_tail?;
+symbol_cluster = (O | GB) symbol_cluster_tail?;
 hieroglyph_cluster = SB+ | SB* G SE* (J SE* (G SE*)?)*;
-independent_cluster = O;
 other = any;
 
 main := |*
-	independent_cluster			=> { found_syllable (use_independent_cluster); };
 	virama_terminated_cluster		=> { found_syllable (use_virama_terminated_cluster); };
 	sakot_terminated_cluster		=> { found_syllable (use_sakot_terminated_cluster); };
 	standard_cluster			=> { found_syllable (use_standard_cluster); };
@@ -225,8 +228,8 @@
 
 
 static bool
-not_standard_default_ignorable (const hb_glyph_info_t &i)
-{ return !(i.use_category() == USE(O) && _hb_glyph_info_is_default_ignorable (&i)); }
+not_ccs_default_ignorable (const hb_glyph_info_t &i)
+{ return !(i.use_category() == USE(CGJ) && _hb_glyph_info_is_default_ignorable (&i)); }
 
 static inline void
 find_syllables_use (hb_buffer_t *buffer)
@@ -235,13 +238,13 @@
   auto p =
     + hb_iter (info, buffer->len)
     | hb_enumerate
-    | hb_filter ([] (const hb_glyph_info_t &i) { return not_standard_default_ignorable (i); },
+    | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
 		 hb_second)
     | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
 		 {
 		   if (p.second.use_category() == USE(ZWNJ))
 		     for (unsigned i = p.first + 1; i < buffer->len; ++i)
-		       if (not_standard_default_ignorable (info[i]))
+		       if (not_ccs_default_ignorable (info[i]))
 			 return !_hb_glyph_info_is_unicode_mark (&info[i]);
 		   return true;
 		 })
diff --git a/src/hb-ot-shape-complex-use-table.hh b/src/hb-ot-shape-complex-use-table.hh
index 7903a0e..7a3a995 100644
--- a/src/hb-ot-shape-complex-use-table.hh
+++ b/src/hb-ot-shape-complex-use-table.hh
@@ -2,7 +2,7 @@
 /*
  * The following table is generated by running:
  *
- *   ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt ArabicShaping.txt Blocks.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
+ *   ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
  *
  * on files with these headers:
  *
@@ -12,22 +12,28 @@
  * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
  * # ArabicShaping-14.0.0.txt
  * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
+ * # DerivedCoreProperties-14.0.0.txt
+ * # Date: 2021-08-12, 23:12:53 GMT
  * # Blocks-14.0.0.txt
  * # Date: 2021-01-22, 23:29:00 GMT [KW]
+ * # Scripts-14.0.0.txt
+ * # Date: 2021-07-10, 00:35:31 GMT
  * # Override values For Indic_Syllabic_Category
  * # Not derivable
  * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated  for Unicode 10.0 by Andrew Glass 2017-07-25
- * # Updated  for Unicode 12.1 by Andrew Glass 2019-05-24
- * # Updated  for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
  * # Override values For Indic_Positional_Category
  * # Not derivable
  * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated  for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
  * # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
- * # Updated  for L2/19-083    by Andrew Glass 2019-05-06
- * # Updated  for Unicode 12.1 by Andrew Glass 2019-05-30
- * # Updated  for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for L2/19-083    by Andrew Glass 2019-05-06
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
  * UnicodeData.txt does not have a header.
  */
 
@@ -41,6 +47,7 @@
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-macros"
 #define B	USE(B)	/* BASE */
+#define CGJ	USE(CGJ)	/* CGJ */
 #define CS	USE(CS)	/* CONS_WITH_STACKER */
 #define G	USE(G)	/* HIEROGLYPH */
 #define GB	USE(GB)	/* BASE_OTHER */
@@ -51,7 +58,6 @@
 #define N	USE(N)	/* BASE_NUM */
 #define O	USE(O)	/* OTHER */
 #define R	USE(R)	/* REPHA */
-#define S	USE(S)	/* SYM */
 #define SB	USE(SB)	/* HIEROGLYPH_SEGMENT_BEGIN */
 #define SE	USE(SE)	/* HIEROGLYPH_SEGMENT_END */
 #define SUB	USE(SUB)	/* CONS_SUB */
@@ -101,14 +107,20 @@
   /* 00C0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 00D0 */     O,     O,     O,     O,     O,     O,     O,    GB,
 
-#define use_offset_0x0640u 80
+#define use_offset_0x0348u 80
+
+
+  /* Combining Diacritical Marks */
+                                                                         O,     O,     O,     O,     O,     O,     O,   CGJ,
+
+#define use_offset_0x0640u 88
 
 
   /* Arabic */
 
   /* 0640 */     B,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x07c8u 88
+#define use_offset_0x07c8u 96
 
 
   /* NKo */
@@ -117,7 +129,7 @@
   /* 07E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
   /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,     O,     O,     O,     B,     O,     O, VMAbv,     O,     O,
 
-#define use_offset_0x0840u 144
+#define use_offset_0x0840u 152
 
 
   /* Mandaic */
@@ -125,7 +137,7 @@
   /* 0840 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0850 */     B,     B,     B,     B,     B,     B,     B,     B,     B, CMBlw, CMBlw, CMBlw,     O,     O,     O,     O,
 
-#define use_offset_0x0900u 176
+#define use_offset_0x0900u 184
 
 
   /* Devanagari */
@@ -238,7 +250,7 @@
   /* 0DE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0DF0 */     O,     O,  VPst,  VPst,     O,     O,     O,     O,
 
-#define use_offset_0x0f00u 1448
+#define use_offset_0x0f00u 1456
 
 
   /* Tibetan */
@@ -257,7 +269,7 @@
   /* 0FB0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,     O,     O,
   /* 0FC0 */     O,     O,     O,     O,     O,     O,  FBlw,     O,
 
-#define use_offset_0x1000u 1648
+#define use_offset_0x1000u 1656
 
 
   /* Myanmar */
@@ -273,7 +285,7 @@
   /* 1080 */     B,     B,  MBlw,  VPst,  VPre,  VAbv,  VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw,     B, VMPst,
   /* 1090 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMPst, VMPst,  VPst,  VAbv,     O,     O,
 
-#define use_offset_0x1700u 1808
+#define use_offset_0x1700u 1816
 
 
   /* Tagalog */
@@ -301,7 +313,7 @@
   /* 1780 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1790 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 17A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPre,  VPre,
+  /* 17B0 */     B,     B,     B,     B,   CGJ,   CGJ,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPre,  VPre,
   /* 17C0 */  VPre,  VPre,  VPre,  VPre,  VPre,  VPre, VMAbv, VMPst,  VPst, VMAbv, VMAbv, FMAbv,  FAbv, CMAbv, FMAbv, VMAbv,
   /* 17D0 */ FMAbv,  VAbv,     H, FMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     B, FMAbv,     O,     O,
   /* 17E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
@@ -309,7 +321,7 @@
 
   /* Mongolian */
 
-  /* 1800 */     B,     O,     O,     O,     O,     O,     O,     B,     O,     O,     B,     O,     O,     O,     O,     O,
+  /* 1800 */     B,     O,     O,     O,     O,     O,     O,     B,     O,     O,     B,   CGJ,   CGJ,   CGJ,     O,   CGJ,
   /* 1810 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 1820 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1830 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
@@ -321,7 +333,7 @@
   /* 1890 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 18A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B, CMBlw,     B,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1900u 2240
+#define use_offset_0x1900u 2248
 
 
   /* Limbu */
@@ -365,7 +377,7 @@
   /* 1A80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1A90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1b00u 2656
+#define use_offset_0x1b00u 2664
 
 
   /* Balinese */
@@ -376,7 +388,7 @@
   /* 1B30 */     B,     B,     B,     B, CMAbv,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VPre,
   /* 1B40 */  VPre,  VPre,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
   /* 1B50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,    GB,    GB,     O,     O,    GB,
-  /* 1B60 */     O,     S,    GB,     S,     S,     S,     S,     S,    GB,     S,     S, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
+  /* 1B60 */     O,     O,    GB,     O,     O,     O,     O,     O,    GB,     O,     O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
   /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Sundanese */
@@ -401,7 +413,7 @@
   /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre, FMAbv, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 1C40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,     B,
 
-#define use_offset_0x1cd0u 2992
+#define use_offset_0x1cd0u 3000
 
 
   /* Vedic Extensions */
@@ -410,20 +422,20 @@
   /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,     O,     O,     O,     O, VMBlw,     O,     O,
   /* 1CF0 */     O,     O,     O,     O, VMAbv,    CS,    CS, VMPst, VMAbv, VMAbv,    GB,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1df8u 3040
+#define use_offset_0x1df8u 3048
 
 
   /* Combining Diacritical Marks Supplement */
                                                                          O,     O,     O, FMAbv,     O,     O,     O,     O,
 
-#define use_offset_0x2008u 3048
+#define use_offset_0x2008u 3056
 
 
   /* General Punctuation */
-                                                                         O,     O,     O,     O,  ZWNJ,     O,     O,     O,
+                                                                         O,     O,     O,     O,  ZWNJ,   CGJ,     O,     O,
   /* 2010 */    GB,    GB,    GB,    GB,    GB,     O,     O,     O,
 
-#define use_offset_0x2070u 3064
+#define use_offset_0x2070u 3072
 
 
   /* Superscripts and Subscripts */
@@ -431,20 +443,20 @@
   /* 2070 */     O,     O,     O,     O, FMPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 2080 */     O,     O, FMPst, FMPst, FMPst,     O,     O,     O,
 
-#define use_offset_0x20f0u 3088
+#define use_offset_0x20f0u 3096
 
 
   /* Combining Diacritical Marks for Symbols */
 
   /* 20F0 */ VMAbv,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x25c8u 3096
+#define use_offset_0x25c8u 3104
 
 
   /* Geometric Shapes */
                                                                          O,     O,     O,     O,     B,     O,     O,     O,
 
-#define use_offset_0x2d30u 3104
+#define use_offset_0x2d30u 3112
 
 
   /* Tifinagh */
@@ -455,7 +467,7 @@
   /* 2D60 */     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,     B,
   /* 2D70 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     H,
 
-#define use_offset_0xa800u 3184
+#define use_offset_0xa800u 3192
 
 
   /* Syloti Nagri */
@@ -542,7 +554,7 @@
   /* AAE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPre,  VBlw,  VAbv,  VPre,  VPst,
   /* AAF0 */     O,     O,     O,     O,     O, VMPst,     H,     O,
 
-#define use_offset_0xabc0u 3944
+#define use_offset_0xabc0u 3952
 
 
   /* Meetei Mayek */
@@ -552,7 +564,25 @@
   /* ABE0 */     B,     B,     B,  VPst,  VPst,  VAbv,  VPst,  VPst,  VBlw,  VPst,  VPst,     O, VMPst,  VBlw,     O,     O,
   /* ABF0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x10a00u 4008
+#define use_offset_0xfe00u 4016
+
+
+  /* Variation Selectors */
+
+  /* FE00 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+
+#define use_offset_0x10570u 4032
+
+
+  /* Vithkuqi */
+
+  /* 10570 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,
+  /* 10580 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,
+  /* 10590 */     B,     B,     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 105A0 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 105B0 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     O,     O,     O,
+
+#define use_offset_0x10a00u 4112
 
 
   /* Kharoshthi */
@@ -563,16 +593,16 @@
   /* 10A30 */     B,     B,     B,     B,     B,     B,     O,     O, CMAbv, CMBlw, CMBlw,     O,     O,     O,     O,     H,
   /* 10A40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x10ac0u 4088
+#define use_offset_0x10ac0u 4192
 
 
   /* Manichaean */
 
   /* 10AC0 */     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,
   /* 10AD0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 10AE0 */     B,     B,     B,     B,     B, CMBlw, CMBlw,     O,
+  /* 10AE0 */     B,     B,     B,     B,     B, CMBlw, CMBlw,     O,     O,     O,     O,     B,     B,     B,     B,     B,
 
-#define use_offset_0x10b80u 4128
+#define use_offset_0x10b80u 4240
 
 
   /* Psalter Pahlavi */
@@ -581,7 +611,7 @@
   /* 10B90 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 10BA0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     O,
 
-#define use_offset_0x10d00u 4176
+#define use_offset_0x10d00u 4288
 
 
   /* Hanifi Rohingya */
@@ -591,7 +621,7 @@
   /* 10D20 */     B,     B,     B,     B, VMAbv, VMAbv, VMAbv, CMAbv,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 10D30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x10e80u 4240
+#define use_offset_0x10e80u 4352
 
 
   /* Yezidi */
@@ -601,17 +631,22 @@
   /* 10EA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,  VAbv,  VAbv,     O,     O,     O,
   /* 10EB0 */     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x10f30u 4296
+#define use_offset_0x10f30u 4408
 
 
   /* Sogdian */
 
   /* 10F30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 10F40 */     B,     B,     B,     B,     B,     B, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,
-  /* 10F50 */ VMBlw,     B,     B,     B,     B,     O,     O,     O,
+  /* 10F50 */ VMBlw,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 10F60 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x10fb0u 4336
+  /* Old Uyghur */
 
+  /* 10F70 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 10F80 */     B,     B, CMBlw, CMBlw, CMBlw, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 10F90 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 10FA0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Chorasmian */
 
@@ -627,7 +662,7 @@
   /* 11010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11020 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11030 */     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,
-  /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,   HVM,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,     H,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11050 */     O,     O,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,
   /* 11060 */     N,     N,     N,     N,     N,     N,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11070 */  VAbv,     B,     B,  VAbv,  VAbv,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,    HN,
@@ -640,7 +675,7 @@
   /* 110B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VAbv,  VAbv,  VPst,  VPst,     H, CMBlw,     O,     O,     O,     O,     O,
   /* 110C0 */     O,     O,  VBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11100u 4616
+#define use_offset_0x11100u 4816
 
 
   /* Chakma */
@@ -678,7 +713,7 @@
   /* 11220 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPst,  VPst,  VBlw,
   /* 11230 */  VAbv,  VAbv,  VAbv,  VAbv, VMAbv,     H, CMAbv, CMAbv,     O,     O,     O,     O,     O,     O, VMAbv,     O,
 
-#define use_offset_0x11280u 4936
+#define use_offset_0x11280u 5136
 
 
   /* Multani */
@@ -706,7 +741,7 @@
   /* 11360 */     B,     B,  VPst,  VPst,     O,     O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
   /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
 
-#define use_offset_0x11400u 5184
+#define use_offset_0x11400u 5384
 
 
   /* Newa */
@@ -729,7 +764,7 @@
   /* 114C0 */ VMAbv, VMAbv,     H, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 114D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11580u 5408
+#define use_offset_0x11580u 5608
 
 
   /* Siddham */
@@ -773,7 +808,7 @@
   /* 11730 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
   /* 11740 */     B,     B,     B,     B,     B,     B,     B,     O,
 
-#define use_offset_0x11800u 5864
+#define use_offset_0x11800u 6064
 
 
   /* Dogra */
@@ -783,7 +818,7 @@
   /* 11820 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,
   /* 11830 */  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11900u 5928
+#define use_offset_0x11900u 6128
 
 
   /* Dives Akuru */
@@ -795,7 +830,7 @@
   /* 11940 */  MPst,     R,  MPst, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11950 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x119a0u 6024
+#define use_offset_0x119a0u 6224
 
 
   /* Nandinagari */
@@ -823,7 +858,7 @@
   /* 11A80 */     B,     B,     B,     B,     R,     R,     R,     R,     R,     R,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,
   /* 11A90 */  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw, VMAbv, VMPst, CMAbv,     H,     O,     O,     O,     B,     O,     O,
 
-#define use_offset_0x11c00u 6280
+#define use_offset_0x11c00u 6480
 
 
   /* Bhaiksuki */
@@ -844,7 +879,7 @@
   /* 11CA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 11CB0 */  VBlw,  VPre,  VBlw,  VAbv,  VPst, VMAbv, VMAbv,     O,
 
-#define use_offset_0x11d00u 6464
+#define use_offset_0x11d00u 6664
 
 
   /* Masaram Gondi */
@@ -864,7 +899,7 @@
   /* 11D90 */  VAbv,  VAbv,     O,  VPst,  VPst, VMAbv, VMPst,     H,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11DA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11ee0u 6640
+#define use_offset_0x11ee0u 6840
 
 
   /* Makasar */
@@ -872,86 +907,93 @@
   /* 11EE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11EF0 */     B,     B,    GB,  VAbv,  VBlw,  VPre,  VPst,     O,
 
-#define use_offset_0x13000u 6664
+#define use_offset_0x13000u 6864
 
 
   /* Egyptian Hieroglyphs */
 
-  /* 13000 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13010 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13020 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13030 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13040 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13050 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13060 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13070 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13080 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13090 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 130A0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 130B0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 130C0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 130D0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 130E0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 130F0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13100 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13110 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13120 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13130 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13140 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13150 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13160 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13170 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13180 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13190 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 131A0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 131B0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 131C0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 131D0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 131E0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 131F0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13200 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13210 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13220 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13230 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13240 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13250 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13260 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13270 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13280 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13290 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 132A0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 132B0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 132C0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 132D0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 132E0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 132F0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13300 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13310 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13320 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13330 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13340 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13350 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13360 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13370 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13380 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13390 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 133A0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 133B0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 133C0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 133D0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 133E0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 133F0 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13400 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13410 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,
-  /* 13420 */     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     G,     O,
+  /* 13000 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13020 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13030 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13040 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13050 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13060 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13070 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13080 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13090 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 130A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 130B0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 130C0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 130D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 130E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 130F0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13100 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13110 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13120 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13130 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13140 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13150 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13160 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13170 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13180 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13190 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 131A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 131B0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 131C0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 131D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 131E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 131F0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13200 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13210 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13220 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13230 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13240 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13250 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13260 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13270 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13280 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13290 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 132A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 132B0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 132C0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 132D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 132E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 132F0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13300 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13310 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13320 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13330 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13340 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13350 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13360 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13370 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13380 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13390 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 133A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 133B0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 133C0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 133D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 133E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 133F0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13400 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13410 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 13420 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,
 
   /* Egyptian Hieroglyph Format Controls */
 
-  /* 13430 */     J,     J,     J,     J,     J,     J,     J,    SB,    SE,     O,     O,     O,     O,     O,     O,     O,
+  /* 13430 */     H,     H,     H,     H,     H,     H,     H,     B,     B,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x16b00u 7752
+#define use_offset_0x16ac0u 7952
 
 
+  /* Tangsa */
+
+  /* 16AC0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
+  /* 16AD0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 16AE0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 16AF0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+
   /* Pahawh Hmong */
 
   /* 16B00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
@@ -959,7 +1001,7 @@
   /* 16B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 16B30 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,
 
-#define use_offset_0x16f00u 7808
+#define use_offset_0x16f00u 8072
 
 
   /* Miao */
@@ -975,14 +1017,14 @@
   /* 16F80 */  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,     O,     O,     O,     O,     O, VMBlw,
   /* 16F90 */ VMBlw, VMBlw, VMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x16fe0u 7960
+#define use_offset_0x16fe0u 8224
 
 
   /* Ideographic Symbols and Punctuation */
 
   /* 16FE0 */     O,     O,     O,     O,     B,     O,     O,     O,
 
-#define use_offset_0x18b00u 7968
+#define use_offset_0x18b00u 8232
 
 
   /* Khitan Small Script */
@@ -1018,7 +1060,7 @@
   /* 18CC0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 18CD0 */     B,     B,     B,     B,     B,     B,     O,     O,
 
-#define use_offset_0x1bc00u 8440
+#define use_offset_0x1bc00u 8704
 
 
   /* Duployan */
@@ -1034,7 +1076,7 @@
   /* 1BC80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,
   /* 1BC90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O, CMBlw, CMBlw,     O,
 
-#define use_offset_0x1e100u 8600
+#define use_offset_0x1e100u 8864
 
 
   /* Nyiakeng Puachue Hmong */
@@ -1045,9 +1087,15 @@
   /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     B,     B,     B,     B,     B,     B,     B,     O,     O,
   /* 1E140 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     B,     B,
 
-#define use_offset_0x1e2c0u 8680
+#define use_offset_0x1e290u 8944
 
 
+  /* Toto */
+
+  /* 1E290 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 1E2A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMAbv,     O,
+  /* 1E2B0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+
   /* Wancho */
 
   /* 1E2C0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
@@ -1055,7 +1103,7 @@
   /* 1E2E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMAbv, VMAbv, VMAbv, VMAbv,
   /* 1E2F0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1e900u 8744
+#define use_offset_0x1e900u 9056
 
 
   /* Adlam */
@@ -1067,7 +1115,28 @@
   /* 1E940 */     B,     B,     B,     B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv,     B,     O,     O,     O,     O,
   /* 1E950 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-}; /* Table items: 8840; occupancy: 79% */
+#define use_offset_0xe0100u 9152
+
+
+  /* Variation Selectors Supplement */
+
+  /* E0100 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E0110 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E0120 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E0130 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E0140 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E0150 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E0160 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E0170 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E0180 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E0190 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E01A0 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E01B0 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E01C0 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E01D0 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+  /* E01E0 */   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,   CGJ,
+
+}; /* Table items: 9392; occupancy: 79% */
 
 static inline uint8_t
 hb_use_get_category (hb_codepoint_t u)
@@ -1077,6 +1146,7 @@
     case 0x0u:
       if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
       if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0640u, 0x0647u)) return use_table[u - 0x0640u + use_offset_0x0640u];
       if (hb_in_range<hb_codepoint_t> (u, 0x07C8u, 0x07FFu)) return use_table[u - 0x07C8u + use_offset_0x07c8u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0840u, 0x085Fu)) return use_table[u - 0x0840u + use_offset_0x0840u];
@@ -1106,18 +1176,22 @@
       if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
       break;
 
+    case 0xFu:
+      if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u];
+      break;
+
     case 0x10u:
+      if (hb_in_range<hb_codepoint_t> (u, 0x10570u, 0x105BFu)) return use_table[u - 0x10570u + use_offset_0x10570u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A4Fu)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AE7u)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return use_table[u - 0x10B80u + use_offset_0x10b80u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D3Fu)) return use_table[u - 0x10D00u + use_offset_0x10d00u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10E80u, 0x10EB7u)) return use_table[u - 0x10E80u + use_offset_0x10e80u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10F57u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110C7u)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
       break;
 
     case 0x11u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x110C7u)) return use_table[u - 0x10FB0u + use_offset_0x10fb0u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
       if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
       if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
       if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
@@ -1135,7 +1209,7 @@
       break;
 
     case 0x16u:
-      if (hb_in_range<hb_codepoint_t> (u, 0x16B00u, 0x16B37u)) return use_table[u - 0x16B00u + use_offset_0x16b00u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x16AC0u, 0x16B37u)) return use_table[u - 0x16AC0u + use_offset_0x16ac0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x16F00u, 0x16F97u)) return use_table[u - 0x16F00u + use_offset_0x16f00u];
       if (hb_in_range<hb_codepoint_t> (u, 0x16FE0u, 0x16FE7u)) return use_table[u - 0x16FE0u + use_offset_0x16fe0u];
       break;
@@ -1150,10 +1224,14 @@
 
     case 0x1Eu:
       if (hb_in_range<hb_codepoint_t> (u, 0x1E100u, 0x1E14Fu)) return use_table[u - 0x1E100u + use_offset_0x1e100u];
-      if (hb_in_range<hb_codepoint_t> (u, 0x1E2C0u, 0x1E2FFu)) return use_table[u - 0x1E2C0u + use_offset_0x1e2c0u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x1E290u, 0x1E2FFu)) return use_table[u - 0x1E290u + use_offset_0x1e290u];
       if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E95Fu)) return use_table[u - 0x1E900u + use_offset_0x1e900u];
       break;
 
+    case 0xE0u:
+      if (hb_in_range<hb_codepoint_t> (u, 0xE0100u, 0xE01EFu)) return use_table[u - 0xE0100u + use_offset_0xe0100u];
+      break;
+
     default:
       break;
   }
@@ -1161,6 +1239,7 @@
 }
 
 #undef B
+#undef CGJ
 #undef CS
 #undef G
 #undef GB
@@ -1171,7 +1250,6 @@
 #undef N
 #undef O
 #undef R
-#undef S
 #undef SB
 #undef SE
 #undef SUB
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index 1e4804c..70b6379 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -257,7 +257,6 @@
     use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F);
     switch (syllable_type)
     {
-      case use_independent_cluster:
       case use_symbol_cluster:
       case use_hieroglyph_cluster:
       case use_non_cluster:
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 0e215c2..4e8a4bc 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -150,23 +150,25 @@
    */
 
 #ifndef HB_NO_AAT_SHAPE
-  bool has_gsub = hb_ot_layout_has_substitution (face);
+  bool has_kerx = hb_aat_layout_has_positioning (face);
+  bool has_gsub = !apply_morx && hb_ot_layout_has_substitution (face);
 #endif
   bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
   if (false)
     ;
 #ifndef HB_NO_AAT_SHAPE
-  else if (hb_aat_layout_has_positioning (face) && !(has_gsub && has_gpos))
+  /* Prefer GPOS over kerx if GSUB is present;
+   * https://github.com/harfbuzz/harfbuzz/issues/3008 */
+  else if (has_kerx && !(has_gsub && has_gpos))
     plan.apply_kerx = true;
 #endif
-  else if (!apply_morx && has_gpos)
+  else if (has_gpos)
     plan.apply_gpos = true;
 
   if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos))
   {
-    /* Apparently Apple applies kerx if GPOS kern was not applied. */
 #ifndef HB_NO_AAT_SHAPE
-    if (hb_aat_layout_has_positioning (face))
+    if (has_kerx)
       plan.apply_kerx = true;
     else
 #endif
diff --git a/src/hb-ot-var-common.hh b/src/hb-ot-var-common.hh
new file mode 100644
index 0000000..0eafb94
--- /dev/null
+++ b/src/hb-ot-var-common.hh
@@ -0,0 +1,264 @@
+/*
+ * Copyright © 2021  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#ifndef HB_OT_VAR_COMMON_HH
+#define HB_OT_VAR_COMMON_HH
+
+#include "hb-ot-layout-common.hh"
+
+
+namespace OT {
+
+struct DeltaSetIndexMapFormat0
+{
+  friend struct DeltaSetIndexMap;
+
+  private:
+  DeltaSetIndexMapFormat0* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->start_embed (this);
+    if (unlikely (!out)) return_trace (nullptr);
+
+    unsigned total_size = min_size + mapCount * get_width ();
+    HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
+    if (unlikely (!p)) return_trace (nullptr);
+
+    memcpy (p, this, HBUINT8::static_size * total_size);
+    return_trace (out);
+  }
+
+  template <typename T>
+  bool serialize (hb_serialize_context_t *c, const T &plan)
+  {
+    unsigned int width = plan.get_width ();
+    unsigned int inner_bit_count = plan.get_inner_bit_count ();
+    const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
+
+    TRACE_SERIALIZE (this);
+    if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
+      return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
+
+    entryFormat = ((width-1)<<4)|(inner_bit_count-1);
+    mapCount = output_map.length;
+    HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
+    if (unlikely (!p)) return_trace (false);
+    for (unsigned int i = 0; i < output_map.length; i++)
+    {
+      unsigned int v = output_map[i];
+      unsigned int outer = v >> 16;
+      unsigned int inner = v & 0xFFFF;
+      unsigned int u = (outer << inner_bit_count) | inner;
+      for (unsigned int w = width; w > 0;)
+      {
+        p[--w] = u;
+        u >>= 8;
+      }
+      p += width;
+    }
+    return_trace (true);
+  }
+
+  uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
+  {
+    /* If count is zero, pass value unchanged.  This takes
+     * care of direct mapping for advance map. */
+    if (!mapCount)
+      return v;
+
+    if (v >= mapCount)
+      v = mapCount - 1;
+
+    unsigned int u = 0;
+    { /* Fetch it. */
+      unsigned int w = get_width ();
+      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
+      for (; w; w--)
+        u = (u << 8) + *p++;
+    }
+
+    { /* Repack it. */
+      unsigned int n = get_inner_bit_count ();
+      unsigned int outer = u >> n;
+      unsigned int inner = u & ((1 << n) - 1);
+      u = (outer<<16) | inner;
+    }
+
+    return u;
+  }
+
+  unsigned get_map_count () const       { return mapCount; }
+  unsigned get_width () const           { return ((entryFormat >> 4) & 3) + 1; }
+  unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
+
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  c->check_range (mapDataZ.arrayZ,
+                                  mapCount,
+                                  get_width ()));
+  }
+
+  protected:
+  HBUINT8       format;         /* Format identifier--format = 0 */
+  HBUINT8       entryFormat;    /* A packed field that describes the compressed
+                                 * representation of delta-set indices. */
+  HBUINT16      mapCount;       /* The number of mapping entries. */
+  UnsizedArrayOf<HBUINT8>
+                mapDataZ;       /* The delta-set index mapping data. */
+
+  public:
+  DEFINE_SIZE_ARRAY (4, mapDataZ);
+};
+
+struct DeltaSetIndexMapFormat1
+{
+  friend struct DeltaSetIndexMap;
+
+  private:
+  DeltaSetIndexMapFormat1* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->start_embed (this);
+    if (unlikely (!out)) return_trace (nullptr);
+
+    unsigned total_size = min_size + mapCount * get_width ();
+    HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
+    if (unlikely (!p)) return_trace (nullptr);
+
+    memcpy (p, this, HBUINT8::static_size * total_size);
+    return_trace (out);
+  }
+
+  unsigned get_map_count () const       { return mapCount; }
+  unsigned get_width () const           { return ((entryFormat >> 4) & 3) + 1; }
+  unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  c->check_range (mapDataZ.arrayZ,
+                                  mapCount,
+                                  get_width ()));
+  }
+
+  protected:
+  HBUINT8       format;         /* Format identifier--format = 1 */
+  HBUINT8       entryFormat;    /* A packed field that describes the compressed
+                                 * representation of delta-set indices. */
+  HBUINT32      mapCount;       /* The number of mapping entries. */
+  UnsizedArrayOf<HBUINT8>
+                mapDataZ;       /* The delta-set index mapping data. */
+
+  public:
+  DEFINE_SIZE_ARRAY (6, mapDataZ);
+};
+
+struct DeltaSetIndexMap
+{
+  template <typename T>
+  bool serialize (hb_serialize_context_t *c, const T &plan)
+  {
+    TRACE_SERIALIZE (this);
+    switch (u.format) {
+    case 0: return_trace (u.format0.serialize (c, plan));
+    default:return_trace (false);
+    }
+  }
+
+  uint32_t map (unsigned v) const
+  {
+    switch (u.format) {
+    case 0: return (u.format0.map (v));
+    default:return v;
+    }
+  }
+
+  unsigned get_map_count () const
+  {
+    switch (u.format) {
+    case 0: return u.format0.get_map_count ();
+    case 1: return u.format1.get_map_count ();
+    default:return 0;
+    }
+  }
+
+  unsigned get_width () const
+  {
+    switch (u.format) {
+    case 0: return u.format0.get_width ();
+    case 1: return u.format1.get_width ();
+    default:return 0;
+    }
+  }
+
+  unsigned get_inner_bit_count () const
+  {
+    switch (u.format) {
+    case 0: return u.format0.get_inner_bit_count ();
+    case 1: return u.format1.get_inner_bit_count ();
+    default:return 0;
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 0: return_trace (u.format0.sanitize (c));
+    case 1: return_trace (u.format1.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    switch (u.format) {
+    case 0: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c)));
+    case 1: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c)));
+    default:return_trace (nullptr);
+    }
+  }
+
+  protected:
+  union {
+  HBUINT8                       format;         /* Format identifier */
+  DeltaSetIndexMapFormat0       format0;
+  DeltaSetIndexMapFormat1       format1;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (1, format);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_VAR_COMMON_HH */
diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh
index 72217e7..074b6a3 100644
--- a/src/hb-ot-var-hvar-table.hh
+++ b/src/hb-ot-var-hvar-table.hh
@@ -28,97 +28,11 @@
 #define HB_OT_VAR_HVAR_TABLE_HH
 
 #include "hb-ot-layout-common.hh"
-
+#include "hb-ot-var-common.hh"
 
 namespace OT {
 
 
-struct DeltaSetIndexMap
-{
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  c->check_range (mapDataZ.arrayZ,
-				  mapCount,
-				  get_width ()));
-  }
-
-  template <typename T>
-  bool serialize (hb_serialize_context_t *c, const T &plan)
-  {
-    unsigned int width = plan.get_width ();
-    unsigned int inner_bit_count = plan.get_inner_bit_count ();
-    const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
-
-    TRACE_SERIALIZE (this);
-    if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
-      return_trace (false);
-    if (unlikely (!c->extend_min (this))) return_trace (false);
-
-    format = ((width-1)<<4)|(inner_bit_count-1);
-    mapCount = output_map.length;
-    HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
-    if (unlikely (!p)) return_trace (false);
-    for (unsigned int i = 0; i < output_map.length; i++)
-    {
-      unsigned int v = output_map[i];
-      unsigned int outer = v >> 16;
-      unsigned int inner = v & 0xFFFF;
-      unsigned int u = (outer << inner_bit_count) | inner;
-      for (unsigned int w = width; w > 0;)
-      {
-	p[--w] = u;
-	u >>= 8;
-      }
-      p += width;
-    }
-    return_trace (true);
-  }
-
-  uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
-  {
-    /* If count is zero, pass value unchanged.  This takes
-     * care of direct mapping for advance map. */
-    if (!mapCount)
-      return v;
-
-    if (v >= mapCount)
-      v = mapCount - 1;
-
-    unsigned int u = 0;
-    { /* Fetch it. */
-      unsigned int w = get_width ();
-      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
-      for (; w; w--)
-	u = (u << 8) + *p++;
-    }
-
-    { /* Repack it. */
-      unsigned int n = get_inner_bit_count ();
-      unsigned int outer = u >> n;
-      unsigned int inner = u & ((1 << n) - 1);
-      u = (outer<<16) | inner;
-    }
-
-    return u;
-  }
-
-  unsigned int get_map_count () const	    { return mapCount; }
-  unsigned int get_width () const           { return ((format >> 4) & 3) + 1; }
-  unsigned int get_inner_bit_count () const { return (format & 0xF) + 1; }
-
-  protected:
-  HBUINT16	format;		/* A packed field that describes the compressed
-				 * representation of delta-set indices. */
-  HBUINT16	mapCount;	/* The number of mapping entries. */
-  UnsizedArrayOf<HBUINT8>
-		mapDataZ;	/* The delta-set index mapping data. */
-
-  public:
-  DEFINE_SIZE_ARRAY (4, mapDataZ);
-};
-
 struct index_map_subset_plan_t
 {
   enum index_map_index_t {
diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh
index 288bae5..7339eeb 100644
--- a/src/hb-repacker.hh
+++ b/src/hb-repacker.hh
@@ -33,6 +33,10 @@
 #include "hb-serialize.hh"
 #include "hb-vector.hh"
 
+/*
+ * For a detailed writeup on the overflow resolution algorithm see:
+ * docs/repacker.md
+ */
 
 struct graph_t
 {
@@ -1111,6 +1115,9 @@
  * If necessary the structure of the graph may be modified in ways that do not
  * affect the functionality of the graph. For example shared objects may be
  * duplicated.
+ *
+ * For a detailed writeup describing how the algorithm operates see:
+ * docs/repacker.md
  */
 inline void
 hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed,
diff --git a/src/hb-style.cc b/src/hb-style.cc
index dfb1017..f1b44ce 100644
--- a/src/hb-style.cc
+++ b/src/hb-style.cc
@@ -113,7 +113,9 @@
   case HB_STYLE_TAG_WIDTH:
     return face->table.OS2->has_data ()
 	   ? face->table.OS2->get_width ()
-	   : (face->table.head->is_condensed () ? 75 : 100);
+	   : (face->table.head->is_condensed () ? 75 :
+	      face->table.head->is_expanded () ? 125 :
+	      100);
   case HB_STYLE_TAG_WEIGHT:
     return face->table.OS2->has_data ()
 	   ? face->table.OS2->usWeightClass
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 1bdf133..1e195ff 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -222,6 +222,39 @@
   cmap.fini ();
 }
 
+static void _colr_closure (hb_face_t *face,
+                           hb_map_t *layers_map,
+                           hb_map_t *palettes_map,
+                           hb_set_t *glyphs_colred)
+{
+  OT::COLR::accelerator_t colr;
+  colr.init (face);
+  if (!colr.is_valid ()) return;
+
+  unsigned iteration_count = 0;
+  hb_set_t palette_indices, layer_indices;
+  unsigned glyphs_num;
+  {
+    glyphs_num = glyphs_colred->get_population ();
+
+    // Collect all glyphs referenced by COLRv0
+    hb_set_t glyphset_colrv0;
+    for (hb_codepoint_t gid : glyphs_colred->iter ())
+      colr.closure_glyphs (gid, &glyphset_colrv0);
+    
+    glyphs_colred->union_ (glyphset_colrv0);
+    
+    //closure for COLRv1
+    colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
+  } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
+           glyphs_num != glyphs_colred->get_population ());
+
+  colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
+  _remap_indexes (&layer_indices, layers_map);
+  _remap_palette_indexes (&palette_indices, palettes_map);
+  colr.fini ();
+}
+
 static inline void
 _math_closure (hb_face_t           *face,
                hb_set_t            *glyphset)
@@ -313,12 +346,10 @@
 #ifndef HB_NO_SUBSET_CFF
   OT::cff1::accelerator_t cff;
 #endif
-  OT::COLR::accelerator_t colr;
   glyf.init (plan->source);
 #ifndef HB_NO_SUBSET_CFF
   cff.init (plan->source);
 #endif
-  colr.init (plan->source);
 
   plan->_glyphset_gsub->add (0); // Not-def
 
@@ -350,30 +381,13 @@
   _math_closure (plan->source, plan->_glyphset_mathed);
   _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
 
-  // Collect all glyphs referenced by COLRv0
-  hb_set_t* cur_glyphset = plan->_glyphset_mathed;
-  hb_set_t glyphset_colrv0;
-  if (colr.is_valid ())
-  {
-    glyphset_colrv0.union_ (*cur_glyphset);
-    for (hb_codepoint_t gid : cur_glyphset->iter ())
-      colr.closure_glyphs (gid, &glyphset_colrv0);
-    cur_glyphset = &glyphset_colrv0;
-  }
-
-  hb_set_t palette_indices;
-  colr.closure_V0palette_indices (cur_glyphset, &palette_indices);
-
-  hb_set_t layer_indices;
-  colr.closure_forV1 (cur_glyphset, &layer_indices, &palette_indices);
-  _remap_indexes (&layer_indices, plan->colrv1_layers);
-  _remap_palette_indexes (&palette_indices, plan->colr_palettes);
-  colr.fini ();
-  _remove_invalid_gids (cur_glyphset, plan->source->get_num_glyphs ());
+  hb_set_t cur_glyphset = *plan->_glyphset_mathed;
+  _colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
+  _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
 
   // Populate a full set of glyphs to retain by adding all referenced
   // composite glyphs.
-  for (hb_codepoint_t gid : cur_glyphset->iter ())
+  for (hb_codepoint_t gid : cur_glyphset.iter ())
   {
     glyf.add_gid_and_children (gid, plan->_glyphset);
 #ifndef HB_NO_SUBSET_CFF
diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh
index 0a79944..4c28bb0 100644
--- a/src/hb-unicode.hh
+++ b/src/hb-unicode.hh
@@ -121,7 +121,7 @@
   static hb_bool_t
   is_variation_selector (hb_codepoint_t unicode)
   {
-    /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
+    /* U+180B..180D, U+180F MONGOLIAN FREE VARIATION SELECTORs are handled in the
      * Arabic shaper.  No need to match them here. */
     return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
 						   0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
@@ -136,7 +136,7 @@
    * As such, we make exceptions for those four.
    * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
    *
-   * Unicode 7.0:
+   * Unicode 14.0:
    * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
    * 00AD          # Cf       SOFT HYPHEN
    * 034F          # Mn       COMBINING GRAPHEME JOINER
@@ -145,6 +145,7 @@
    * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
    * 180B..180D    # Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
    * 180E          # Cf       MONGOLIAN VOWEL SEPARATOR
+   * 180F          # Mn       MONGOLIAN FREE VARIATION SELECTOR FOUR
    * 200B..200F    # Cf   [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
    * 202A..202E    # Cf   [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
    * 2060..2064    # Cf   [5] WORD JOINER..INVISIBLE PLUS
diff --git a/src/hb.hh b/src/hb.hh
index 829b5a1..1f14267 100644
--- a/src/hb.hh
+++ b/src/hb.hh
@@ -62,6 +62,7 @@
 
 /* Error.  Should never happen. */
 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
+#pragma GCC diagnostic error   "-Wbitwise-instead-of-logical"
 #pragma GCC diagnostic error   "-Wcast-align"
 #pragma GCC diagnostic error   "-Wcast-function-type"
 #pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
diff --git a/src/meson.build b/src/meson.build
index e15da3a..7dca59e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -147,6 +147,7 @@
   'hb-ot-tag-table.hh',
   'hb-ot-tag.cc',
   'hb-ot-var-avar-table.hh',
+  'hb-ot-var-common.hh',
   'hb-ot-var-fvar-table.hh',
   'hb-ot-var-gvar-table.hh',
   'hb-ot-var-hvar-table.hh',
@@ -345,7 +346,7 @@
 if conf.get('HAVE_GRAPHITE2', 0) == 1
   hb_sources += hb_graphite2_sources
   hb_headers += hb_graphite2_headers
-  harfbuzz_deps += [graphite2_dep]
+  harfbuzz_deps += [graphite2_dep, graphite_dep]
 endif
 
 if conf.get('HAVE_GLIB', 0) == 1
diff --git a/src/ms-use/IndicPositionalCategory-Additional.txt b/src/ms-use/IndicPositionalCategory-Additional.txt
index 8d325ad..83a164e 100644
--- a/src/ms-use/IndicPositionalCategory-Additional.txt
+++ b/src/ms-use/IndicPositionalCategory-Additional.txt
@@ -1,11 +1,12 @@
 # Override values For Indic_Positional_Category
 # Not derivable
 # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
-# Updated  for Unicode 10.0 by Andrew Glass 2017-07-25
+# Updated for Unicode 10.0 by Andrew Glass 2017-07-25
 # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
-# Updated  for L2/19-083    by Andrew Glass 2019-05-06
-# Updated  for Unicode 12.1 by Andrew Glass 2019-05-30
-# Updated  for Unicode 13.0 by Andrew Glass 2020-07-28
+# Updated for L2/19-083    by Andrew Glass 2019-05-06
+# Updated for Unicode 12.1 by Andrew Glass 2019-05-30
+# Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+# Updated for Unicode 14.0 by Andrew Glass 2021-09-28
 
 # ================================================
 # ================================================
@@ -14,39 +15,39 @@
 # ================================================
 
 # Indic_Positional_Category=Bottom
-0F72        ; Bottom  # Mn      TIBETAN VOWEL SIGN I # Not really below, but need to override to fit into Universal model
-0F7A..0F7D  ; Bottom  # Mn  [4] TIBETAN VOWEL SIGN E..TIBETAN VOWEL SIGN OO # Not really below, but need to override to fit into Universal model
-0F80        ; Bottom  # Mn      TIBETAN VOWEL SIGN REVERSED I # Not really below, but need to override to fit into Universal model
-A9BF        ; Bottom  # Mc      JAVANESE CONSONANT SIGN CAKRA
-11127..11129; Bottom  # Mn  [3] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN II
-1112D       ; Bottom  # Mn      CHAKMA VOWEL SIGN AI
-11130       ; Bottom  # Mn      CHAKMA VOWEL SIGN OI
+0F72          ; Bottom  # Mn      TIBETAN VOWEL SIGN I # Not really below, but need to override to fit into Universal model
+0F7A..0F7D    ; Bottom  # Mn  [4] TIBETAN VOWEL SIGN E..TIBETAN VOWEL SIGN OO # Not really below, but need to override to fit into Universal model
+0F80          ; Bottom  # Mn      TIBETAN VOWEL SIGN REVERSED I # Not really below, but need to override to fit into Universal model
+A9BF          ; Bottom  # Mc      JAVANESE CONSONANT SIGN CAKRA
+11127..11129  ; Bottom  # Mn  [3] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN II
+1112D         ; Bottom  # Mn      CHAKMA VOWEL SIGN AI
+11130         ; Bottom  # Mn      CHAKMA VOWEL SIGN OI
 
 # ================================================
 
 # Indic_Positional_Category=Left
-1C29        ; Left    # Mc      LEPCHA VOWEL SIGN OO  # Reduced from Top_And_Left
+1C29          ; Left    # Mc      LEPCHA VOWEL SIGN OO  # Reduced from Top_And_Left
 
 # ================================================
 
 
 # Indic_Positional_Category=Right
-A9BE        ; Right   # Mc      JAVANESE CONSONANT SIGN PENGKAL # Reduced from Bottom_And_Right
-10A0C       ; Right   # Mn      KHAROSHTHI VOWEL LENGTH MARK    # Follows vowels and precedes vowel modifiers
-11942       ; Right   # Mc      DIVES AKURU MEDIAL RA           # Reduced from Bottom_And_Right
+A9BE          ; Right   # Mc      JAVANESE CONSONANT SIGN PENGKAL # Reduced from Bottom_And_Right
+10A0C         ; Right   # Mn      KHAROSHTHI VOWEL LENGTH MARK    # Follows vowels and precedes vowel modifiers
+11942         ; Right   # Mc      DIVES AKURU MEDIAL RA           # Reduced from Bottom_And_Right
 
 # ================================================
 
 # Indic_Positional_Category=Top
-0F74         ; Top   # Mn       TIBETAN VOWEL SIGN U # Not really above, but need to override to fit into Universal model
-1A18         ; Top   # Mn       BUGINESE VOWEL SIGN U # Workaround to allow below to occur before above by treating all below marks as above
-AA35         ; Top   # Mn       CHAM CONSONANT SIGN
+0F74          ; Top     # Mn       TIBETAN VOWEL SIGN U # Not really above, but need to override to fit into Universal model
+1A18          ; Top     # Mn       BUGINESE VOWEL SIGN U # Workaround to allow below to occur before above by treating all below marks as above
+AA35          ; Top     # Mn       CHAM CONSONANT SIGN
 
 # ================================================
 
 # Indic_Positional_Category=Top_And_Right
-0E33    ; Top_And_Right # Lo       THAI CHARACTER SARA AM # IMC has Right, which seems to be a mistake.
-0EB3    ; Top_And_Right # Lo       LAO VOWEL SIGN AM # IMC has Right, which seems to be a mistake.
+0E33          ; Top_And_Right # Lo       THAI CHARACTER SARA AM # IMC has Right, which seems to be a mistake.
+0EB3          ; Top_And_Right # Lo       LAO VOWEL SIGN AM # IMC has Right, which seems to be a mistake.
 
 # ================================================
 # ================================================
@@ -55,41 +56,46 @@
 # ================================================
 
 # Indic_Positional_Category=Bottom
-0859..085B   ; Bottom # Mn   [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
-18A9         ; Bottom # Mn       MONGOLIAN LETTER ALI GALI DAGALGA
-10AE5        ; Bottom # Mn       MANICHAEAN ABBREVIATION MARK ABOVE # Not really bottom, but here for ccc to control
-10AE6        ; Bottom # Mn       MANICHAEAN ABBREVIATION MARK BELOW
-10F46..10F47 ; Bottom # Mn   [2] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING TWO DOTS BELOW
-10F48..10F4A ; Bottom # Mn   [3] SOGDIAN COMBINING DOT ABOVE..SOGDIAN COMBINING CURVE ABOVE # Overriden to below because ccc-based Normalization controls order
-10F4B        ; Bottom # Mn       SOGDIAN COMBINING CURVE BELOW
-10F4C        ; Bottom # Mn       SOGDIAN COMBINING HOOK ABOVE # Overriden to below because ccc-based Normalization controls order
-10F4D..10F50 ; Bottom # Mn   [4] SOGDIAN COMBINING HOOK BELOW..SOGDIAN COMBINING STROKE BELOW
-16F4F        ; Bottom # Mn       MIAO SIGN CONSONANT MODIFIER BAR
-16F51..16F87 ; Bottom # Mc  [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
-16F8F..16F92 ; Bottom # Mn   [4] MIAO TONE RIGHT..MIAO TONE BELOW
+0859..085B    ; Bottom # Mn   [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
+18A9          ; Bottom # Mn       MONGOLIAN LETTER ALI GALI DAGALGA
+10AE5         ; Bottom # Mn       MANICHAEAN ABBREVIATION MARK ABOVE  # Overriden, ccc controls order
+10AE6         ; Bottom # Mn       MANICHAEAN ABBREVIATION MARK BELOW
+10F46..10F47  ; Bottom # Mn   [2] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING TWO DOTS BELOW
+10F48..10F4A  ; Bottom # Mn   [3] SOGDIAN COMBINING DOT ABOVE..SOGDIAN COMBINING CURVE ABOVE     # Overriden, ccc controls order
+10F4B         ; Bottom # Mn       SOGDIAN COMBINING CURVE BELOW
+10F4C         ; Bottom # Mn       SOGDIAN COMBINING HOOK ABOVE        # Overriden, ccc controls order
+10F4D..10F50  ; Bottom # Mn   [4] SOGDIAN COMBINING HOOK BELOW..SOGDIAN COMBINING STROKE BELOW
+10F82         ; Bottom # Mn       OLD UYGHUR COMBINING DOT ABOVE      # Overriden, ccc controls order
+10F83         ; Bottom # Mn       OLD UYGHUR COMBINING DOT BELOW
+10F84         ; Bottom # Mn       OLD UYGHUR COMBINING TWO DOTS ABOVE # Overriden, ccc controls order
+10F85         ; Bottom # Mn       OLD UYGHUR COMBINING TWO DOTS BELOW
+16F4F         ; Bottom # Mn       MIAO SIGN CONSONANT MODIFIER BAR
+16F51..16F87  ; Bottom # Mc  [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
+16F8F..16F92  ; Bottom # Mn   [4] MIAO TONE RIGHT..MIAO TONE BELOW
 
 # ================================================
 
 # Indic_Positional_Category=Left
-103C          ; Left # Mc       MYANMAR CONSONANT SIGN MEDIAL RA
+103C          ; Left   # Mc       MYANMAR CONSONANT SIGN MEDIAL RA
 
 # ================================================
 
 # Indic_Positional_Category=Top
-07EB..07F3   ; Top   # Mn   [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
-07FD         ; Top   # Mn       NKO DANTAYALAN # Not really top, but assigned here to allow ccc to control mark order
-1885..1886   ; Top   # Mn   [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
-10EAB..10EAC ; Top   # Mn   [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
-1E944..1E94A ; Top   # Mn   [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
-10D24..10D27 ; Top   # Mn   [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
-16B30..16B36 ; Top   # Mn   [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
-1E130..1E136 ; Top   # Mn   [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
-1E2EC..1E2EF ; Top   # Mn   [4] WANCHO TONE TUP..WANCHO TONE KOINI
+07EB..07F3    ; Top   # Mn   [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
+07FD          ; Top   # Mn       NKO DANTAYALAN # Not really top, but assigned here to allow ccc to control mark order
+1885..1886    ; Top   # Mn   [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
+10D24..10D27  ; Top   # Mn   [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
+10EAB..10EAC  ; Top   # Mn   [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
+16B30..16B36  ; Top   # Mn   [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
+1E130..1E136  ; Top   # Mn   [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
+1E2AE         ; Top   # Mn       TOTO SIGN RISING TONE
+1E2EC..1E2EF  ; Top   # Mn   [4] WANCHO TONE TUP..WANCHO TONE KOINI
+1E944..1E94A  ; Top   # Mn   [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
 
 # ================================================
 
 # Indic_Positional_Category=Overstruck
-1BC9D..1BC9E ; Overstruck # Mn  [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
+1BC9D..1BC9E  ; Overstruck # Mn  [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
 
 # ================================================
 # ================================================
@@ -98,5 +104,6 @@
 # ================================================
 
 # Indic_Positional_Category=NA
-180B..180D ; NA        # Mn  [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
-2D7F       ; NA        # Mn      TIFINAGH CONSONANT JOINER
+180B..180D   ; NA        # Mn  [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+180F         ; NA        # Mn      MONGOLIAN FREE VARIATION SELECTOR FOUR
+2D7F         ; NA        # Mn      TIFINAGH CONSONANT JOINER
diff --git a/src/ms-use/IndicSyllabicCategory-Additional.txt b/src/ms-use/IndicSyllabicCategory-Additional.txt
index 0912055..8bcada3 100644
--- a/src/ms-use/IndicSyllabicCategory-Additional.txt
+++ b/src/ms-use/IndicSyllabicCategory-Additional.txt
@@ -1,9 +1,10 @@
 # Override values For Indic_Syllabic_Category
 # Not derivable
 # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
-# Updated  for Unicode 10.0 by Andrew Glass 2017-07-25
-# Updated  for Unicode 12.1 by Andrew Glass 2019-05-24
-# Updated  for Unicode 13.0 by Andrew Glass 2020-07-28
+# Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+# Updated for Unicode 12.1 by Andrew Glass 2019-05-24
+# Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+# Updated for Unicode 14.0 by Andrew Glass 2021-09-25
 
 # ================================================
 # OVERRIDES TO ASSIGNED VALUES
@@ -17,28 +18,28 @@
 # ================================================
 
 # Indic_Syllabic_Category=Consonant
-0840..0858   ; Consonant # Lo  [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN
-0F00..0F01   ; Consonant # Lo   [2] TIBETAN SYLLABLE OM..TIBETAN MARK GTER YIG MGO TRUNCATED
-0F04..0F06   ; Consonant # Po       TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK CARET YIG MGO PHUR SHAD MA
-19C1..19C7   ; Consonant # Lo   [7] NEW TAI LUE LETTER FINAL V..NEW TAI LUE LETTER FINAL B # Reassigned to avoid clustering with a base consonant
-25CC         ; Consonant # So       DOTTED CIRCLE
+0840..0858    ; Consonant # Lo  [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN
+0F00..0F01    ; Consonant # Lo   [2] TIBETAN SYLLABLE OM..TIBETAN MARK GTER YIG MGO TRUNCATED
+0F04..0F06    ; Consonant # Po       TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK CARET YIG MGO PHUR SHAD MA
+19C1..19C7    ; Consonant # Lo   [7] NEW TAI LUE LETTER FINAL V..NEW TAI LUE LETTER FINAL B # Reassigned to avoid clustering with a base consonant
+25CC          ; Consonant # So       DOTTED CIRCLE
 
 # ================================================
 
 # Indic_Syllabic_Category=Consonant_Dead
-0F7F         ; Consonant_Dead    # Mc       TIBETAN SIGN RNAM BCAD # reassigned so that visarga will form an independent cluster
+0F7F          ; Consonant_Dead    # Mc       TIBETAN SIGN RNAM BCAD # reassigned so that visarga will form an independent cluster
 
 # ================================================
 
 # Indic_Syllabic_Category=Consonant_Final
-0F35         ; Consonant_Final   # Mn       TIBETAN MARK NGAS BZUNG NYI ZLA
-0F37         ; Consonant_Final   # Mn       TIBETAN MARK NGAS BZUNG SGOR RTAGS
-0FC6         ; Consonant_Final   # Mn       TIBETAN SYMBOL PADMA GDAN
+0F35          ; Consonant_Final   # Mn       TIBETAN MARK NGAS BZUNG NYI ZLA
+0F37          ; Consonant_Final   # Mn       TIBETAN MARK NGAS BZUNG SGOR RTAGS
+0FC6          ; Consonant_Final   # Mn       TIBETAN SYMBOL PADMA GDAN
 
 # ================================================
 
 # Indic_Syllabic_Category=Consonant_Final_Modifier
-1C36     ; Consonant_Final_Modifier  # Mn   LEPCHA SIGN RAN
+1C36          ; Consonant_Final_Modifier  # Mn   LEPCHA SIGN RAN
 
 # ================================================
 
@@ -54,9 +55,8 @@
 # ================================================
 
 # Indic_Syllabic_Category=Tone_Mark
-A982         ; Tone_Mark         # Mn       JAVANESE SIGN LAYAR# Not a repha, because it does not reorder to front of cluster
-1A7B..1A7C   ; Tone_Mark         # Mn   [2] TAI THAM SIGN MAI SAM..TAI THAM SIGN KHUEN-LUE KARAN
-1A7F         ; Tone_Mark         # Mn       TAI THAM COMBINING CRYPTOGRAMMIC DOT
+1A7B..1A7C    ; Tone_Mark         # Mn   [2] TAI THAM SIGN MAI SAM..TAI THAM SIGN KHUEN-LUE KARAN
+1A7F          ; Tone_Mark         # Mn       TAI THAM COMBINING CRYPTOGRAMMIC DOT
 
 # ================================================
 
@@ -72,41 +72,50 @@
 # ================================================
 
 # Indic_Syllabic_Category=Consonant
-0800..0815   ; Consonant # Lo   [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF
-1800         ; Consonant # Po        MONGOLIAN BIRGA # Reassigned so that legacy Birga + MFVS sequences still work
-1807         ; Consonant # Po        MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER
-180A         ; Consonant # Po        MONGOLIAN NIRUGU
-1820..1878   ; Consonant # Lo   [88] MONGOLIAN LETTER A..MONGOLIAN LETTER CHA WITH TWO DOTS
-1843         ; Consonant # Lm        MONGOLIAN LETTER TODO LONG VOWEL SIGN
-2D30..2D67   ; Consonant # Lo   [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO
-2D6F         ; Consonant # Lm        TIFINAGH MODIFIER LETTER LABIALIZATION MARK
-10AC0..10AC7 ; Consonant # Lo    [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW
-10AC9..10AE4 ; Consonant # Lo   [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW
-10D00..10D23 ; Consonant # Lo   [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA
-10E80..10EA9 ; Consonant # Lo   [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET
-10EB0..10EB1 ; Consonant # Lo    [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE
-10F30..10F45 ; Consonant # Lo   [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN
-111DA        ; Consonant # Lo        SHARADA EKAM
-#HIEROGLYPHS moved to new category
-#13000..1342E ; Consonant # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032
+0800..0815    ; Consonant # Lo   [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF
+1800          ; Consonant # Po        MONGOLIAN BIRGA # Reassigned so that legacy Birga + MFVS sequences still work
+1807          ; Consonant # Po        MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER
+180A          ; Consonant # Po        MONGOLIAN NIRUGU
+1820..1878    ; Consonant # Lo   [88] MONGOLIAN LETTER A..MONGOLIAN LETTER CHA WITH TWO DOTS
+1843          ; Consonant # Lm        MONGOLIAN LETTER TODO LONG VOWEL SIGN
+2D30..2D67    ; Consonant # Lo   [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO
+2D6F          ; Consonant # Lm        TIFINAGH MODIFIER LETTER LABIALIZATION MARK
+10570..1057A  ; Consonant # Lo   [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA
+1057C..1058A  ; Consonant # Lo   [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE
+1058C..10592  ; Consonant # Lo    [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE
+10594..10595  ; Consonant # Lo    [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE
+10597..105A1  ; Consonant # Lo   [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA
+105A3..105B1  ; Consonant # Lo   [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE
+105B3..105B9  ; Consonant # Lo    [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE
+105BB..105BC  ; Consonant # Lo    [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE
+10AC0..10AC7  ; Consonant # Lo    [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW
+10AC9..10AE4  ; Consonant # Lo   [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW
+10D00..10D23  ; Consonant # Lo   [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA
+10E80..10EA9  ; Consonant # Lo   [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET
+10EB0..10EB1  ; Consonant # Lo    [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE
+10F30..10F45  ; Consonant # Lo   [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN
+111DA         ; Consonant # Lo        SHARADA EKAM
+#HIEROGLYPHS to be moved to new category
+13000..1342E  ; Consonant # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032
 #For the Begin and End segment to be handled fully correctly, the cluster model needs to be modified.
-#13437..13438 ; Consonant # Lo    [2] EGYPTIAN HIEROGLYPH BEGIN SEGMENT..EGYPTIAN HIEROGLYPH END SEGMENT
-16B00..16B2F ; Consonant # Lo   [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU
-16F00..16F4A ; Consonant # Lo   [75] MIAO LETTER PA..MIAO LETTER RTE
-16FE4        ; Consonant # Mn        KHITAN SMALL SCRIPT FILLER
-18B00..18CD5 ; Consonant # Lo  [470] KHITAN SMALL SCRIPT CHARACTER-18B00..KHITAN SMALL SCRIPT CHARACTER-18CD5
-1BC00..1BC6A ; Consonant # Lo  [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M
-1BC70..1BC7C ; Consonant # Lo   [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK 
-1BC80..1BC88 ; Consonant # Lo    [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL
-1BC90..1BC99 ; Consonant # Lo   [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW
-1E100..1E12C ; Consonant # Lo   [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W
-1E137..1E13D ; Consonant # Lm    [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER
-1E14E        ; Consonant # Lo        NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ
-1E14F        ; Consonant # So        NYIAKENG PUACHUE HMONG CIRCLED CA
-1E2C0..1E2EB ; Consonant # Lo   [44] WANCHO LETTER AA..WANCHO LETTER YIH
-1E900..1E921 ; Consonant # Lu   [34] ADLAM CAPITAL LETTER ALIF..ADLAM CAPITAL LETTER SHA
-1E922..1E943 ; Consonant # Ll   [34] ADLAM SMALL LETTER ALIF..ADLAM SMALL LETTER SHA
-1E94B        ; Consonant # Lm        ADLAM NASALIZATION MARK
+13437..13438  ; Consonant # Lo    [2] EGYPTIAN HIEROGLYPH BEGIN SEGMENT..EGYPTIAN HIEROGLYPH END SEGMENT
+16B00..16B2F  ; Consonant # Lo   [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU
+16F00..16F4A  ; Consonant # Lo   [75] MIAO LETTER PA..MIAO LETTER RTE
+16FE4         ; Consonant # Mn        KHITAN SMALL SCRIPT FILLER          # Avoids Mn pushing this into VOWEL class
+18B00..18CD5  ; Consonant # Lo  [470] KHITAN SMALL SCRIPT CHARACTER-18B00..KHITAN SMALL SCRIPT CHARACTER-18CD5
+1BC00..1BC6A  ; Consonant # Lo  [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M
+1BC70..1BC7C  ; Consonant # Lo   [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK 
+1BC80..1BC88  ; Consonant # Lo    [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL
+1BC90..1BC99  ; Consonant # Lo   [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW
+1E100..1E12C  ; Consonant # Lo   [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W
+1E137..1E13D  ; Consonant # Lm    [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER
+1E14E         ; Consonant # Lo        NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ
+1E14F         ; Consonant # So        NYIAKENG PUACHUE HMONG CIRCLED CA
+1E290..1E2AD  ; Consonant # Lo   [30] TOTO LETTER PA..TOTO LETTER A
+1E2C0..1E2EB  ; Consonant # Lo   [44] WANCHO LETTER AA..WANCHO LETTER YIH
+1E900..1E921  ; Consonant # Lu   [34] ADLAM CAPITAL LETTER ALIF..ADLAM CAPITAL LETTER SHA
+1E922..1E943  ; Consonant # Ll   [34] ADLAM SMALL LETTER ALIF..ADLAM SMALL LETTER SHA
+1E94B         ; Consonant # Lm        ADLAM NASALIZATION MARK
 
 # ================================================
 
@@ -116,13 +125,13 @@
 # ================================================
 
 # Indic_Syllabic_Category=Gemination_Mark
-10D27      ; Gemination_Mark # Mn       HANIFI ROHINGYA SIGN TASSI
+10D27         ; Gemination_Mark   # Mn       HANIFI ROHINGYA SIGN TASSI
 
 # ================================================
 
 # Indic_Syllabic_Category=Modifying_Letter
-FE00..FE0F   ; Modifying_Letter  # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16# Need to treat them as isolated bases so they don't merge with a cluster in invalid scenarios
-16F50        ; Modifying_Letter  # Lo       MIAO LETTER NASALIZATION
+FE00..FE0F    ; Modifying_Letter  # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16# Need to treat them as isolated bases so they don't merge with a cluster in invalid scenarios
+16F50         ; Modifying_Letter  # Lo       MIAO LETTER NASALIZATION
 
 # ================================================
 
@@ -136,49 +145,52 @@
 16F4F         ; Nukta            # Mn       MIAO SIGN CONSONANT MODIFIER BAR
 1BC9D..1BC9E  ; Nukta            # Mn   [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
 1E944..1E94A  ; Nukta            # Mn   [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
+10F82..10F85  ; Nukta            # Mn   [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW
 
 # ================================================
 
 # Indic_Syllabic_Category=Number
-10D30..10D39 ; Number              # Nd  [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE
-10F51..10F54 ; Number              # No   [4] SOGDIAN NUMBER ONE..SOGDIAN NUMBER ONE HUNDRED
-1E140..1E149 ; Number              # Nd  [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE
-1E2F0..1E2F9 ; Number              # Nd  [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE
-1E950..1E959 ; Number              # Nd  [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE
+10D30..10D39  ; Number              # Nd  [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE
+10F51..10F54  ; Number              # No   [4] SOGDIAN NUMBER ONE..SOGDIAN NUMBER ONE HUNDRED
+16AC0..16AC9  ; Number              # Nd  [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE
+1E140..1E149  ; Number              # Nd  [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE
+1E2F0..1E2F9  ; Number              # Nd  [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE
+1E950..1E959  ; Number              # Nd  [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE
 
 # ================================================
 
 # Indic_Syllabic_Category=Tone_Mark
-07EB..07F3   ; Tone_Mark           # Mn   [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
-07FD         ; Tone_Mark           # Mn       NKO DANTAYALAN
-0F86..0F87   ; Tone_Mark           # Mn   [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS
-17CF         ; Tone_Mark           # Mn       KHMER SIGN AHSDA
-10D24..10D26 ; Tone_Mark           # Mn   [3] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TANA
-10F46..10F50 ; Tone_Mark           # Mn  [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
-16B30..16B36 ; Tone_Mark           # Mn   [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
-16F8F..16F92 ; Tone_Mark           # Mn   [4] MIAO TONE RIGHT..MIAO TONE BELOW
-1E130..1E136 ; Tone_Mark           # Mn   [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
-1E2EC..1E2EF ; Tone_Mark           # Mn   [4] WANCHO TONE TUP..WANCHO TONE KOINI
+07EB..07F3    ; Tone_Mark           # Mn   [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
+07FD          ; Tone_Mark           # Mn       NKO DANTAYALAN
+0F86..0F87    ; Tone_Mark           # Mn   [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS
+17CF          ; Tone_Mark           # Mn       KHMER SIGN AHSDA
+10D24..10D26  ; Tone_Mark           # Mn   [3] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TANA
+10F46..10F50  ; Tone_Mark           # Mn  [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
+16B30..16B36  ; Tone_Mark           # Mn   [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
+16F8F..16F92  ; Tone_Mark           # Mn   [4] MIAO TONE RIGHT..MIAO TONE BELOW
+1E130..1E136  ; Tone_Mark           # Mn   [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
+1E2AE         ; Tone_Mark           # Mn       TOTO SIGN RISING TONE
+1E2EC..1E2EF  ; Tone_Mark           # Mn   [4] WANCHO TONE TUP..WANCHO TONE KOINI
 
 # ================================================
 
 # Indic_Syllabic_Category=Virama
-2D7F         ; Virama              # Mn       TIFINAGH CONSONANT JOINER
-13430..13436 ; Virama              # Cf   [7] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH OVERLAY MIDDLE
+2D7F          ; Virama              # Mn       TIFINAGH CONSONANT JOINER
+13430..13436  ; Virama              # Cf   [7] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH OVERLAY MIDDLE
 
 # ================================================
 
 # Indic_Syllabic_Category=Vowel_Independent
-AAB1         ; Vowel_Independent   # Lo       TAI VIET VOWEL AA
-AABA         ; Vowel_Independent   # Lo       TAI VIET VOWEL UA
-AABD         ; Vowel_Independent   # Lo       TAI VIET VOWEL AN
+AAB1          ; Vowel_Independent   # Lo       TAI VIET VOWEL AA
+AABA          ; Vowel_Independent   # Lo       TAI VIET VOWEL UA
+AABD          ; Vowel_Independent   # Lo       TAI VIET VOWEL AN
 
 # ================================================
 
 # Indic_Syllabic_Category=Vowel_Dependent
-0B55          ; Vowel_Dependent   # Mn       ORIYA SIGN OVERLINE
-10EAB..10EAC  ; Vowel_Dependent   # Mn   [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
-16F51..16F87  ; Vowel_Dependent   # Mc  [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
+0B55          ; Vowel_Dependent     # Mn       ORIYA SIGN OVERLINE
+10EAB..10EAC  ; Vowel_Dependent     # Mn   [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
+16F51..16F87  ; Vowel_Dependent     # Mc  [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
 
 # ================================================
 # ================================================
diff --git a/src/update-unicode-tables.make b/src/update-unicode-tables.make
index f31b34e..8c2eaa4 100755
--- a/src/update-unicode-tables.make
+++ b/src/update-unicode-tables.make
@@ -21,7 +21,7 @@
 	./$^ > $@ || ($(RM) $@; false)
 hb-ucd-table.hh: gen-ucd-table.py ucd.nounihan.grouped.zip hb-common.h
 	./$^ > $@ || ($(RM) $@; false)
-hb-ot-shape-complex-use-table.hh: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt ArabicShaping.txt Blocks.txt ms-use/IndicSyllabicCategory-Additional.txt ms-use/IndicPositionalCategory-Additional.txt
+hb-ot-shape-complex-use-table.hh: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt ms-use/IndicSyllabicCategory-Additional.txt ms-use/IndicPositionalCategory-Additional.txt
 	./$^ > $@ || ($(RM) $@; false)
 hb-ot-shape-complex-vowel-constraints.cc: gen-vowel-constraints.py ms-use/IndicShapingInvalidCluster.txt Scripts.txt
 	./$^ > $@ || ($(RM) $@; false)
@@ -29,28 +29,18 @@
 packtab:
 	/usr/bin/env python3 -c "import packTab" 2>/dev/null || /usr/bin/env python3 -m pip install git+https://github.com/harfbuzz/packtab
 
-ArabicShaping.txt:
-	curl -O https://unicode.org/Public/UCD/latest/ucd/ArabicShaping.txt
-UnicodeData.txt:
-	curl -O https://unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
-Blocks.txt:
-	curl -O https://unicode.org/Public/UCD/latest/ucd/Blocks.txt
+ArabicShaping.txt DerivedCoreProperties.txt IndicPositionalCategory.txt IndicSyllabicCategory.txt Scripts.txt UnicodeData.txt:
+	curl -O https://unicode.org/Public/UCD/latest/ucd/$@
 emoji-data.txt:
 	curl -O https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt
 emoji-test.txt:
 	curl -O https://www.unicode.org/Public/emoji/latest/emoji-test.txt
-IndicSyllabicCategory.txt:
-	curl -O https://unicode.org/Public/UCD/latest/ucd/IndicSyllabicCategory.txt
-IndicPositionalCategory.txt:
-	curl -O https://unicode.org/Public/UCD/latest/ucd/IndicPositionalCategory.txt
 languagetags:
 	curl -O https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
 language-subtag-registry:
 	curl -O https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
 ucd.nounihan.grouped.zip:
 	curl -O https://unicode.org/Public/UCD/latest/ucdxml/ucd.nounihan.grouped.zip
-Scripts.txt:
-	curl -O https://unicode.org/Public/UCD/latest/ucd/Scripts.txt
 
 clean:
 	$(RM) \
diff --git a/test/api/fonts/TwemojiMozilla.subset.default.32,3299.ttf b/test/api/fonts/TwemojiMozilla.subset.default.32,3299.ttf
index 2f1a11a..ea7411a 100644
--- a/test/api/fonts/TwemojiMozilla.subset.default.32,3299.ttf
+++ b/test/api/fonts/TwemojiMozilla.subset.default.32,3299.ttf
Binary files differ
diff --git a/test/api/fonts/TwemojiMozilla.subset.default.32.ttf b/test/api/fonts/TwemojiMozilla.subset.default.32.ttf
index d77db78..9ac8407 100644
--- a/test/api/fonts/TwemojiMozilla.subset.default.32.ttf
+++ b/test/api/fonts/TwemojiMozilla.subset.default.32.ttf
Binary files differ
diff --git a/test/api/fonts/TwemojiMozilla.subset.default.3297.ttf b/test/api/fonts/TwemojiMozilla.subset.default.3297.ttf
index 5028110..7119a37 100644
--- a/test/api/fonts/TwemojiMozilla.subset.default.3297.ttf
+++ b/test/api/fonts/TwemojiMozilla.subset.default.3297.ttf
Binary files differ
diff --git a/test/api/fonts/TwemojiMozilla.subset.ttf b/test/api/fonts/TwemojiMozilla.subset.ttf
index 7d09649..5045cb3 100644
--- a/test/api/fonts/TwemojiMozilla.subset.ttf
+++ b/test/api/fonts/TwemojiMozilla.subset.ttf
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6616166961905664 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6616166961905664
new file mode 100644
index 0000000..35b6479
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6616166961905664
Binary files differ
diff --git a/test/shape/data/in-house/fonts/e2b17207c4b7ad78d843e1b0c4d00b09398a1137.ttf b/test/shape/data/in-house/fonts/e2b17207c4b7ad78d843e1b0c4d00b09398a1137.ttf
new file mode 100644
index 0000000..b499ce0
--- /dev/null
+++ b/test/shape/data/in-house/fonts/e2b17207c4b7ad78d843e1b0c4d00b09398a1137.ttf
Binary files differ
diff --git a/test/shape/data/in-house/fonts/e6185e88b04432fbf373594d5971686bb7dd698d.ttf b/test/shape/data/in-house/fonts/e6185e88b04432fbf373594d5971686bb7dd698d.ttf
new file mode 100644
index 0000000..5234b06
--- /dev/null
+++ b/test/shape/data/in-house/fonts/e6185e88b04432fbf373594d5971686bb7dd698d.ttf
Binary files differ
diff --git a/test/shape/data/in-house/tests/aat-morx.tests b/test/shape/data/in-house/tests/aat-morx.tests
index 99122c9..b1b5079 100644
--- a/test/shape/data/in-house/tests/aat-morx.tests
+++ b/test/shape/data/in-house/tests/aat-morx.tests
@@ -1 +1,2 @@
 ../fonts/MORXTwentyeight.ttf;;U+0041,U+0078,U+0045,U+0079,U+0044,U+0079,U+0079;[A_E_D=0+1394|x=0+529|y=0+510|y=5+510|y=6+510]
+../fonts/e6185e88b04432fbf373594d5971686bb7dd698d.ttf;;U+0B95,U+0BCD,U+0020,U+0B9A,U+0BCD;[ka-tamil=0+825|pulli-tamil=0@-392,0+0|space=2+260|ca-tamil=3+723|pulli-tamil=3@-320,0+0]
diff --git a/test/shape/data/in-house/tests/indic-syllable.tests b/test/shape/data/in-house/tests/indic-syllable.tests
index 87b62b7..275fb13 100644
--- a/test/shape/data/in-house/tests/indic-syllable.tests
+++ b/test/shape/data/in-house/tests/indic-syllable.tests
@@ -10,3 +10,4 @@
 ../fonts/f75c4b05a0a4d67c1a808081ae3d74a9c66509e8.ttf;;U+0A20,U+0A75,U+0A42;[tthaguru=0+1352|yakashuuguru=0+0]
 ../fonts/b3075ca42b27dde7341c2d0ae16703c5b6640df0.ttf;;U+0B2C,U+0B55,U+0B3E;[uni0B2C=0+641|uni0B55=0+0|uni0B3E=0+253]
 ../fonts/b3075ca42b27dde7341c2d0ae16703c5b6640df0.ttf;;U+0B2C,U+0B3E,U+0B55;[uni0B2C=0+641|uni0B3E=0+253|uni0B55=0+0]
+../fonts/e2b17207c4b7ad78d843e1b0c4d00b09398a1137.ttf;;U+0BAA,U+0BAA,U+0BCD;[pa-tamil=0+778|pa-tamil.001=1+778|pulli-tamil=1@-385,0+0]
diff --git a/test/shape/data/in-house/tests/use-syllable.tests b/test/shape/data/in-house/tests/use-syllable.tests
index a0f0be8..1cc52fd 100644
--- a/test/shape/data/in-house/tests/use-syllable.tests
+++ b/test/shape/data/in-house/tests/use-syllable.tests
@@ -19,4 +19,4 @@
 ../fonts/573d3a3177c9a8646e94c8a0d7b224334340946a.ttf;--font-funcs=ft;U+11410,U+200C,U+11442,U+034F,U+11411;[Ga.icd=0+367|Gha.diag=1@100,0+386]
 ../fonts/e68a88939e0f06e34d2bc911f09b70890289c8fd.ttf;;U+AA00,U+200C,U+AA34;[raMedial_cham_pre=0+400|a_cham=0+1121]
 ../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf;;U+11124,U+200D,U+11127;[u11124=0+514|u11127=0+0]
-../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf;;U+11124,U+2060,U+11127;[u11124=0+514|u11127=1+0]
+../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf;;U+11124,U+2060,U+11127;[u11124=0+514|uni25CC=1+547|u11127=1+0]
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
index 79dfd31..f530fad 100644
--- a/test/subset/data/Makefile.am
+++ b/test/subset/data/Makefile.am
@@ -40,6 +40,7 @@
 	expected/cmap14 \
 	expected/sbix \
 	expected/colr \
+	expected/colrv1 \
 	expected/colr_with_components \
 	expected/cbdt \
 	expected/variable \
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
index d9cd4e4..2ed1056 100644
--- a/test/subset/data/Makefile.sources
+++ b/test/subset/data/Makefile.sources
@@ -7,6 +7,7 @@
 	tests/cmap.tests \
 	tests/cmap14.tests \
 	tests/colr.tests \
+	tests/colrv1.tests \
 	tests/colr_with_components.tests \
 	tests/full-font.tests \
 	tests/glyf_bug_3131.tests \
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3297,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3297,3299.ttf
index 0c48ab7..5045cb3 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3297,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3297,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3297.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3297.ttf
index e8cb319..f911e0e 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3297.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3297.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3299.ttf
index df6e698..ea7411a 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.32,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3297,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3297,3299.ttf
index 7d2b6a7..d3fc1d2 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3297,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3297,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3297.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3297.ttf
index 6e62919..7119a37 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3297.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3297.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3299.ttf
index ae27249..98a36ef 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.default.3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3297,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3297,3299.ttf
index 5e233f1..65547c3 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3297,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3297,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3297.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3297.ttf
index bda0ba5..00eb43e 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3297.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3297.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3299.ttf
index 884b72a..7d6e3c0 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.32,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3297,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3297,3299.ttf
index eda873e..7e87237 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3297,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3297,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3297.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3297.ttf
index 6ed63f7..b1c100e 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3297.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3297.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3299.ttf
index 31a3dcd..1e63412 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints-retain-gids.3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3297,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3297,3299.ttf
index 5e233f1..65547c3 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3297,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3297,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3297.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3297.ttf
index 40e0545..7cc71b1 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3297.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3297.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3299.ttf
index 864fce3..2c5d33c 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.32,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3297,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3297,3299.ttf
index c581a41..275d198 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3297,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3297,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3297.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3297.ttf
index cce7de4..73e6b97 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3297.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3297.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3299.ttf
index ab488ca..30ed3b8 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.drop-hints.3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3297,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3297,3299.ttf
index 0c48ab7..5045cb3 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3297,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3297,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3297.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3297.ttf
index 2e4a901..1fad08b 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3297.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3297.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3299.ttf
index f0f5c2b..adb431c 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.32,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3297,3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3297,3299.ttf
index a70a883..3d01daa 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3297,3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3297,3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3297.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3297.ttf
index ec0e46a..7823ed8 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3297.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3297.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3299.ttf b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3299.ttf
index a44dd9f..c8d4ccd 100644
--- a/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3299.ttf
+++ b/test/subset/data/expected/colr/TwemojiMozilla.subset.retain-gids.3299.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr_with_components/colr-table.default.6B.ttf b/test/subset/data/expected/colr_with_components/colr-table.default.6B.ttf
index fe9b819..67020e2 100644
--- a/test/subset/data/expected/colr_with_components/colr-table.default.6B.ttf
+++ b/test/subset/data/expected/colr_with_components/colr-table.default.6B.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr_with_components/colr-table.drop-hints-retain-gids.6B.ttf b/test/subset/data/expected/colr_with_components/colr-table.drop-hints-retain-gids.6B.ttf
index 0e063f1..a2be484 100644
--- a/test/subset/data/expected/colr_with_components/colr-table.drop-hints-retain-gids.6B.ttf
+++ b/test/subset/data/expected/colr_with_components/colr-table.drop-hints-retain-gids.6B.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr_with_components/colr-table.drop-hints.6B.ttf b/test/subset/data/expected/colr_with_components/colr-table.drop-hints.6B.ttf
index fe9b819..67020e2 100644
--- a/test/subset/data/expected/colr_with_components/colr-table.drop-hints.6B.ttf
+++ b/test/subset/data/expected/colr_with_components/colr-table.drop-hints.6B.ttf
Binary files differ
diff --git a/test/subset/data/expected/colr_with_components/colr-table.retain-gids.6B.ttf b/test/subset/data/expected/colr_with_components/colr-table.retain-gids.6B.ttf
index 0e063f1..a2be484 100644
--- a/test/subset/data/expected/colr_with_components/colr-table.retain-gids.6B.ttf
+++ b/test/subset/data/expected/colr_with_components/colr-table.retain-gids.6B.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E001,E002,E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E001,E002,E003.ttf
new file mode 100644
index 0000000..c7fafc1
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E001,E002,E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E001,E002.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E001,E002.ttf
new file mode 100644
index 0000000..78634bb
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E001,E002.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E001.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E001.ttf
new file mode 100644
index 0000000..7a490cb
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E001.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E004.ttf
new file mode 100644
index 0000000..bab0b4f
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E000.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000.ttf
new file mode 100644
index 0000000..764be9b
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E000.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E001.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E001.ttf
new file mode 100644
index 0000000..0a381b7
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E001.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E002,E003,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E002,E003,E004.ttf
new file mode 100644
index 0000000..7d094e0
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E002,E003,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E002,E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E002,E003.ttf
new file mode 100644
index 0000000..82dd4b9
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E002,E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E002.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E002.ttf
new file mode 100644
index 0000000..c2e76cc
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E002.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E003,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E003,E004.ttf
new file mode 100644
index 0000000..af8c79b
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E003,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E003.ttf
new file mode 100644
index 0000000..2ea7578
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.E004.ttf
new file mode 100644
index 0000000..d547667
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.default.retain-all-codepoint.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.default.retain-all-codepoint.ttf
new file mode 100644
index 0000000..b0e9865
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.default.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E001,E002,E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E001,E002,E003.ttf
new file mode 100644
index 0000000..929a9ed
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E001,E002,E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E001,E002.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E001,E002.ttf
new file mode 100644
index 0000000..5516df3
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E001,E002.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E001.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E001.ttf
new file mode 100644
index 0000000..d529046
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E001.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E004.ttf
new file mode 100644
index 0000000..3e9abac
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000.ttf
new file mode 100644
index 0000000..f5f0e0b
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E000.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E001.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E001.ttf
new file mode 100644
index 0000000..a98ed2e
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E001.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E002,E003,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E002,E003,E004.ttf
new file mode 100644
index 0000000..25b5aed
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E002,E003,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E002,E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E002,E003.ttf
new file mode 100644
index 0000000..b8b3e90
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E002,E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E002.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E002.ttf
new file mode 100644
index 0000000..85e2f68
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E002.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E003,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E003,E004.ttf
new file mode 100644
index 0000000..f983408
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E003,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E003.ttf
new file mode 100644
index 0000000..907da5f
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E004.ttf
new file mode 100644
index 0000000..66528df
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.retain-all-codepoint.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.retain-all-codepoint.ttf
new file mode 100644
index 0000000..ec3ddec
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints-retain-gids.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E001,E002,E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E001,E002,E003.ttf
new file mode 100644
index 0000000..714c9c8
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E001,E002,E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E001,E002.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E001,E002.ttf
new file mode 100644
index 0000000..437a67d
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E001,E002.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E001.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E001.ttf
new file mode 100644
index 0000000..2729c8d
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E001.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E004.ttf
new file mode 100644
index 0000000..2c87b3d
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000.ttf
new file mode 100644
index 0000000..56e3835
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E000.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E001.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E001.ttf
new file mode 100644
index 0000000..80d281f
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E001.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E002,E003,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E002,E003,E004.ttf
new file mode 100644
index 0000000..dde87f7
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E002,E003,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E002,E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E002,E003.ttf
new file mode 100644
index 0000000..b06cf18
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E002,E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E002.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E002.ttf
new file mode 100644
index 0000000..89520f0
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E002.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E003,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E003,E004.ttf
new file mode 100644
index 0000000..50be561
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E003,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E003.ttf
new file mode 100644
index 0000000..b05b82b
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E004.ttf
new file mode 100644
index 0000000..f6a12e2
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.retain-all-codepoint.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.retain-all-codepoint.ttf
new file mode 100644
index 0000000..ec3ddec
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.drop-hints.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E001,E002,E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E001,E002,E003.ttf
new file mode 100644
index 0000000..ff537f1
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E001,E002,E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E001,E002.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E001,E002.ttf
new file mode 100644
index 0000000..e548a8b
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E001,E002.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E001.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E001.ttf
new file mode 100644
index 0000000..cb5a94d
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E001.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E004.ttf
new file mode 100644
index 0000000..5d72345
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000.ttf
new file mode 100644
index 0000000..fe1a85c
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E000.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E001.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E001.ttf
new file mode 100644
index 0000000..f25586a
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E001.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E002,E003,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E002,E003,E004.ttf
new file mode 100644
index 0000000..549b52d
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E002,E003,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E002,E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E002,E003.ttf
new file mode 100644
index 0000000..bc43627
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E002,E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E002.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E002.ttf
new file mode 100644
index 0000000..f99b3dd
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E002.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E003,E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E003,E004.ttf
new file mode 100644
index 0000000..ec25389
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E003,E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E003.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E003.ttf
new file mode 100644
index 0000000..4e6ef19
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E003.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E004.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E004.ttf
new file mode 100644
index 0000000..756ea5f
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.E004.ttf
Binary files differ
diff --git a/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.retain-all-codepoint.ttf b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.retain-all-codepoint.ttf
new file mode 100644
index 0000000..b0e9865
--- /dev/null
+++ b/test/subset/data/expected/colrv1/TestCOLRv1.retain-gids.retain-all-codepoint.ttf
Binary files differ
diff --git a/test/subset/data/fonts/TestCOLRv1.ttf b/test/subset/data/fonts/TestCOLRv1.ttf
index 262f266..631da66 100644
--- a/test/subset/data/fonts/TestCOLRv1.ttf
+++ b/test/subset/data/fonts/TestCOLRv1.ttf
Binary files differ
diff --git a/test/subset/data/tests/colrv1.tests b/test/subset/data/tests/colrv1.tests
index f579737..a15ad92 100644
--- a/test/subset/data/tests/colrv1.tests
+++ b/test/subset/data/tests/colrv1.tests
@@ -8,14 +8,16 @@
 retain-gids.txt
 
 SUBSETS:
-#U+E000
-#U+E001
-#U+E003
+U+E000
+U+E001
+U+E002
+U+E003
 U+E004
-#U+E000,U+E001
-#U+E002,U+E003
+U+E000,U+E001
+U+E002,U+E003
 U+E000,U+E004
 U+E003,U+E004
-#U+E000,U+E001,U+E002
-#U+E000,U+E001,U+E002,U+E003
+U+E000,U+E001,U+E002
+U+E000,U+E001,U+E002,U+E003
+U+E002,U+E003,U+E004
 *
diff --git a/test/subset/meson.build b/test/subset/meson.build
index 05fbf8a..9a5377c 100644
--- a/test/subset/meson.build
+++ b/test/subset/meson.build
@@ -35,7 +35,7 @@
   'math',
 # TODO: re-enable once colrv1 subsetting is stabilized.
 # 'colrv1.notoemoji',
-# 'colrv1',
+  'colrv1',
   'colr_with_components',
   'cbdt',
   'variable',