diff --git a/gfx/harfbuzz/README-mozilla b/gfx/harfbuzz/README-mozilla
index ac786a76bd..ce21b33802 100644
--- a/gfx/harfbuzz/README-mozilla
+++ b/gfx/harfbuzz/README-mozilla
@@ -1,9 +1,9 @@
-gfx/harfbuzz status as of 2021-07-09:
+gfx/harfbuzz status as of 2021-12-12:
This directory contains the harfbuzz source from the 'master' branch of
https://github.com/harfbuzz/harfbuzz.
-Current version: 2.8.2
+Current version: 3.2.0
UPDATING:
diff --git a/gfx/harfbuzz/src/Makefile.am b/gfx/harfbuzz/src/Makefile.am
index f405331d6d..c0c77055ee 100644
--- a/gfx/harfbuzz/src/Makefile.am
+++ b/gfx/harfbuzz/src/Makefile.am
@@ -342,7 +342,20 @@ test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
-COMPILED_TESTS = test-algs test-array test-iter test-meta test-number test-ot-tag test-priority-queue test-unicode-ranges test-bimap test-repacker
+COMPILED_TESTS = \
+ test-algs \
+ test-array \
+ test-iter \
+ test-map \
+ test-number \
+ test-ot-tag \
+ test-priority-queue \
+ test-set \
+ test-unicode-ranges \
+ test-vector \
+ test-bimap \
+ test-repacker \
+ $(NULL)
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
check_PROGRAMS += $(COMPILED_TESTS)
@@ -368,9 +381,9 @@ test_iter_SOURCES = test-iter.cc hb-static.cc
test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_iter_LDADD = $(COMPILED_TESTS_LDADD)
-test_meta_SOURCES = test-meta.cc hb-static.cc
-test_meta_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
-test_meta_LDADD = $(COMPILED_TESTS_LDADD)
+test_map_SOURCES = test-map.cc hb-static.cc
+test_map_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_map_LDADD = $(COMPILED_TESTS_LDADD)
test_number_SOURCES = test-number.cc hb-number.cc
test_number_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
@@ -380,10 +393,18 @@ test_ot_tag_SOURCES = hb-ot-tag.cc
test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD)
+test_set_SOURCES = test-set.cc hb-static.cc
+test_set_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_set_LDADD = $(COMPILED_TESTS_LDADD)
+
test_unicode_ranges_SOURCES = test-unicode-ranges.cc
test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD)
+test_vector_SOURCES = test-vector.cc hb-static.cc
+test_vector_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_vector_LDADD = $(COMPILED_TESTS_LDADD)
+
test_bimap_SOURCES = test-bimap.cc hb-static.cc
test_bimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_bimap_LDADD = $(COMPILED_TESTS_LDADD)
diff --git a/gfx/harfbuzz/src/Makefile.sources b/gfx/harfbuzz/src/Makefile.sources
index d8b7b2f7d7..699dfdcafc 100644
--- a/gfx/harfbuzz/src/Makefile.sources
+++ b/gfx/harfbuzz/src/Makefile.sources
@@ -19,6 +19,9 @@ HB_BASE_sources = \
hb-array.hh \
hb-atomic.hh \
hb-bimap.hh \
+ hb-bit-page.hh \
+ hb-bit-set.hh \
+ hb-bit-set-invertible.hh \
hb-blob.cc \
hb-blob.hh \
hb-buffer-serialize.cc \
@@ -47,6 +50,8 @@ HB_BASE_sources = \
hb-map.cc \
hb-map.hh \
hb-meta.hh \
+ hb-ms-feature-ranges.cc \
+ hb-ms-feature-ranges.hh \
hb-mutex.hh \
hb-null.hh \
hb-number.cc \
@@ -138,6 +143,7 @@ HB_BASE_sources = \
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 \
@@ -257,6 +263,7 @@ HB_SUBSET_sources = \
hb-ot-cff1-table.cc \
hb-ot-cff2-table.cc \
hb-ot-color-colrv1-closure.hh \
+ hb-ot-post-table-v2subset.hh \
hb-static.cc \
hb-subset-cff-common.cc \
hb-subset-cff-common.hh \
diff --git a/gfx/harfbuzz/src/check-symbols.py b/gfx/harfbuzz/src/check-symbols.py
index 8050e1bf96..385959bdef 100644
--- a/gfx/harfbuzz/src/check-symbols.py
+++ b/gfx/harfbuzz/src/check-symbols.py
@@ -9,7 +9,8 @@ libs = os.getenv ('libs', '.libs')
IGNORED_SYMBOLS = '|'.join(['_fini', '_init', '_fdata', '_ftext', '_fbss',
'__bss_start', '__bss_start__', '__bss_end__', '_edata', '_end', '_bss_end__',
- '__end__', '__gcov_.*', 'llvm_.*', 'flush_fn_list', 'writeout_fn_list', 'mangle_path'])
+ '__end__', '__gcov_.*', 'llvm_.*', 'flush_fn_list', 'writeout_fn_list', 'mangle_path',
+ 'lprofDirMode', 'reset_fn_list'])
nm = os.getenv ('NM', shutil.which ('nm'))
if not nm:
@@ -67,7 +68,7 @@ for soname in ['harfbuzz', 'harfbuzz-subset', 'harfbuzz-icu', 'harfbuzz-gobject'
tested = True
if not tested:
- print ('check-symbols.sh: no shared libraries found; skipping test')
+ print ('check-symbols.py: no shared libraries found; skipping test')
sys.exit (77)
sys.exit (stat)
diff --git a/gfx/harfbuzz/src/gen-def.py b/gfx/harfbuzz/src/gen-def.py
index aa6dcd95fb..33aa4df769 100644
--- a/gfx/harfbuzz/src/gen-def.py
+++ b/gfx/harfbuzz/src/gen-def.py
@@ -36,7 +36,6 @@ hb_draw_funcs_set_cubic_to_func
hb_draw_funcs_set_line_to_func
hb_draw_funcs_set_move_to_func
hb_draw_funcs_set_quadratic_to_func
-hb_style_get_value
hb_font_get_var_coords_design""".splitlines ()
symbols = [x for x in symbols if x not in experimental_symbols]
symbols = "\n".join (symbols)
diff --git a/gfx/harfbuzz/src/gen-emoji-table.py b/gfx/harfbuzz/src/gen-emoji-table.py
index 1bdd402f86..0ee8fecfa4 100644
--- a/gfx/harfbuzz/src/gen-emoji-table.py
+++ b/gfx/harfbuzz/src/gen-emoji-table.py
@@ -1,16 +1,17 @@
#!/usr/bin/env python3
-"""usage: ./gen-emoji-table.py emoji-data.txt
+"""usage: ./gen-emoji-table.py emoji-data.txt emoji-test.txt
Input file:
* https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt
+* https://www.unicode.org/Public/emoji/latest/emoji-test.txt
"""
import sys
from collections import OrderedDict
import packTab
-if len (sys.argv) != 2:
+if len (sys.argv) != 3:
sys.exit (__doc__)
f = open(sys.argv[1])
@@ -74,3 +75,24 @@ print ()
print ("#endif /* HB_UNICODE_EMOJI_TABLE_HH */")
print ()
print ("/* == End of generated table == */")
+
+
+# Generate test file.
+sequences = []
+with open(sys.argv[2]) as f:
+ for line in f.readlines():
+ if "#" in line:
+ line = line[:line.index("#")]
+ if ";" in line:
+ line = line[:line.index(";")]
+ line = line.strip()
+ line = line.split(" ")
+ if len(line) < 2:
+ continue
+ sequences.append(line)
+
+with open("../test/shaping/data/in-house/tests/emoji-clusters.tests", "w") as f:
+ for sequence in sequences:
+ f.write("../fonts/AdobeBlank2.ttf:--no-glyph-names --no-positions --font-funcs=ot")
+ f.write(":" + ",".join(sequence))
+ f.write(":[" + "|".join("1=0" for c in sequence) + "]\n")
diff --git a/gfx/harfbuzz/src/gen-hb-version.py b/gfx/harfbuzz/src/gen-hb-version.py
index 879811ffc8..4fac0a0e5b 100644
--- a/gfx/harfbuzz/src/gen-hb-version.py
+++ b/gfx/harfbuzz/src/gen-hb-version.py
@@ -15,7 +15,7 @@ INPUT = sys.argv[3]
CURRENT_SOURCE_DIR = os.path.dirname(INPUT)
try:
- with open (OUTPUT, "r") as old_output:
+ with open (OUTPUT, "r", encoding='utf-8') as old_output:
for line in old_output:
old_version = re.match (r"#define HB_VERSION_STRING \"(\d.\d.\d)\"", line)
if old_version and old_version[1] == version:
diff --git a/gfx/harfbuzz/src/gen-ragel-artifacts.py b/gfx/harfbuzz/src/gen-ragel-artifacts.py
index d22e03ae3d..8bbb375bfb 100644
--- a/gfx/harfbuzz/src/gen-ragel-artifacts.py
+++ b/gfx/harfbuzz/src/gen-ragel-artifacts.py
@@ -4,16 +4,16 @@
import os, os.path, sys, subprocess, shutil
-ragel = os.getenv ('RAGEL', shutil.which ('ragel'))
+ragel = sys.argv[1]
if not ragel:
sys.exit ('You have to install ragel if you are going to develop HarfBuzz itself')
if len (sys.argv) < 4:
sys.exit (__doc__)
-OUTPUT = sys.argv[1]
-CURRENT_SOURCE_DIR = sys.argv[2]
-INPUT = sys.argv[3]
+OUTPUT = sys.argv[2]
+CURRENT_SOURCE_DIR = sys.argv[3]
+INPUT = sys.argv[4]
outdir = os.path.dirname (OUTPUT)
shutil.copy (INPUT, outdir)
diff --git a/gfx/harfbuzz/src/gen-tag-table.py b/gfx/harfbuzz/src/gen-tag-table.py
index d1b5d4342e..cb612b9829 100644
--- a/gfx/harfbuzz/src/gen-tag-table.py
+++ b/gfx/harfbuzz/src/gen-tag-table.py
@@ -340,11 +340,15 @@ class OpenTypeRegistryParser (HTMLParser):
self.from_bcp_47 = collections.defaultdict (set)
# Whether the parser is in a
element
self._td = False
+ # Whether the parser is after a element within the current | element
+ self._br = False
# The text of the | elements of the current |
element.
self._current_tr = []
def handle_starttag (self, tag, attrs):
- if tag == 'meta':
+ if tag == 'br':
+ self._br = True
+ elif tag == 'meta':
for attr, value in attrs:
if attr == 'name' and value == 'updated_at':
self.header = self.get_starttag_text ()
@@ -353,6 +357,7 @@ class OpenTypeRegistryParser (HTMLParser):
self._td = True
self._current_tr.append ('')
elif tag == 'tr':
+ self._br = False
self._current_tr = []
def handle_endtag (self, tag):
@@ -377,7 +382,7 @@ class OpenTypeRegistryParser (HTMLParser):
self.ranks[tag] = rank
def handle_data (self, data):
- if self._td:
+ if self._td and not self._br:
self._current_tr[-1] += data
def handle_charref (self, name):
@@ -704,6 +709,8 @@ ot.ranks['MLR'] += 1
bcp_47.names['mhv'] = 'Arakanese'
bcp_47.scopes['mhv'] = ' (retired code)'
+ot.add_language ('mnw-TH', 'MONT')
+
ot.add_language ('no', 'NOR')
ot.add_language ('oc-provenc', 'PRO')
diff --git a/gfx/harfbuzz/src/gen-use-table.py b/gfx/harfbuzz/src/gen-use-table.py
index 930300364d..34540ca6d8 100644
--- a/gfx/harfbuzz/src/gen-use-table.py
+++ b/gfx/harfbuzz/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 @@ headers.append (["UnicodeData.txt does not have a header."])
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 @@ for i, f in enumerate (files):
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][0x1B67] = defaults[0]
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 @@ for i,v in enumerate (defaults):
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 @@ for name in property_names:
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 @@ def is_BASE(U, UISC, UGC, AJT):
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 @@ use_mapping = {
'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 @@ use_positions = {
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 @@ def map_to_use(data):
# 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 @@ def map_to_use(data):
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 ("/* == Start of generated table == */")
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/gfx/harfbuzz/src/harfbuzz.cc b/gfx/harfbuzz/src/harfbuzz.cc
index fe00100974..14ee6f5e8a 100644
--- a/gfx/harfbuzz/src/harfbuzz.cc
+++ b/gfx/harfbuzz/src/harfbuzz.cc
@@ -9,6 +9,7 @@
#include "hb-fallback-shape.cc"
#include "hb-font.cc"
#include "hb-map.cc"
+#include "hb-ms-feature-ranges.cc"
#include "hb-number.cc"
#include "hb-ot-cff1-table.cc"
#include "hb-ot-cff2-table.cc"
diff --git a/gfx/harfbuzz/src/hb-aat-layout-bsln-table.hh b/gfx/harfbuzz/src/hb-aat-layout-bsln-table.hh
index cd36fc8953..b52844e75d 100644
--- a/gfx/harfbuzz/src/hb-aat-layout-bsln-table.hh
+++ b/gfx/harfbuzz/src/hb-aat-layout-bsln-table.hh
@@ -82,7 +82,7 @@ struct BaselineTableFormat2Part
}
protected:
- HBGlyphID stdGlyph; /* The specific glyph index number in this
+ HBGlyphID16 stdGlyph; /* The specific glyph index number in this
* font that is used to set the baseline values.
* This is the standard glyph.
* This glyph must contain a set of control points
@@ -105,7 +105,7 @@ struct BaselineTableFormat3Part
}
protected:
- HBGlyphID stdGlyph; /* ditto */
+ HBGlyphID16 stdGlyph; /* ditto */
HBUINT16 ctlPoints[32]; /* ditto */
Lookup
lookupTable; /* Lookup table that maps glyphs to their
diff --git a/gfx/harfbuzz/src/hb-aat-layout-common.hh b/gfx/harfbuzz/src/hb-aat-layout-common.hh
index e70ce97174..1dcbe92904 100644
--- a/gfx/harfbuzz/src/hb-aat-layout-common.hh
+++ b/gfx/harfbuzz/src/hb-aat-layout-common.hh
@@ -96,8 +96,8 @@ struct LookupSegmentSingle
return_trace (c->check_struct (this) && value.sanitize (c, base));
}
- HBGlyphID last; /* Last GlyphID in this segment */
- HBGlyphID first; /* First GlyphID in this segment */
+ HBGlyphID16 last; /* Last GlyphID in this segment */
+ HBGlyphID16 first; /* First GlyphID in this segment */
T value; /* The lookup value (only one) */
public:
DEFINE_SIZE_STATIC (4 + T::static_size);
@@ -162,11 +162,11 @@ struct LookupSegmentArray
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
first <= last &&
- valuesZ.sanitize (c, base, last - first + 1, hb_forward (ds)...));
+ valuesZ.sanitize (c, base, last - first + 1, std::forward (ds)...));
}
- HBGlyphID last; /* Last GlyphID in this segment */
- HBGlyphID first; /* First GlyphID in this segment */
+ HBGlyphID16 last; /* Last GlyphID in this segment */
+ HBGlyphID16 first; /* First GlyphID in this segment */
NNOffset16To>
valuesZ; /* A 16-bit offset from the start of
* the table to the data. */
@@ -225,7 +225,7 @@ struct LookupSingle
return_trace (c->check_struct (this) && value.sanitize (c, base));
}
- HBGlyphID glyph; /* Last GlyphID */
+ HBGlyphID16 glyph; /* Last GlyphID */
T value; /* The lookup value (only one) */
public:
DEFINE_SIZE_STATIC (2 + T::static_size);
@@ -287,7 +287,7 @@ struct LookupFormat8
protected:
HBUINT16 format; /* Format identifier--format = 8 */
- HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */
+ HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
* glyph minus the value of firstGlyph plus 1). */
UnsizedArrayOf
@@ -329,7 +329,7 @@ struct LookupFormat10
protected:
HBUINT16 format; /* Format identifier--format = 8 */
HBUINT16 valueSize; /* Byte size of each value. */
- HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */
+ HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
* glyph minus the value of firstGlyph plus 1). */
UnsizedArrayOf
@@ -661,7 +661,7 @@ struct ClassTable
return_trace (c->check_struct (this) && classArray.sanitize (c));
}
protected:
- HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */
+ HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
Array16Of classArray; /* The class codes (indexed by glyph index minus
* firstGlyph). */
public:
diff --git a/gfx/harfbuzz/src/hb-aat-layout-just-table.hh b/gfx/harfbuzz/src/hb-aat-layout-just-table.hh
index 556d4ad75b..d745c11431 100644
--- a/gfx/harfbuzz/src/hb-aat-layout-just-table.hh
+++ b/gfx/harfbuzz/src/hb-aat-layout-just-table.hh
@@ -100,7 +100,7 @@ struct UnconditionalAddGlyphAction
protected:
ActionSubrecordHeader
header;
- HBGlyphID addGlyph; /* Glyph that should be added if the distance factor
+ HBGlyphID16 addGlyph; /* Glyph that should be added if the distance factor
* is growing. */
public:
@@ -121,11 +121,11 @@ struct ConditionalAddGlyphAction
HBFixed substThreshold; /* Distance growth factor (in ems) at which
* this glyph is replaced and the growth factor
* recalculated. */
- HBGlyphID addGlyph; /* Glyph to be added as kashida. If this value is
+ HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is
* 0xFFFF, no extra glyph will be added. Note that
* generally when a glyph is added, justification
* will need to be redone. */
- HBGlyphID substGlyph; /* Glyph to be substituted for this glyph if the
+ HBGlyphID16 substGlyph; /* Glyph to be substituted for this glyph if the
* growth factor equals or exceeds the value of
* substThreshold. */
public:
@@ -170,7 +170,7 @@ struct RepeatedAddGlyphAction
ActionSubrecordHeader
header;
HBUINT16 flags; /* Currently unused; set to 0. */
- HBGlyphID glyph; /* Glyph that should be added if the distance factor
+ HBGlyphID16 glyph; /* Glyph that should be added if the distance factor
* is growing. */
public:
DEFINE_SIZE_STATIC (10);
diff --git a/gfx/harfbuzz/src/hb-aat-layout-kerx-table.hh b/gfx/harfbuzz/src/hb-aat-layout-kerx-table.hh
index d0eacf0e61..0354b47d5a 100644
--- a/gfx/harfbuzz/src/hb-aat-layout-kerx-table.hh
+++ b/gfx/harfbuzz/src/hb-aat-layout-kerx-table.hh
@@ -82,8 +82,8 @@ struct KernPair
}
protected:
- HBGlyphID left;
- HBGlyphID right;
+ HBGlyphID16 left;
+ HBGlyphID16 right;
FWORD value;
public:
DEFINE_SIZE_STATIC (6);
@@ -775,11 +775,11 @@ struct KerxSubTable
unsigned int subtable_type = get_type ();
TRACE_DISPATCH (this, subtable_type);
switch (subtable_type) {
- case 0: return_trace (c->dispatch (u.format0, hb_forward (ds)...));
- case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...));
- case 2: return_trace (c->dispatch (u.format2, hb_forward (ds)...));
- case 4: return_trace (c->dispatch (u.format4, hb_forward (ds)...));
- case 6: return_trace (c->dispatch (u.format6, hb_forward (ds)...));
+ case 0: return_trace (c->dispatch (u.format0, std::forward (ds)...));
+ case 1: return_trace (c->dispatch (u.format1, std::forward (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward (ds)...));
+ case 6: return_trace (c->dispatch (u.format6, std::forward (ds)...));
default: return_trace (c->default_return_value ());
}
}
diff --git a/gfx/harfbuzz/src/hb-aat-layout-morx-table.hh b/gfx/harfbuzz/src/hb-aat-layout-morx-table.hh
index a807bdcfc5..2f99510925 100644
--- a/gfx/harfbuzz/src/hb-aat-layout-morx-table.hh
+++ b/gfx/harfbuzz/src/hb-aat-layout-morx-table.hh
@@ -243,21 +243,21 @@ struct ContextualSubtable
if (buffer->idx == buffer->len && !mark_set)
return;
- const HBGlyphID *replacement;
+ const HBGlyphID16 *replacement;
replacement = nullptr;
if (Types::extended)
{
if (entry.data.markIndex != 0xFFFF)
{
- const Lookup &lookup = subs[entry.data.markIndex];
+ const Lookup &lookup = subs[entry.data.markIndex];
replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
}
}
else
{
unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
- const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs;
+ const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs;
replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
if (!replacement->sanitize (&c->sanitizer) || !*replacement)
replacement = nullptr;
@@ -278,14 +278,14 @@ struct ContextualSubtable
{
if (entry.data.currentIndex != 0xFFFF)
{
- const Lookup &lookup = subs[entry.data.currentIndex];
+ const Lookup &lookup = subs[entry.data.currentIndex];
replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
}
}
else
{
unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
- const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs;
+ const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs;
replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
if (!replacement->sanitize (&c->sanitizer) || !*replacement)
replacement = nullptr;
@@ -315,7 +315,7 @@ struct ContextualSubtable
bool has_glyph_classes;
unsigned int mark;
const ContextualSubtable *table;
- const UnsizedListOfOffset16To, HBUINT, false> &subs;
+ const UnsizedListOfOffset16To, HBUINT, false> &subs;
};
bool apply (hb_aat_apply_context_t *c) const
@@ -359,7 +359,7 @@ struct ContextualSubtable
protected:
StateTable
machine;
- NNOffsetTo, HBUINT, false>, HBUINT>
+ NNOffsetTo, HBUINT, false>, HBUINT>
substitutionTables;
public:
DEFINE_SIZE_STATIC (20);
@@ -531,7 +531,7 @@ struct LigatureSubtable
if (action & (LigActionStore | LigActionLast))
{
ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
- const HBGlyphID &ligatureData = ligature[ligature_idx];
+ const HBGlyphID16 &ligatureData = ligature[ligature_idx];
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
hb_codepoint_t lig = ligatureData;
@@ -565,7 +565,7 @@ struct LigatureSubtable
const LigatureSubtable *table;
const UnsizedArrayOf &ligAction;
const UnsizedArrayOf &component;
- const UnsizedArrayOf &ligature;
+ const UnsizedArrayOf &ligature;
unsigned int match_length;
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
};
@@ -597,7 +597,7 @@ struct LigatureSubtable
ligAction; /* Offset to the ligature action table. */
NNOffsetTo, HBUINT>
component; /* Offset to the component table. */
- NNOffsetTo, HBUINT>
+ NNOffsetTo, HBUINT>
ligature; /* Offset to the actual ligature lists. */
public:
DEFINE_SIZE_STATIC (28);
@@ -620,7 +620,7 @@ struct NoncontextualSubtable
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++)
{
- const HBGlyphID *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
+ const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
if (replacement)
{
info[i].codepoint = *replacement;
@@ -641,7 +641,7 @@ struct NoncontextualSubtable
}
protected:
- Lookup substitute;
+ Lookup substitute;
public:
DEFINE_SIZE_MIN (2);
};
@@ -744,7 +744,7 @@ struct InsertionSubtable
unsigned int count = (flags & MarkedInsertCount);
if (unlikely ((buffer->max_ops -= count) <= 0)) return;
unsigned int start = entry.data.markedInsertIndex;
- const HBGlyphID *glyphs = &insertionAction[start];
+ const HBGlyphID16 *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
bool before = flags & MarkedInsertBefore;
@@ -772,7 +772,7 @@ struct InsertionSubtable
unsigned int count = (flags & CurrentInsertCount) >> 5;
if (unlikely ((buffer->max_ops -= count) <= 0)) return;
unsigned int start = entry.data.currentInsertIndex;
- const HBGlyphID *glyphs = &insertionAction[start];
+ const HBGlyphID16 *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
bool before = flags & CurrentInsertBefore;
@@ -810,7 +810,7 @@ struct InsertionSubtable
private:
hb_aat_apply_context_t *c;
unsigned int mark;
- const UnsizedArrayOf &insertionAction;
+ const UnsizedArrayOf &insertionAction;
};
bool apply (hb_aat_apply_context_t *c) const
@@ -836,7 +836,7 @@ struct InsertionSubtable
protected:
StateTable
machine;
- NNOffsetTo, HBUINT>
+ NNOffsetTo, HBUINT>
insertionAction; /* Byte offset from stateHeader to the start of
* the insertion glyph table. */
public:
@@ -906,11 +906,11 @@ struct ChainSubtable
unsigned int subtable_type = get_type ();
TRACE_DISPATCH (this, subtable_type);
switch (subtable_type) {
- case Rearrangement: return_trace (c->dispatch (u.rearrangement, hb_forward (ds)...));
- case Contextual: return_trace (c->dispatch (u.contextual, hb_forward (ds)...));
- case Ligature: return_trace (c->dispatch (u.ligature, hb_forward (ds)...));
- case Noncontextual: return_trace (c->dispatch (u.noncontextual, hb_forward (ds)...));
- case Insertion: return_trace (c->dispatch (u.insertion, hb_forward (ds)...));
+ case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward (ds)...));
+ case Contextual: return_trace (c->dispatch (u.contextual, std::forward (ds)...));
+ case Ligature: return_trace (c->dispatch (u.ligature, std::forward (ds)...));
+ case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward (ds)...));
+ case Insertion: return_trace (c->dispatch (u.insertion, std::forward (ds)...));
default: return_trace (c->default_return_value ());
}
}
@@ -1038,12 +1038,12 @@ struct Chain
goto skip;
if (reverse)
- c->buffer->reverse ();
+ _hb_ot_layout_reverse_graphemes (c->buffer);
subtable->apply (c);
if (reverse)
- c->buffer->reverse ();
+ _hb_ot_layout_reverse_graphemes (c->buffer);
(void) c->buffer->message (c->font, "end chainsubtable %d", c->lookup_index);
diff --git a/gfx/harfbuzz/src/hb-algs.hh b/gfx/harfbuzz/src/hb-algs.hh
index bc170b0546..446d87e28b 100644
--- a/gfx/harfbuzz/src/hb-algs.hh
+++ b/gfx/harfbuzz/src/hb-algs.hh
@@ -34,6 +34,9 @@
#include "hb-null.hh"
#include "hb-number.hh"
+#include
+#include
+#include
/*
* Flags
@@ -125,7 +128,7 @@ struct BEInt
template
struct BEInt
{
- static_assert (!hb_is_signed (Type), "");
+ static_assert (!std::is_signed::value, "");
public:
BEInt () = default;
constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
@@ -179,7 +182,7 @@ struct
{
/* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
template constexpr auto
- operator () (T&& v) const HB_AUTO_RETURN ( hb_forward (v) )
+ operator () (T&& v) const HB_AUTO_RETURN ( std::forward (v) )
}
HB_FUNCOBJ (hb_identity);
struct
@@ -203,7 +206,7 @@ HB_FUNCOBJ (hb_ridentity);
struct
{
template constexpr bool
- operator () (T&& v) const { return bool (hb_forward (v)); }
+ operator () (T&& v) const { return bool (std::forward (v)); }
}
HB_FUNCOBJ (hb_bool);
@@ -215,7 +218,7 @@ struct
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
template constexpr auto
+ hb_enable_if (std::is_integral::value)> constexpr auto
impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
(
/* Knuth's multiplicative method: */
@@ -237,26 +240,26 @@ struct
/* Pointer-to-member-function. */
template auto
impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
- ((hb_deref (hb_forward (v)).*hb_forward (a)) (hb_forward (ds)...))
+ ((hb_deref (std::forward (v)).*std::forward (a)) (std::forward (ds)...))
/* Pointer-to-member. */
template auto
impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
- ((hb_deref (hb_forward (v))).*hb_forward (a))
+ ((hb_deref (std::forward (v))).*std::forward (a))
/* Operator(). */
template auto
impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
- (hb_deref (hb_forward (a)) (hb_forward (ds)...))
+ (hb_deref (std::forward (a)) (std::forward (ds)...))
public:
template auto
operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
(
- impl (hb_forward (a),
+ impl (std::forward (a),
hb_prioritize,
- hb_forward (ds)...)
+ std::forward (ds)...)
)
}
HB_FUNCOBJ (hb_invoke);
@@ -275,9 +278,9 @@ struct hb_partial_t
hb_declval (V),
hb_declval (Ts)...))
{
- return hb_invoke (hb_forward (a),
- hb_forward (v),
- hb_forward (ds)...);
+ return hb_invoke (std::forward (a),
+ std::forward (v),
+ std::forward (ds)...);
}
template (a),
- hb_forward (d0),
- hb_forward (v),
- hb_forward (ds)...);
+ return hb_invoke (std::forward (a),
+ std::forward (d0),
+ std::forward (v),
+ std::forward (ds)...);
}
private:
@@ -324,14 +327,14 @@ auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
#define HB_PARTIALIZE(Pos) \
template \
decltype(auto) operator () (_T&& _v) const \
- { return hb_partial (this, hb_forward<_T> (_v)); } \
+ { return hb_partial (this, std::forward<_T> (_v)); } \
static_assert (true, "")
#else
/* https://github.com/harfbuzz/harfbuzz/issues/1724 */
#define HB_PARTIALIZE(Pos) \
template \
auto operator () (_T&& _v) const HB_AUTO_RETURN \
- (hb_partial (+this, hb_forward<_T> (_v))) \
+ (hb_partial (+this, std::forward<_T> (_v))) \
static_assert (true, "")
#endif
@@ -343,22 +346,22 @@ struct
template auto
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(
- hb_deref (hb_forward (p)).has (hb_forward (v))
+ hb_deref (std::forward (p)).has (std::forward (v))
)
template auto
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
(
- hb_invoke (hb_forward (p),
- hb_forward (v))
+ hb_invoke (std::forward (p),
+ std::forward (v))
)
public:
template auto
operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
- impl (hb_forward (p),
- hb_forward (v),
+ impl (std::forward (p),
+ std::forward (v),
hb_prioritize)
)
}
@@ -371,22 +374,22 @@ struct
template auto
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(
- hb_has (hb_forward (p),
- hb_forward (v))
+ hb_has (std::forward (p),
+ std::forward (v))
)
template auto
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
(
- hb_forward (p) == hb_forward (v)
+ std::forward (p) == std::forward (v)
)
public:
template auto
operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
- impl (hb_forward (p),
- hb_forward (v),
+ impl (std::forward (p),
+ std::forward (v),
hb_prioritize)
)
}
@@ -399,20 +402,20 @@ struct
template auto
impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
(
- hb_deref (hb_forward (f)).get (hb_forward (v))
+ hb_deref (std::forward (f)).get (std::forward (v))
)
template auto
impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
(
- hb_invoke (hb_forward (f),
- hb_forward (v))
+ hb_invoke (std::forward (f),
+ std::forward (v))
)
template auto
impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
(
- hb_forward (f)[hb_forward (v)]
+ std::forward (f)[std::forward (v)]
)
public:
@@ -420,8 +423,8 @@ struct
template auto
operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN
(
- impl (hb_forward (f),
- hb_forward (v),
+ impl (std::forward (f),
+ std::forward (v),
hb_prioritize)
)
}
@@ -434,19 +437,19 @@ struct
template auto
impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
(
- hb_forward (v2).cmp (hb_forward (v1)) == 0
+ std::forward (v2).cmp (std::forward (v1)) == 0
)
template auto
impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
(
- hb_forward (v1).cmp (hb_forward (v2)) == 0
+ std::forward (v1).cmp (std::forward (v2)) == 0
)
template auto
impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
(
- hb_forward (v1) == hb_forward (v2)
+ std::forward (v1) == std::forward (v2)
)
public:
@@ -454,8 +457,8 @@ struct
template auto
operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN
(
- impl (hb_forward (v1),
- hb_forward (v2),
+ impl (std::forward (v1),
+ std::forward (v2),
hb_prioritize)
)
}
@@ -515,24 +518,34 @@ struct
{
template constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a <= b ? hb_forward (a) : hb_forward (b))
+ (a <= b ? std::forward (a) : std::forward (b))
}
HB_FUNCOBJ (hb_min);
struct
{
template constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a >= b ? hb_forward (a) : hb_forward (b))
+ (a >= b ? std::forward (a) : std::forward (b))
}
HB_FUNCOBJ (hb_max);
struct
{
template constexpr auto
operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN
- (hb_min (hb_max (hb_forward (x), hb_forward (min)), hb_forward (max)))
+ (hb_min (hb_max (std::forward (x), std::forward (min)), std::forward (max)))
}
HB_FUNCOBJ (hb_clamp);
+struct
+{
+ template void
+ operator () (T& a, T& b) const
+ {
+ using std::swap; // allow ADL
+ swap (a, b);
+ }
+}
+HB_FUNCOBJ (hb_swap);
/*
* Bithacks.
@@ -760,6 +773,14 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
+static inline void *
+hb_memcpy (void *__restrict dst, const void *__restrict src, size_t len)
+{
+ /* It's illegal to pass 0 as size to memcpy. */
+ if (unlikely (!len)) return dst;
+ return memcpy (dst, src, len);
+}
+
static inline int
hb_memcmp (const void *a, const void *b, unsigned int len)
{
@@ -787,7 +808,7 @@ hb_ceil_to_4 (unsigned int v)
template static inline bool
hb_in_range (T u, T lo, T hi)
{
- static_assert (!hb_is_signed::value, "");
+ static_assert (!std::is_signed::value, "");
/* The casts below are important as if T is smaller than int,
* the subtract results will become a signed int! */
@@ -1151,30 +1172,48 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
/* Operators. */
-struct hb_bitwise_and
+struct
{ HB_PARTIALIZE(2);
template constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
}
HB_FUNCOBJ (hb_bitwise_and);
-struct hb_bitwise_or
+struct
{ HB_PARTIALIZE(2);
template constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
}
HB_FUNCOBJ (hb_bitwise_or);
-struct hb_bitwise_xor
+struct
{ HB_PARTIALIZE(2);
template constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
}
HB_FUNCOBJ (hb_bitwise_xor);
-struct hb_bitwise_sub
+struct
+{ HB_PARTIALIZE(2);
+ template constexpr auto
+ operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a & b)
+}
+HB_FUNCOBJ (hb_bitwise_lt);
+struct
{ HB_PARTIALIZE(2);
template constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
}
-HB_FUNCOBJ (hb_bitwise_sub);
+HB_FUNCOBJ (hb_bitwise_gt); // aka sub
+struct
+{ HB_PARTIALIZE(2);
+ template constexpr auto
+ operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a | b)
+}
+HB_FUNCOBJ (hb_bitwise_le);
+struct
+{ HB_PARTIALIZE(2);
+ template constexpr auto
+ operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b)
+}
+HB_FUNCOBJ (hb_bitwise_ge);
struct
{
template constexpr auto
@@ -1195,6 +1234,12 @@ struct
}
HB_FUNCOBJ (hb_sub);
struct
+{ HB_PARTIALIZE(2);
+ template constexpr auto
+ operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a)
+}
+HB_FUNCOBJ (hb_rsub);
+struct
{ HB_PARTIALIZE(2);
template constexpr auto
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
diff --git a/gfx/harfbuzz/src/hb-array.hh b/gfx/harfbuzz/src/hb-array.hh
index e60e037892..0beffb078f 100644
--- a/gfx/harfbuzz/src/hb-array.hh
+++ b/gfx/harfbuzz/src/hb-array.hh
@@ -36,20 +36,34 @@
template
struct hb_sorted_array_t;
+enum hb_not_found_t
+{
+ HB_NOT_FOUND_DONT_STORE,
+ HB_NOT_FOUND_STORE,
+ HB_NOT_FOUND_STORE_CLOSEST,
+};
+
+
template
struct hb_array_t : hb_iter_with_fallback_t, Type&>
{
/*
* Constructors.
*/
- hb_array_t () : arrayZ (nullptr), length (0), backwards_length (0) {}
- hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_), backwards_length (0) {}
+ hb_array_t () = default;
+ hb_array_t (const hb_array_t&) = default;
+ ~hb_array_t () = default;
+ hb_array_t& operator= (const hb_array_t&) = default;
+ hb_array_t& operator= (hb_array_t&&) = default;
+
+ constexpr hb_array_t (std::nullptr_t) : hb_array_t () {}
+ constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
template
- hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_), backwards_length (0) {}
+ constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {}
template
- hb_array_t (const hb_array_t &o) :
+ constexpr hb_array_t (const hb_array_t &o) :
hb_iter_with_fallback_t (),
arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {}
template , Type&>
return lfind (x, &i) ? &this->arrayZ[i] : not_found;
}
template
- bool lfind (const T &x, unsigned *pos = nullptr) const
+ bool lfind (const T &x, unsigned *pos = nullptr,
+ hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
+ unsigned int to_store = (unsigned int) -1) const
{
for (unsigned i = 0; i < length; ++i)
if (hb_equal (x, this->arrayZ[i]))
@@ -149,6 +165,22 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&>
return true;
}
+ if (pos)
+ {
+ switch (not_found)
+ {
+ case HB_NOT_FOUND_DONT_STORE:
+ break;
+
+ case HB_NOT_FOUND_STORE:
+ *pos = to_store;
+ break;
+
+ case HB_NOT_FOUND_STORE_CLOSEST:
+ *pos = length;
+ break;
+ }
+ }
return false;
}
@@ -255,9 +287,9 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&>
*/
public:
- Type *arrayZ;
- unsigned int length;
- unsigned int backwards_length;
+ Type *arrayZ = nullptr;
+ unsigned int length = 0;
+ unsigned int backwards_length = 0;
};
template inline hb_array_t
hb_array (T *array, unsigned int length)
@@ -266,13 +298,6 @@ template inline hb_array_t
hb_array (T (&array_)[length_])
{ return hb_array_t (array_); }
-enum hb_bfind_not_found_t
-{
- HB_BFIND_NOT_FOUND_DONT_STORE,
- HB_BFIND_NOT_FOUND_STORE,
- HB_BFIND_NOT_FOUND_STORE_CLOSEST,
-};
-
template
struct hb_sorted_array_t :
hb_iter_t, Type&>,
@@ -283,14 +308,20 @@ struct hb_sorted_array_t :
static constexpr bool is_random_access_iterator = true;
static constexpr bool is_sorted_iterator = true;
- hb_sorted_array_t () : hb_array_t () {}
- hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t (array_, length_) {}
+ hb_sorted_array_t () = default;
+ hb_sorted_array_t (const hb_sorted_array_t&) = default;
+ ~hb_sorted_array_t () = default;
+ hb_sorted_array_t& operator= (const hb_sorted_array_t&) = default;
+ hb_sorted_array_t& operator= (hb_sorted_array_t&&) = default;
+
+ constexpr hb_sorted_array_t (std::nullptr_t) : hb_sorted_array_t () {}
+ constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t (array_, length_) {}
template
- hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t (array_) {}
+ constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t (array_) {}
template
- hb_sorted_array_t (const hb_array_t &o) :
+ constexpr hb_sorted_array_t (const hb_array_t &o) :
hb_iter_t (),
hb_array_t (o) {}
template
bool bfind (const T &x, unsigned int *i = nullptr,
- hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+ hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
unsigned int to_store = (unsigned int) -1) const
{
unsigned pos;
@@ -339,14 +370,14 @@ struct hb_sorted_array_t :
{
switch (not_found)
{
- case HB_BFIND_NOT_FOUND_DONT_STORE:
+ case HB_NOT_FOUND_DONT_STORE:
break;
- case HB_BFIND_NOT_FOUND_STORE:
+ case HB_NOT_FOUND_STORE:
*i = to_store;
break;
- case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
+ case HB_NOT_FOUND_STORE_CLOSEST:
*i = pos;
break;
}
diff --git a/gfx/harfbuzz/src/hb-atomic.hh b/gfx/harfbuzz/src/hb-atomic.hh
index 93265f655f..e640d1b586 100644
--- a/gfx/harfbuzz/src/hb-atomic.hh
+++ b/gfx/harfbuzz/src/hb-atomic.hh
@@ -102,20 +102,12 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
-#elif defined(HB_NO_MT)
+#else /* defined(HB_NO_MT) */
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
-
#define _hb_memory_barrier() do {} while (0)
-
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
-
-#else
-
-#error "Could not find any system to define atomic_int macros."
-#error "Check hb-atomic.hh for possible resolutions."
-
#endif
diff --git a/gfx/harfbuzz/src/hb-bimap.hh b/gfx/harfbuzz/src/hb-bimap.hh
index e9f3a6a52d..d466af8b60 100644
--- a/gfx/harfbuzz/src/hb-bimap.hh
+++ b/gfx/harfbuzz/src/hb-bimap.hh
@@ -33,15 +33,14 @@
/* Bi-directional map */
struct hb_bimap_t
{
- hb_bimap_t () { init (); }
- ~hb_bimap_t () { fini (); }
-
+ /* XXX(remove) */
void init ()
{
forw_map.init ();
back_map.init ();
}
+ /* XXX(remove) */
void fini ()
{
forw_map.fini ();
@@ -58,10 +57,15 @@ struct hb_bimap_t
void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
{
+ if (in_error ()) return;
if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return;
if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
+
forw_map.set (lhs, rhs);
+ if (in_error ()) return;
+
back_map.set (rhs, lhs);
+ if (in_error ()) forw_map.del (lhs);
}
hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
@@ -94,14 +98,6 @@ struct hb_bimap_t
/* Inremental bimap: only lhs is given, rhs is incrementally assigned */
struct hb_inc_bimap_t : hb_bimap_t
{
- hb_inc_bimap_t () { init (); }
-
- void init ()
- {
- hb_bimap_t::init ();
- next_value = 0;
- }
-
/* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
* Return the rhs value as the result.
*/
@@ -160,7 +156,7 @@ struct hb_inc_bimap_t : hb_bimap_t
}
protected:
- unsigned int next_value;
+ unsigned int next_value = 0;
};
#endif /* HB_BIMAP_HH */
diff --git a/gfx/harfbuzz/src/hb-bit-page.hh b/gfx/harfbuzz/src/hb-bit-page.hh
new file mode 100644
index 0000000000..263be3d044
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-bit-page.hh
@@ -0,0 +1,203 @@
+/*
+ * Copyright © 2012,2017 Google, Inc.
+ * Copyright © 2021 Behdad Esfahbod
+ *
+ * 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BIT_PAGE_HH
+#define HB_BIT_PAGE_HH
+
+#include "hb.hh"
+
+struct hb_bit_page_t
+{
+ void init0 () { v.clear (); }
+ void init1 () { v.clear (0xFF); }
+
+ constexpr unsigned len () const
+ { return ARRAY_LENGTH_CONST (v); }
+
+ bool is_empty () const
+ {
+ for (unsigned int i = 0; i < len (); i++)
+ if (v[i])
+ return false;
+ return true;
+ }
+
+ void add (hb_codepoint_t g) { elt (g) |= mask (g); }
+ void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
+ void set (hb_codepoint_t g, bool v) { if (v) add (g); else del (g); }
+ bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
+
+ void add_range (hb_codepoint_t a, hb_codepoint_t b)
+ {
+ elt_t *la = &elt (a);
+ elt_t *lb = &elt (b);
+ if (la == lb)
+ *la |= (mask (b) << 1) - mask(a);
+ else
+ {
+ *la |= ~(mask (a) - 1);
+ la++;
+
+ memset (la, 0xff, (char *) lb - (char *) la);
+
+ *lb |= ((mask (b) << 1) - 1);
+ }
+ }
+ void del_range (hb_codepoint_t a, hb_codepoint_t b)
+ {
+ elt_t *la = &elt (a);
+ elt_t *lb = &elt (b);
+ if (la == lb)
+ *la &= ~((mask (b) << 1) - mask(a));
+ else
+ {
+ *la &= mask (a) - 1;
+ la++;
+
+ memset (la, 0, (char *) lb - (char *) la);
+
+ *lb &= ~((mask (b) << 1) - 1);
+ }
+ }
+ void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
+ { if (v) add_range (a, b); else del_range (a, b); }
+
+ bool is_equal (const hb_bit_page_t &other) const
+ {
+ return 0 == hb_memcmp (&v, &other.v, sizeof (v));
+ }
+ bool is_subset (const hb_bit_page_t &larger_page) const
+ {
+ for (unsigned i = 0; i < len (); i++)
+ if (~larger_page.v[i] & v[i])
+ return false;
+ return true;
+ }
+
+ unsigned int get_population () const
+ {
+ unsigned int pop = 0;
+ for (unsigned int i = 0; i < len (); i++)
+ pop += hb_popcount (v[i]);
+ return pop;
+ }
+
+ bool next (hb_codepoint_t *codepoint) const
+ {
+ unsigned int m = (*codepoint + 1) & MASK;
+ if (!m)
+ {
+ *codepoint = INVALID;
+ return false;
+ }
+ unsigned int i = m / ELT_BITS;
+ unsigned int j = m & ELT_MASK;
+
+ const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
+ for (const elt_t *p = &vv; i < len (); p = &v[++i])
+ if (*p)
+ {
+ *codepoint = i * ELT_BITS + elt_get_min (*p);
+ return true;
+ }
+
+ *codepoint = INVALID;
+ return false;
+ }
+ bool previous (hb_codepoint_t *codepoint) const
+ {
+ unsigned int m = (*codepoint - 1) & MASK;
+ if (m == MASK)
+ {
+ *codepoint = INVALID;
+ return false;
+ }
+ unsigned int i = m / ELT_BITS;
+ unsigned int j = m & ELT_MASK;
+
+ /* Fancy mask to avoid shifting by elt_t bitsize, which is undefined. */
+ const elt_t mask = j < 8 * sizeof (elt_t) - 1 ?
+ ((elt_t (1) << (j + 1)) - 1) :
+ (elt_t) -1;
+ const elt_t vv = v[i] & mask;
+ const elt_t *p = &vv;
+ while (true)
+ {
+ if (*p)
+ {
+ *codepoint = i * ELT_BITS + elt_get_max (*p);
+ return true;
+ }
+ if ((int) i <= 0) break;
+ p = &v[--i];
+ }
+
+ *codepoint = INVALID;
+ return false;
+ }
+ hb_codepoint_t get_min () const
+ {
+ for (unsigned int i = 0; i < len (); i++)
+ if (v[i])
+ return i * ELT_BITS + elt_get_min (v[i]);
+ return INVALID;
+ }
+ hb_codepoint_t get_max () const
+ {
+ for (int i = len () - 1; i >= 0; i--)
+ if (v[i])
+ return i * ELT_BITS + elt_get_max (v[i]);
+ return 0;
+ }
+
+ static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
+
+ typedef unsigned long long elt_t;
+ static constexpr unsigned PAGE_BITS = 512;
+ static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
+
+ static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
+ static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
+
+ typedef hb_vector_size_t vector_t;
+
+ static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
+ static constexpr unsigned ELT_MASK = ELT_BITS - 1;
+ static constexpr unsigned BITS = sizeof (vector_t) * 8;
+ static constexpr unsigned MASK = BITS - 1;
+ static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
+
+ elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
+ const elt_t& elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
+ static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
+
+ vector_t v;
+};
+static_assert (hb_bit_page_t::PAGE_BITS == sizeof (hb_bit_page_t) * 8, "");
+
+
+#endif /* HB_BIT_PAGE_HH */
diff --git a/gfx/harfbuzz/src/hb-bit-set-invertible.hh b/gfx/harfbuzz/src/hb-bit-set-invertible.hh
new file mode 100644
index 0000000000..0832b0fc23
--- /dev/null
+++ b/gfx/harfbuzz/src/hb-bit-set-invertible.hh
@@ -0,0 +1,364 @@
+/*
+ * Copyright © 2012,2017 Google, Inc.
+ * Copyright © 2021 Behdad Esfahbod
+ *
+ * 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BIT_SET_INVERTIBLE_HH
+#define HB_BIT_SET_INVERTIBLE_HH
+
+#include "hb.hh"
+#include "hb-bit-set.hh"
+
+
+struct hb_bit_set_invertible_t
+{
+ hb_bit_set_t s;
+ bool inverted = false;
+
+ hb_bit_set_invertible_t () = default;
+ hb_bit_set_invertible_t (hb_bit_set_invertible_t& o) = default;
+ hb_bit_set_invertible_t (hb_bit_set_invertible_t&& o) = default;
+ hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default;
+ hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& o) = default;
+ friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b)
+ {
+ if (likely (!a.s.successful || !b.s.successful))
+ return;
+ hb_swap (a.inverted, b.inverted);
+ hb_swap (a.s, b.s);
+ }
+
+ void init () { s.init (); inverted = false; }
+ void fini () { s.fini (); }
+ void err () { s.err (); }
+ bool in_error () const { return s.in_error (); }
+ explicit operator bool () const { return !is_empty (); }
+
+ void reset ()
+ {
+ s.reset ();
+ inverted = false;
+ }
+ void clear ()
+ {
+ s.clear ();
+ if (likely (s.successful))
+ inverted = false;
+ }
+ void invert ()
+ {
+ if (likely (s.successful))
+ inverted = !inverted;
+ }
+
+ bool is_empty () const
+ {
+ hb_codepoint_t v = INVALID;
+ next (&v);
+ return v == INVALID;
+ }
+ hb_codepoint_t get_min () const
+ {
+ hb_codepoint_t v = INVALID;
+ next (&v);
+ return v;
+ }
+ hb_codepoint_t get_max () const
+ {
+ hb_codepoint_t v = INVALID;
+ previous (&v);
+ return v;
+ }
+ unsigned int get_population () const
+ { return inverted ? INVALID - s.get_population () : s.get_population (); }
+
+
+ void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
+ bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+ { return unlikely (inverted) ? (s.del_range (a, b), true) : s.add_range (a, b); }
+
+ template
+ void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+ { inverted ? s.del_array (array, count, stride) : s.add_array (array, count, stride); }
+ template
+ void add_array (const hb_array_t& arr) { add_array (&arr, arr.len ()); }
+
+ /* Might return false if array looks unsorted.
+ * Used for faster rejection of corrupt data. */
+ template
+ bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+ { return inverted ? s.del_sorted_array (array, count, stride) : s.add_sorted_array (array, count, stride); }
+ template