mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 08:48:39 +09:00
update harfbuzz to 3.2.0
This commit is contained in:
parent
58116e6c55
commit
b5e969b8aa
157 changed files with 14579 additions and 10022 deletions
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -340,11 +340,15 @@ class OpenTypeRegistryParser (HTMLParser):
|
|||
self.from_bcp_47 = collections.defaultdict (set)
|
||||
# Whether the parser is in a <td> element
|
||||
self._td = False
|
||||
# Whether the parser is after a <br> element within the current <tr> element
|
||||
self._br = False
|
||||
# The text of the <td> elements of the current <tr> 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')
|
||||
|
|
|
|||
|
|
@ -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 (" *")
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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<HBUINT16>
|
||||
lookupTable; /* Lookup table that maps glyphs to their
|
||||
|
|
|
|||
|
|
@ -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<Ts> (ds)...));
|
||||
valuesZ.sanitize (c, base, last - first + 1, std::forward<Ts> (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<UnsizedArrayOf<T>>
|
||||
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<T>
|
||||
|
|
@ -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<HBUINT8>
|
||||
|
|
@ -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<HBUCHAR> classArray; /* The class codes (indexed by glyph index minus
|
||||
* firstGlyph). */
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<Ts> (ds)...));
|
||||
case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
|
||||
case 4: return_trace (c->dispatch (u.format4, hb_forward<Ts> (ds)...));
|
||||
case 6: return_trace (c->dispatch (u.format6, hb_forward<Ts> (ds)...));
|
||||
case 0: return_trace (c->dispatch (u.format0, std::forward<Ts> (ds)...));
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
|
||||
case 6: return_trace (c->dispatch (u.format6, std::forward<Ts> (ds)...));
|
||||
default: return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<HBGlyphID> &lookup = subs[entry.data.markIndex];
|
||||
const Lookup<HBGlyphID16> &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<HBGlyphID> &subs_old = (const UnsizedArrayOf<HBGlyphID> &) subs;
|
||||
const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) 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<HBGlyphID> &lookup = subs[entry.data.currentIndex];
|
||||
const Lookup<HBGlyphID16> &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<HBGlyphID> &subs_old = (const UnsizedArrayOf<HBGlyphID> &) subs;
|
||||
const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) 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<Lookup<HBGlyphID>, HBUINT, false> &subs;
|
||||
const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false> &subs;
|
||||
};
|
||||
|
||||
bool apply (hb_aat_apply_context_t *c) const
|
||||
|
|
@ -359,7 +359,7 @@ struct ContextualSubtable
|
|||
protected:
|
||||
StateTable<Types, EntryData>
|
||||
machine;
|
||||
NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID>, HBUINT, false>, HBUINT>
|
||||
NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, 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<HBUINT32> &ligAction;
|
||||
const UnsizedArrayOf<HBUINT16> &component;
|
||||
const UnsizedArrayOf<HBGlyphID> &ligature;
|
||||
const UnsizedArrayOf<HBGlyphID16> &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<UnsizedArrayOf<HBUINT16>, HBUINT>
|
||||
component; /* Offset to the component table. */
|
||||
NNOffsetTo<UnsizedArrayOf<HBGlyphID>, HBUINT>
|
||||
NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, 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<HBGlyphID> substitute;
|
||||
Lookup<HBGlyphID16> 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<HBGlyphID> &insertionAction;
|
||||
const UnsizedArrayOf<HBGlyphID16> &insertionAction;
|
||||
};
|
||||
|
||||
bool apply (hb_aat_apply_context_t *c) const
|
||||
|
|
@ -836,7 +836,7 @@ struct InsertionSubtable
|
|||
protected:
|
||||
StateTable<Types, EntryData>
|
||||
machine;
|
||||
NNOffsetTo<UnsizedArrayOf<HBGlyphID>, HBUINT>
|
||||
NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, 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<Ts> (ds)...));
|
||||
case Contextual: return_trace (c->dispatch (u.contextual, hb_forward<Ts> (ds)...));
|
||||
case Ligature: return_trace (c->dispatch (u.ligature, hb_forward<Ts> (ds)...));
|
||||
case Noncontextual: return_trace (c->dispatch (u.noncontextual, hb_forward<Ts> (ds)...));
|
||||
case Insertion: return_trace (c->dispatch (u.insertion, hb_forward<Ts> (ds)...));
|
||||
case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward<Ts> (ds)...));
|
||||
case Contextual: return_trace (c->dispatch (u.contextual, std::forward<Ts> (ds)...));
|
||||
case Ligature: return_trace (c->dispatch (u.ligature, std::forward<Ts> (ds)...));
|
||||
case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward<Ts> (ds)...));
|
||||
case Insertion: return_trace (c->dispatch (u.insertion, std::forward<Ts> (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);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@
|
|||
#include "hb-null.hh"
|
||||
#include "hb-number.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <new>
|
||||
|
||||
/*
|
||||
* Flags
|
||||
|
|
@ -125,7 +128,7 @@ struct BEInt<Type, 2>
|
|||
template <typename Type>
|
||||
struct BEInt<Type, 3>
|
||||
{
|
||||
static_assert (!hb_is_signed (Type), "");
|
||||
static_assert (!std::is_signed<Type>::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 <typename T> constexpr auto
|
||||
operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )
|
||||
operator () (T&& v) const HB_AUTO_RETURN ( std::forward<T> (v) )
|
||||
}
|
||||
HB_FUNCOBJ (hb_identity);
|
||||
struct
|
||||
|
|
@ -203,7 +206,7 @@ HB_FUNCOBJ (hb_ridentity);
|
|||
struct
|
||||
{
|
||||
template <typename T> constexpr bool
|
||||
operator () (T&& v) const { return bool (hb_forward<T> (v)); }
|
||||
operator () (T&& v) const { return bool (std::forward<T> (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 <typename T,
|
||||
hb_enable_if (hb_is_integral (T))> constexpr auto
|
||||
hb_enable_if (std::is_integral<T>::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 <typename Appl, typename T, typename ...Ts> auto
|
||||
impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
|
||||
((hb_deref (hb_forward<T> (v)).*hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
|
||||
((hb_deref (std::forward<T> (v)).*std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
|
||||
|
||||
/* Pointer-to-member. */
|
||||
template <typename Appl, typename T> auto
|
||||
impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
|
||||
((hb_deref (hb_forward<T> (v))).*hb_forward<Appl> (a))
|
||||
((hb_deref (std::forward<T> (v))).*std::forward<Appl> (a))
|
||||
|
||||
/* Operator(). */
|
||||
template <typename Appl, typename ...Ts> auto
|
||||
impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
|
||||
(hb_deref (hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
|
||||
(hb_deref (std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
|
||||
|
||||
public:
|
||||
|
||||
template <typename Appl, typename ...Ts> auto
|
||||
operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
|
||||
(
|
||||
impl (hb_forward<Appl> (a),
|
||||
impl (std::forward<Appl> (a),
|
||||
hb_prioritize,
|
||||
hb_forward<Ts> (ds)...)
|
||||
std::forward<Ts> (ds)...)
|
||||
)
|
||||
}
|
||||
HB_FUNCOBJ (hb_invoke);
|
||||
|
|
@ -275,9 +278,9 @@ struct hb_partial_t
|
|||
hb_declval (V),
|
||||
hb_declval (Ts)...))
|
||||
{
|
||||
return hb_invoke (hb_forward<Appl> (a),
|
||||
hb_forward<V> (v),
|
||||
hb_forward<Ts> (ds)...);
|
||||
return hb_invoke (std::forward<Appl> (a),
|
||||
std::forward<V> (v),
|
||||
std::forward<Ts> (ds)...);
|
||||
}
|
||||
template <typename T0, typename ...Ts,
|
||||
unsigned P = Pos,
|
||||
|
|
@ -287,10 +290,10 @@ struct hb_partial_t
|
|||
hb_declval (V),
|
||||
hb_declval (Ts)...))
|
||||
{
|
||||
return hb_invoke (hb_forward<Appl> (a),
|
||||
hb_forward<T0> (d0),
|
||||
hb_forward<V> (v),
|
||||
hb_forward<Ts> (ds)...);
|
||||
return hb_invoke (std::forward<Appl> (a),
|
||||
std::forward<T0> (d0),
|
||||
std::forward<V> (v),
|
||||
std::forward<Ts> (ds)...);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -324,14 +327,14 @@ auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
|
|||
#define HB_PARTIALIZE(Pos) \
|
||||
template <typename _T> \
|
||||
decltype(auto) operator () (_T&& _v) const \
|
||||
{ return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \
|
||||
{ return hb_partial<Pos> (this, std::forward<_T> (_v)); } \
|
||||
static_assert (true, "")
|
||||
#else
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1724 */
|
||||
#define HB_PARTIALIZE(Pos) \
|
||||
template <typename _T> \
|
||||
auto operator () (_T&& _v) const HB_AUTO_RETURN \
|
||||
(hb_partial<Pos> (+this, hb_forward<_T> (_v))) \
|
||||
(hb_partial<Pos> (+this, std::forward<_T> (_v))) \
|
||||
static_assert (true, "")
|
||||
#endif
|
||||
|
||||
|
|
@ -343,22 +346,22 @@ struct
|
|||
template <typename Pred, typename Val> auto
|
||||
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v))
|
||||
hb_deref (std::forward<Pred> (p)).has (std::forward<Val> (v))
|
||||
)
|
||||
|
||||
template <typename Pred, typename Val> auto
|
||||
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_invoke (hb_forward<Pred> (p),
|
||||
hb_forward<Val> (v))
|
||||
hb_invoke (std::forward<Pred> (p),
|
||||
std::forward<Val> (v))
|
||||
)
|
||||
|
||||
public:
|
||||
|
||||
template <typename Pred, typename Val> auto
|
||||
operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
|
||||
impl (hb_forward<Pred> (p),
|
||||
hb_forward<Val> (v),
|
||||
impl (std::forward<Pred> (p),
|
||||
std::forward<Val> (v),
|
||||
hb_prioritize)
|
||||
)
|
||||
}
|
||||
|
|
@ -371,22 +374,22 @@ struct
|
|||
template <typename Pred, typename Val> auto
|
||||
impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_has (hb_forward<Pred> (p),
|
||||
hb_forward<Val> (v))
|
||||
hb_has (std::forward<Pred> (p),
|
||||
std::forward<Val> (v))
|
||||
)
|
||||
|
||||
template <typename Pred, typename Val> auto
|
||||
impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_forward<Pred> (p) == hb_forward<Val> (v)
|
||||
std::forward<Pred> (p) == std::forward<Val> (v)
|
||||
)
|
||||
|
||||
public:
|
||||
|
||||
template <typename Pred, typename Val> auto
|
||||
operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
|
||||
impl (hb_forward<Pred> (p),
|
||||
hb_forward<Val> (v),
|
||||
impl (std::forward<Pred> (p),
|
||||
std::forward<Val> (v),
|
||||
hb_prioritize)
|
||||
)
|
||||
}
|
||||
|
|
@ -399,20 +402,20 @@ struct
|
|||
template <typename Proj, typename Val> auto
|
||||
impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v))
|
||||
hb_deref (std::forward<Proj> (f)).get (std::forward<Val> (v))
|
||||
)
|
||||
|
||||
template <typename Proj, typename Val> auto
|
||||
impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_invoke (hb_forward<Proj> (f),
|
||||
hb_forward<Val> (v))
|
||||
hb_invoke (std::forward<Proj> (f),
|
||||
std::forward<Val> (v))
|
||||
)
|
||||
|
||||
template <typename Proj, typename Val> auto
|
||||
impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_forward<Proj> (f)[hb_forward<Val> (v)]
|
||||
std::forward<Proj> (f)[std::forward<Val> (v)]
|
||||
)
|
||||
|
||||
public:
|
||||
|
|
@ -420,8 +423,8 @@ struct
|
|||
template <typename Proj, typename Val> auto
|
||||
operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN
|
||||
(
|
||||
impl (hb_forward<Proj> (f),
|
||||
hb_forward<Val> (v),
|
||||
impl (std::forward<Proj> (f),
|
||||
std::forward<Val> (v),
|
||||
hb_prioritize)
|
||||
)
|
||||
}
|
||||
|
|
@ -434,19 +437,19 @@ struct
|
|||
template <typename T1, typename T2> auto
|
||||
impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_forward<T2> (v2).cmp (hb_forward<T1> (v1)) == 0
|
||||
std::forward<T2> (v2).cmp (std::forward<T1> (v1)) == 0
|
||||
)
|
||||
|
||||
template <typename T1, typename T2> auto
|
||||
impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_forward<T1> (v1).cmp (hb_forward<T2> (v2)) == 0
|
||||
std::forward<T1> (v1).cmp (std::forward<T2> (v2)) == 0
|
||||
)
|
||||
|
||||
template <typename T1, typename T2> auto
|
||||
impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
|
||||
(
|
||||
hb_forward<T1> (v1) == hb_forward<T2> (v2)
|
||||
std::forward<T1> (v1) == std::forward<T2> (v2)
|
||||
)
|
||||
|
||||
public:
|
||||
|
|
@ -454,8 +457,8 @@ struct
|
|||
template <typename T1, typename T2> auto
|
||||
operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN
|
||||
(
|
||||
impl (hb_forward<T1> (v1),
|
||||
hb_forward<T2> (v2),
|
||||
impl (std::forward<T1> (v1),
|
||||
std::forward<T2> (v2),
|
||||
hb_prioritize)
|
||||
)
|
||||
}
|
||||
|
|
@ -515,24 +518,34 @@ struct
|
|||
{
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
|
||||
(a <= b ? hb_forward<T> (a) : hb_forward<T2> (b))
|
||||
(a <= b ? std::forward<T> (a) : std::forward<T2> (b))
|
||||
}
|
||||
HB_FUNCOBJ (hb_min);
|
||||
struct
|
||||
{
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
|
||||
(a >= b ? hb_forward<T> (a) : hb_forward<T2> (b))
|
||||
(a >= b ? std::forward<T> (a) : std::forward<T2> (b))
|
||||
}
|
||||
HB_FUNCOBJ (hb_max);
|
||||
struct
|
||||
{
|
||||
template <typename T, typename T2, typename T3> constexpr auto
|
||||
operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN
|
||||
(hb_min (hb_max (hb_forward<T> (x), hb_forward<T2> (min)), hb_forward<T3> (max)))
|
||||
(hb_min (hb_max (std::forward<T> (x), std::forward<T2> (min)), std::forward<T3> (max)))
|
||||
}
|
||||
HB_FUNCOBJ (hb_clamp);
|
||||
|
||||
struct
|
||||
{
|
||||
template <typename T> 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 <typename T> static inline bool
|
||||
hb_in_range (T u, T lo, T hi)
|
||||
{
|
||||
static_assert (!hb_is_signed<T>::value, "");
|
||||
static_assert (!std::is_signed<T>::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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_ge);
|
||||
struct
|
||||
{
|
||||
template <typename T> constexpr auto
|
||||
|
|
@ -1195,6 +1234,12 @@ struct
|
|||
}
|
||||
HB_FUNCOBJ (hb_sub);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a)
|
||||
}
|
||||
HB_FUNCOBJ (hb_rsub);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
|
||||
|
|
|
|||
|
|
@ -36,20 +36,34 @@
|
|||
template <typename Type>
|
||||
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 <typename Type>
|
||||
struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, 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 <unsigned int length_>
|
||||
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 <typename U,
|
||||
hb_enable_if (hb_is_cr_convertible(U, Type))>
|
||||
hb_array_t (const hb_array_t<U> &o) :
|
||||
constexpr hb_array_t (const hb_array_t<U> &o) :
|
||||
hb_iter_with_fallback_t<hb_array_t, Type&> (),
|
||||
arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {}
|
||||
template <typename U,
|
||||
|
|
@ -139,7 +153,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
return lfind (x, &i) ? &this->arrayZ[i] : not_found;
|
||||
}
|
||||
template <typename T>
|
||||
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<hb_array_t<Type>, 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<hb_array_t<Type>, Type&>
|
|||
*/
|
||||
|
||||
public:
|
||||
Type *arrayZ;
|
||||
unsigned int length;
|
||||
unsigned int backwards_length;
|
||||
Type *arrayZ = nullptr;
|
||||
unsigned int length = 0;
|
||||
unsigned int backwards_length = 0;
|
||||
};
|
||||
template <typename T> inline hb_array_t<T>
|
||||
hb_array (T *array, unsigned int length)
|
||||
|
|
@ -266,13 +298,6 @@ template <typename T, unsigned int length_> inline hb_array_t<T>
|
|||
hb_array (T (&array_)[length_])
|
||||
{ return hb_array_t<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 <typename Type>
|
||||
struct hb_sorted_array_t :
|
||||
hb_iter_t<hb_sorted_array_t<Type>, 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<Type> () {}
|
||||
hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (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<Type> (array_, length_) {}
|
||||
template <unsigned int length_>
|
||||
hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
|
||||
constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
|
||||
|
||||
template <typename U,
|
||||
hb_enable_if (hb_is_cr_convertible(U, Type))>
|
||||
hb_sorted_array_t (const hb_array_t<U> &o) :
|
||||
constexpr hb_sorted_array_t (const hb_array_t<U> &o) :
|
||||
hb_iter_t<hb_sorted_array_t, Type&> (),
|
||||
hb_array_t<Type> (o) {}
|
||||
template <typename U,
|
||||
|
|
@ -323,7 +354,7 @@ struct hb_sorted_array_t :
|
|||
}
|
||||
template <typename T>
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
203
gfx/harfbuzz/src/hb-bit-page.hh
Normal file
203
gfx/harfbuzz/src/hb-bit-page.hh
Normal file
|
|
@ -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<elt_t, PAGE_BITS / 8> 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 */
|
||||
364
gfx/harfbuzz/src/hb-bit-set-invertible.hh
Normal file
364
gfx/harfbuzz/src/hb-bit-set-invertible.hh
Normal file
|
|
@ -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 <typename T>
|
||||
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 <typename T>
|
||||
void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
|
||||
|
||||
/* Might return false if array looks unsorted.
|
||||
* Used for faster rejection of corrupt data. */
|
||||
template <typename T>
|
||||
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 <typename T>
|
||||
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
|
||||
|
||||
void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); }
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{ unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); }
|
||||
|
||||
bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
|
||||
|
||||
/* Has interface. */
|
||||
static constexpr bool SENTINEL = false;
|
||||
typedef bool value_t;
|
||||
value_t operator [] (hb_codepoint_t k) const { return get (k); }
|
||||
bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
|
||||
/* Predicate. */
|
||||
bool operator () (hb_codepoint_t k) const { return has (k); }
|
||||
|
||||
/* Sink interface. */
|
||||
hb_bit_set_invertible_t& operator << (hb_codepoint_t v)
|
||||
{ add (v); return *this; }
|
||||
hb_bit_set_invertible_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{
|
||||
hb_codepoint_t c = first - 1;
|
||||
return next (&c) && c <= last;
|
||||
}
|
||||
|
||||
void set (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
s.set (other.s);
|
||||
if (likely (s.successful))
|
||||
inverted = other.inverted;
|
||||
}
|
||||
|
||||
bool is_equal (const hb_bit_set_invertible_t &other) const
|
||||
{
|
||||
if (likely (inverted == other.inverted))
|
||||
return s.is_equal (other.s);
|
||||
else
|
||||
{
|
||||
/* TODO Add iter_ranges() and use here. */
|
||||
auto it1 = iter ();
|
||||
auto it2 = other.iter ();
|
||||
return hb_all (+ hb_zip (it1, it2)
|
||||
| hb_map ([](hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) { return _.first == _.second; }));
|
||||
}
|
||||
}
|
||||
|
||||
bool is_subset (const hb_bit_set_invertible_t &larger_set) const
|
||||
{
|
||||
if (unlikely (inverted != larger_set.inverted))
|
||||
return hb_all (hb_iter (s) | hb_map (larger_set.s));
|
||||
else
|
||||
return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s);
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename Op>
|
||||
void process (const Op& op, const hb_bit_set_invertible_t &other)
|
||||
{ s.process (op, other.s); }
|
||||
public:
|
||||
void union_ (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
if (likely (inverted == other.inverted))
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_and, other);
|
||||
else
|
||||
process (hb_bitwise_or, other); /* Main branch. */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_gt, other);
|
||||
else
|
||||
process (hb_bitwise_lt, other);
|
||||
}
|
||||
if (likely (s.successful))
|
||||
inverted = inverted || other.inverted;
|
||||
}
|
||||
void intersect (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
if (likely (inverted == other.inverted))
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_or, other);
|
||||
else
|
||||
process (hb_bitwise_and, other); /* Main branch. */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_lt, other);
|
||||
else
|
||||
process (hb_bitwise_gt, other);
|
||||
}
|
||||
if (likely (s.successful))
|
||||
inverted = inverted && other.inverted;
|
||||
}
|
||||
void subtract (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
if (likely (inverted == other.inverted))
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_lt, other);
|
||||
else
|
||||
process (hb_bitwise_gt, other); /* Main branch. */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (inverted))
|
||||
process (hb_bitwise_or, other);
|
||||
else
|
||||
process (hb_bitwise_and, other);
|
||||
}
|
||||
if (likely (s.successful))
|
||||
inverted = inverted && !other.inverted;
|
||||
}
|
||||
void symmetric_difference (const hb_bit_set_invertible_t &other)
|
||||
{
|
||||
process (hb_bitwise_xor, other);
|
||||
if (likely (s.successful))
|
||||
inverted = inverted ^ other.inverted;
|
||||
}
|
||||
|
||||
bool next (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
if (likely (!inverted))
|
||||
return s.next (codepoint);
|
||||
|
||||
auto old = *codepoint;
|
||||
if (unlikely (old + 1 == INVALID))
|
||||
{
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto v = old;
|
||||
s.next (&v);
|
||||
if (old + 1 < v)
|
||||
{
|
||||
*codepoint = old + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
v = old;
|
||||
s.next_range (&old, &v);
|
||||
|
||||
*codepoint = v + 1;
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
bool previous (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
if (likely (!inverted))
|
||||
return s.previous (codepoint);
|
||||
|
||||
auto old = *codepoint;
|
||||
if (unlikely (old - 1 == INVALID))
|
||||
{
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto v = old;
|
||||
s.previous (&v);
|
||||
|
||||
if (old - 1 > v || v == INVALID)
|
||||
{
|
||||
*codepoint = old - 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
v = old;
|
||||
s.previous_range (&v, &old);
|
||||
|
||||
*codepoint = v - 1;
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
if (likely (!inverted))
|
||||
return s.next_range (first, last);
|
||||
|
||||
if (!next (last))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
*first = *last;
|
||||
s.next (last);
|
||||
--*last;
|
||||
return true;
|
||||
}
|
||||
bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
if (likely (!inverted))
|
||||
return s.previous_range (first, last);
|
||||
|
||||
if (!previous (first))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
*last = *first;
|
||||
s.previous (first);
|
||||
++*first;
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID;
|
||||
|
||||
/*
|
||||
* Iterator implementation.
|
||||
*/
|
||||
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
|
||||
{
|
||||
static constexpr bool is_sorted_iterator = true;
|
||||
iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t),
|
||||
bool init = true) : s (&s_), v (INVALID), l(0)
|
||||
{
|
||||
if (init)
|
||||
{
|
||||
l = s->get_population () + 1;
|
||||
__next__ ();
|
||||
}
|
||||
}
|
||||
|
||||
typedef hb_codepoint_t __item_t__;
|
||||
hb_codepoint_t __item__ () const { return v; }
|
||||
bool __more__ () const { return v != INVALID; }
|
||||
void __next__ () { s->next (&v); if (l) l--; }
|
||||
void __prev__ () { s->previous (&v); }
|
||||
unsigned __len__ () const { return l; }
|
||||
iter_t end () const { return iter_t (*s, false); }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return s != o.s || v != o.v; }
|
||||
|
||||
protected:
|
||||
const hb_bit_set_invertible_t *s;
|
||||
hb_codepoint_t v;
|
||||
unsigned l;
|
||||
};
|
||||
iter_t iter () const { return iter_t (*this); }
|
||||
operator iter_t () const { return iter (); }
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_BIT_SET_INVERTIBLE_HH */
|
||||
817
gfx/harfbuzz/src/hb-bit-set.hh
Normal file
817
gfx/harfbuzz/src/hb-bit-set.hh
Normal file
|
|
@ -0,0 +1,817 @@
|
|||
/*
|
||||
* 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_HH
|
||||
#define HB_BIT_SET_HH
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-bit-page.hh"
|
||||
#include "hb-machinery.hh"
|
||||
|
||||
|
||||
struct hb_bit_set_t
|
||||
{
|
||||
hb_bit_set_t () = default;
|
||||
~hb_bit_set_t () = default;
|
||||
|
||||
hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other); }
|
||||
hb_bit_set_t ( hb_bit_set_t&& other) : hb_bit_set_t () { hb_swap (*this, other); }
|
||||
hb_bit_set_t& operator= (const hb_bit_set_t& other) { set (other); return *this; }
|
||||
hb_bit_set_t& operator= (hb_bit_set_t&& other) { hb_swap (*this, other); return *this; }
|
||||
friend void swap (hb_bit_set_t &a, hb_bit_set_t &b)
|
||||
{
|
||||
if (likely (!a.successful || !b.successful))
|
||||
return;
|
||||
hb_swap (a.population, b.population);
|
||||
hb_swap (a.last_page_lookup, b.last_page_lookup);
|
||||
hb_swap (a.page_map, b.page_map);
|
||||
hb_swap (a.pages, b.pages);
|
||||
}
|
||||
|
||||
void init ()
|
||||
{
|
||||
successful = true;
|
||||
population = 0;
|
||||
last_page_lookup = 0;
|
||||
page_map.init ();
|
||||
pages.init ();
|
||||
}
|
||||
void fini ()
|
||||
{
|
||||
page_map.fini ();
|
||||
pages.fini ();
|
||||
}
|
||||
|
||||
using page_t = hb_bit_page_t;
|
||||
struct page_map_t
|
||||
{
|
||||
int cmp (const page_map_t &o) const { return cmp (o.major); }
|
||||
int cmp (uint32_t o_major) const { return (int) o_major - (int) major; }
|
||||
|
||||
uint32_t major;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
bool successful = true; /* Allocations successful */
|
||||
mutable unsigned int population = 0;
|
||||
mutable unsigned int last_page_lookup = 0;
|
||||
hb_sorted_vector_t<page_map_t> page_map;
|
||||
hb_vector_t<page_t> pages;
|
||||
|
||||
void err () { if (successful) successful = false; } /* TODO Remove */
|
||||
bool in_error () const { return !successful; }
|
||||
|
||||
bool resize (unsigned int count)
|
||||
{
|
||||
if (unlikely (!successful)) return false;
|
||||
if (unlikely (!pages.resize (count) || !page_map.resize (count)))
|
||||
{
|
||||
pages.resize (page_map.length);
|
||||
successful = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
successful = true;
|
||||
clear ();
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
resize (0);
|
||||
if (likely (successful))
|
||||
population = 0;
|
||||
}
|
||||
bool is_empty () const
|
||||
{
|
||||
unsigned int count = pages.length;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!pages[i].is_empty ())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
explicit operator bool () const { return !is_empty (); }
|
||||
|
||||
private:
|
||||
void dirty () { population = UINT_MAX; }
|
||||
public:
|
||||
|
||||
void add (hb_codepoint_t g)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
if (unlikely (g == INVALID)) return;
|
||||
dirty ();
|
||||
page_t *page = page_for (g, true); if (unlikely (!page)) return;
|
||||
page->add (g);
|
||||
}
|
||||
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
|
||||
if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
|
||||
dirty ();
|
||||
unsigned int ma = get_major (a);
|
||||
unsigned int mb = get_major (b);
|
||||
if (ma == mb)
|
||||
{
|
||||
page_t *page = page_for (a, true); if (unlikely (!page)) return false;
|
||||
page->add_range (a, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
page_t *page = page_for (a, true); if (unlikely (!page)) return false;
|
||||
page->add_range (a, major_start (ma + 1) - 1);
|
||||
|
||||
for (unsigned int m = ma + 1; m < mb; m++)
|
||||
{
|
||||
page = page_for (major_start (m), true); if (unlikely (!page)) return false;
|
||||
page->init1 ();
|
||||
}
|
||||
|
||||
page = page_for (b, true); if (unlikely (!page)) return false;
|
||||
page->add_range (major_start (mb), b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void set_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
if (!count) return;
|
||||
dirty ();
|
||||
hb_codepoint_t g = *array;
|
||||
while (count)
|
||||
{
|
||||
unsigned int m = get_major (g);
|
||||
page_t *page = page_for (g, v); if (unlikely (v && !page)) return;
|
||||
unsigned int start = major_start (m);
|
||||
unsigned int end = major_start (m + 1);
|
||||
do
|
||||
{
|
||||
if (v || page) /* The v check is to optimize out the page check if v is true. */
|
||||
page->set (g, v);
|
||||
|
||||
array = &StructAtOffsetUnaligned<T> (array, stride);
|
||||
count--;
|
||||
}
|
||||
while (count && (g = *array, start <= g && g < end));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ set_array (true, array, count, stride); }
|
||||
template <typename T>
|
||||
void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
|
||||
|
||||
template <typename T>
|
||||
void del_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ set_array (false, array, count, stride); }
|
||||
template <typename T>
|
||||
void del_array (const hb_array_t<const T>& arr) { del_array (&arr, arr.len ()); }
|
||||
|
||||
/* Might return false if array looks unsorted.
|
||||
* Used for faster rejection of corrupt data. */
|
||||
template <typename T>
|
||||
bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{
|
||||
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
|
||||
if (!count) return true;
|
||||
dirty ();
|
||||
hb_codepoint_t g = *array;
|
||||
hb_codepoint_t last_g = g;
|
||||
while (count)
|
||||
{
|
||||
unsigned int m = get_major (g);
|
||||
page_t *page = page_for (g, v); if (unlikely (v && !page)) return false;
|
||||
unsigned int end = major_start (m + 1);
|
||||
do
|
||||
{
|
||||
/* If we try harder we can change the following comparison to <=;
|
||||
* Not sure if it's worth it. */
|
||||
if (g < last_g) return false;
|
||||
last_g = g;
|
||||
|
||||
if (v || page) /* The v check is to optimize out the page check if v is true. */
|
||||
page->add (g);
|
||||
|
||||
array = (const T *) ((const char *) array + stride);
|
||||
count--;
|
||||
}
|
||||
while (count && (g = *array, g < end));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ return set_sorted_array (true, array, count, stride); }
|
||||
template <typename T>
|
||||
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
|
||||
|
||||
template <typename T>
|
||||
bool del_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
|
||||
{ return set_sorted_array (false, array, count, stride); }
|
||||
template <typename T>
|
||||
bool del_sorted_array (const hb_sorted_array_t<const T>& arr) { return del_sorted_array (&arr, arr.len ()); }
|
||||
|
||||
void del (hb_codepoint_t g)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
page_t *page = page_for (g);
|
||||
if (!page)
|
||||
return;
|
||||
dirty ();
|
||||
page->del (g);
|
||||
}
|
||||
|
||||
private:
|
||||
void del_pages (int ds, int de)
|
||||
{
|
||||
if (ds <= de)
|
||||
{
|
||||
// Pre-allocate the workspace that compact() will need so we can bail on allocation failure
|
||||
// before attempting to rewrite the page map.
|
||||
hb_vector_t<unsigned> compact_workspace;
|
||||
if (unlikely (!allocate_compact_workspace (compact_workspace))) return;
|
||||
|
||||
unsigned int write_index = 0;
|
||||
for (unsigned int i = 0; i < page_map.length; i++)
|
||||
{
|
||||
int m = (int) page_map[i].major;
|
||||
if (m < ds || de < m)
|
||||
page_map[write_index++] = page_map[i];
|
||||
}
|
||||
compact (compact_workspace, write_index);
|
||||
resize (write_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
if (unlikely (a > b || a == INVALID)) return;
|
||||
dirty ();
|
||||
unsigned int ma = get_major (a);
|
||||
unsigned int mb = get_major (b);
|
||||
/* Delete pages from ds through de if ds <= de. */
|
||||
int ds = (a == major_start (ma))? (int) ma: (int) (ma + 1);
|
||||
int de = (b + 1 == major_start (mb + 1))? (int) mb: ((int) mb - 1);
|
||||
if (ds > de || (int) ma < ds)
|
||||
{
|
||||
page_t *page = page_for (a);
|
||||
if (page)
|
||||
{
|
||||
if (ma == mb)
|
||||
page->del_range (a, b);
|
||||
else
|
||||
page->del_range (a, major_start (ma + 1) - 1);
|
||||
}
|
||||
}
|
||||
if (de < (int) mb && ma != mb)
|
||||
{
|
||||
page_t *page = page_for (b);
|
||||
if (page)
|
||||
page->del_range (major_start (mb), b);
|
||||
}
|
||||
del_pages (ds, de);
|
||||
}
|
||||
|
||||
bool get (hb_codepoint_t g) const
|
||||
{
|
||||
const page_t *page = page_for (g);
|
||||
if (!page)
|
||||
return false;
|
||||
return page->get (g);
|
||||
}
|
||||
|
||||
/* Has interface. */
|
||||
static constexpr bool SENTINEL = false;
|
||||
typedef bool value_t;
|
||||
value_t operator [] (hb_codepoint_t k) const { return get (k); }
|
||||
bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
|
||||
/* Predicate. */
|
||||
bool operator () (hb_codepoint_t k) const { return has (k); }
|
||||
|
||||
/* Sink interface. */
|
||||
hb_bit_set_t& operator << (hb_codepoint_t v)
|
||||
{ add (v); return *this; }
|
||||
hb_bit_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{
|
||||
hb_codepoint_t c = first - 1;
|
||||
return next (&c) && c <= last;
|
||||
}
|
||||
void set (const hb_bit_set_t &other)
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
unsigned int count = other.pages.length;
|
||||
if (unlikely (!resize (count)))
|
||||
return;
|
||||
population = other.population;
|
||||
|
||||
/* TODO switch to vector operator =. */
|
||||
hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size);
|
||||
hb_memcpy ((void *) page_map, (const void *) other.page_map, count * page_map.item_size);
|
||||
}
|
||||
|
||||
bool is_equal (const hb_bit_set_t &other) const
|
||||
{
|
||||
if (has_population () && other.has_population () &&
|
||||
get_population () != other.get_population ())
|
||||
return false;
|
||||
|
||||
unsigned int na = pages.length;
|
||||
unsigned int nb = other.pages.length;
|
||||
|
||||
unsigned int a = 0, b = 0;
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_at (a).is_empty ()) { a++; continue; }
|
||||
if (other.page_at (b).is_empty ()) { b++; continue; }
|
||||
if (page_map[a].major != other.page_map[b].major ||
|
||||
!page_at (a).is_equal (other.page_at (b)))
|
||||
return false;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
for (; a < na; a++)
|
||||
if (!page_at (a).is_empty ()) { return false; }
|
||||
for (; b < nb; b++)
|
||||
if (!other.page_at (b).is_empty ()) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_subset (const hb_bit_set_t &larger_set) const
|
||||
{
|
||||
if (has_population () && larger_set.has_population () &&
|
||||
get_population () != larger_set.get_population ())
|
||||
return false;
|
||||
|
||||
uint32_t spi = 0;
|
||||
for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++)
|
||||
{
|
||||
uint32_t spm = page_map[spi].major;
|
||||
uint32_t lpm = larger_set.page_map[lpi].major;
|
||||
auto sp = page_at (spi);
|
||||
auto lp = larger_set.page_at (lpi);
|
||||
|
||||
if (spm < lpm && !sp.is_empty ())
|
||||
return false;
|
||||
|
||||
if (lpm < spm)
|
||||
continue;
|
||||
|
||||
if (!sp.is_subset (lp))
|
||||
return false;
|
||||
|
||||
spi++;
|
||||
}
|
||||
|
||||
while (spi < page_map.length)
|
||||
if (!page_at (spi++).is_empty ())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool allocate_compact_workspace (hb_vector_t<unsigned>& workspace)
|
||||
{
|
||||
if (unlikely (!workspace.resize (pages.length)))
|
||||
{
|
||||
successful = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* workspace should be a pre-sized vector allocated to hold at exactly pages.length
|
||||
* elements.
|
||||
*/
|
||||
void compact (hb_vector_t<unsigned>& workspace,
|
||||
unsigned int length)
|
||||
{
|
||||
assert(workspace.length == pages.length);
|
||||
hb_vector_t<unsigned>& old_index_to_page_map_index = workspace;
|
||||
|
||||
hb_fill (old_index_to_page_map_index.writer(), 0xFFFFFFFF);
|
||||
for (unsigned i = 0; i < length; i++)
|
||||
old_index_to_page_map_index[page_map[i].index] = i;
|
||||
|
||||
compact_pages (old_index_to_page_map_index);
|
||||
}
|
||||
void compact_pages (const hb_vector_t<unsigned>& old_index_to_page_map_index)
|
||||
{
|
||||
unsigned int write_index = 0;
|
||||
for (unsigned int i = 0; i < pages.length; i++)
|
||||
{
|
||||
if (old_index_to_page_map_index[i] == 0xFFFFFFFF) continue;
|
||||
|
||||
if (write_index < i)
|
||||
pages[write_index] = pages[i];
|
||||
|
||||
page_map[old_index_to_page_map_index[i]].index = write_index;
|
||||
write_index++;
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
template <typename Op>
|
||||
void process (const Op& op, const hb_bit_set_t &other)
|
||||
{
|
||||
const bool passthru_left = op (1, 0);
|
||||
const bool passthru_right = op (0, 1);
|
||||
|
||||
if (unlikely (!successful)) return;
|
||||
|
||||
dirty ();
|
||||
|
||||
unsigned int na = pages.length;
|
||||
unsigned int nb = other.pages.length;
|
||||
unsigned int next_page = na;
|
||||
|
||||
unsigned int count = 0, newCount = 0;
|
||||
unsigned int a = 0, b = 0;
|
||||
unsigned int write_index = 0;
|
||||
|
||||
// Pre-allocate the workspace that compact() will need so we can bail on allocation failure
|
||||
// before attempting to rewrite the page map.
|
||||
hb_vector_t<unsigned> compact_workspace;
|
||||
if (!passthru_left && unlikely (!allocate_compact_workspace (compact_workspace))) return;
|
||||
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_map[a].major == other.page_map[b].major)
|
||||
{
|
||||
if (!passthru_left)
|
||||
{
|
||||
// Move page_map entries that we're keeping from the left side set
|
||||
// to the front of the page_map vector. This isn't necessary if
|
||||
// passthru_left is set since no left side pages will be removed
|
||||
// in that case.
|
||||
if (write_index < a)
|
||||
page_map[write_index] = page_map[a];
|
||||
write_index++;
|
||||
}
|
||||
|
||||
count++;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
else if (page_map[a].major < other.page_map[b].major)
|
||||
{
|
||||
if (passthru_left)
|
||||
count++;
|
||||
a++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (passthru_right)
|
||||
count++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
if (passthru_left)
|
||||
count += na - a;
|
||||
if (passthru_right)
|
||||
count += nb - b;
|
||||
|
||||
if (!passthru_left)
|
||||
{
|
||||
na = write_index;
|
||||
next_page = write_index;
|
||||
compact (compact_workspace, write_index);
|
||||
}
|
||||
|
||||
if (unlikely (!resize (count)))
|
||||
return;
|
||||
|
||||
newCount = count;
|
||||
|
||||
/* Process in-place backward. */
|
||||
a = na;
|
||||
b = nb;
|
||||
for (; a && b; )
|
||||
{
|
||||
if (page_map[a - 1].major == other.page_map[b - 1].major)
|
||||
{
|
||||
a--;
|
||||
b--;
|
||||
count--;
|
||||
page_map[count] = page_map[a];
|
||||
page_at (count).v = op (page_at (a).v, other.page_at (b).v);
|
||||
}
|
||||
else if (page_map[a - 1].major > other.page_map[b - 1].major)
|
||||
{
|
||||
a--;
|
||||
if (passthru_left)
|
||||
{
|
||||
count--;
|
||||
page_map[count] = page_map[a];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
b--;
|
||||
if (passthru_right)
|
||||
{
|
||||
count--;
|
||||
page_map[count].major = other.page_map[b].major;
|
||||
page_map[count].index = next_page++;
|
||||
page_at (count).v = other.page_at (b).v;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (passthru_left)
|
||||
while (a)
|
||||
{
|
||||
a--;
|
||||
count--;
|
||||
page_map[count] = page_map [a];
|
||||
}
|
||||
if (passthru_right)
|
||||
while (b)
|
||||
{
|
||||
b--;
|
||||
count--;
|
||||
page_map[count].major = other.page_map[b].major;
|
||||
page_map[count].index = next_page++;
|
||||
page_at (count).v = other.page_at (b).v;
|
||||
}
|
||||
assert (!count);
|
||||
resize (newCount);
|
||||
}
|
||||
|
||||
void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); }
|
||||
void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); }
|
||||
void subtract (const hb_bit_set_t &other) { process (hb_bitwise_gt, other); }
|
||||
void symmetric_difference (const hb_bit_set_t &other) { process (hb_bitwise_xor, other); }
|
||||
|
||||
bool next (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
// TODO: this should be merged with prev() as both implementations
|
||||
// are very similar.
|
||||
if (unlikely (*codepoint == INVALID)) {
|
||||
*codepoint = get_min ();
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
|
||||
const auto* page_map_array = page_map.arrayZ;
|
||||
unsigned int major = get_major (*codepoint);
|
||||
unsigned int i = last_page_lookup;
|
||||
|
||||
if (unlikely (i >= page_map.length || page_map_array[i].major != major))
|
||||
{
|
||||
page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i >= page_map.length) {
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const auto* pages_array = pages.arrayZ;
|
||||
const page_map_t ¤t = page_map_array[i];
|
||||
if (likely (current.major == major))
|
||||
{
|
||||
if (pages_array[current.index].next (codepoint))
|
||||
{
|
||||
*codepoint += current.major * page_t::PAGE_BITS;
|
||||
last_page_lookup = i;
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
for (; i < page_map.length; i++)
|
||||
{
|
||||
const page_map_t ¤t = page_map.arrayZ[i];
|
||||
hb_codepoint_t m = pages_array[current.index].get_min ();
|
||||
if (m != INVALID)
|
||||
{
|
||||
*codepoint = current.major * page_t::PAGE_BITS + m;
|
||||
last_page_lookup = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
last_page_lookup = 0;
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
bool previous (hb_codepoint_t *codepoint) const
|
||||
{
|
||||
if (unlikely (*codepoint == INVALID)) {
|
||||
*codepoint = get_max ();
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
|
||||
page_map_t map = {get_major (*codepoint), 0};
|
||||
unsigned int i;
|
||||
page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i < page_map.length && page_map[i].major == map.major)
|
||||
{
|
||||
if (pages[page_map[i].index].previous (codepoint))
|
||||
{
|
||||
*codepoint += page_map[i].major * page_t::PAGE_BITS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i--;
|
||||
for (; (int) i >= 0; i--)
|
||||
{
|
||||
hb_codepoint_t m = pages[page_map[i].index].get_max ();
|
||||
if (m != INVALID)
|
||||
{
|
||||
*codepoint = page_map[i].major * page_t::PAGE_BITS + m;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
hb_codepoint_t i;
|
||||
|
||||
i = *last;
|
||||
if (!next (&i))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO Speed up. */
|
||||
*last = *first = i;
|
||||
while (next (&i) && i == *last + 1)
|
||||
(*last)++;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
|
||||
{
|
||||
hb_codepoint_t i;
|
||||
|
||||
i = *first;
|
||||
if (!previous (&i))
|
||||
{
|
||||
*last = *first = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO Speed up. */
|
||||
*last = *first = i;
|
||||
while (previous (&i) && i == *first - 1)
|
||||
(*first)--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has_population () const { return population != UINT_MAX; }
|
||||
unsigned int get_population () const
|
||||
{
|
||||
if (has_population ())
|
||||
return population;
|
||||
|
||||
unsigned int pop = 0;
|
||||
unsigned int count = pages.length;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
pop += pages[i].get_population ();
|
||||
|
||||
population = pop;
|
||||
return pop;
|
||||
}
|
||||
hb_codepoint_t get_min () const
|
||||
{
|
||||
unsigned count = pages.length;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
const auto& map = page_map[i];
|
||||
const auto& page = pages[map.index];
|
||||
|
||||
if (!page.is_empty ())
|
||||
return map.major * page_t::PAGE_BITS + page.get_min ();
|
||||
}
|
||||
return INVALID;
|
||||
}
|
||||
hb_codepoint_t get_max () const
|
||||
{
|
||||
unsigned count = pages.length;
|
||||
for (signed i = count - 1; i >= 0; i--)
|
||||
{
|
||||
const auto& map = page_map[(unsigned) i];
|
||||
const auto& page = pages[map.index];
|
||||
|
||||
if (!page.is_empty ())
|
||||
return map.major * page_t::PAGE_BITS + page.get_max ();
|
||||
}
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
static constexpr hb_codepoint_t INVALID = page_t::INVALID;
|
||||
|
||||
/*
|
||||
* Iterator implementation.
|
||||
*/
|
||||
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
|
||||
{
|
||||
static constexpr bool is_sorted_iterator = true;
|
||||
iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t),
|
||||
bool init = true) : s (&s_), v (INVALID), l(0)
|
||||
{
|
||||
if (init)
|
||||
{
|
||||
l = s->get_population () + 1;
|
||||
__next__ ();
|
||||
}
|
||||
}
|
||||
|
||||
typedef hb_codepoint_t __item_t__;
|
||||
hb_codepoint_t __item__ () const { return v; }
|
||||
bool __more__ () const { return v != INVALID; }
|
||||
void __next__ () { s->next (&v); if (l) l--; }
|
||||
void __prev__ () { s->previous (&v); }
|
||||
unsigned __len__ () const { return l; }
|
||||
iter_t end () const { return iter_t (*s, false); }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return s != o.s || v != o.v; }
|
||||
|
||||
protected:
|
||||
const hb_bit_set_t *s;
|
||||
hb_codepoint_t v;
|
||||
unsigned l;
|
||||
};
|
||||
iter_t iter () const { return iter_t (*this); }
|
||||
operator iter_t () const { return iter (); }
|
||||
|
||||
protected:
|
||||
|
||||
page_t *page_for (hb_codepoint_t g, bool insert = false)
|
||||
{
|
||||
page_map_t map = {get_major (g), pages.length};
|
||||
unsigned int i;
|
||||
if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST))
|
||||
{
|
||||
if (!insert)
|
||||
return nullptr;
|
||||
|
||||
if (unlikely (!resize (pages.length + 1)))
|
||||
return nullptr;
|
||||
|
||||
pages[map.index].init0 ();
|
||||
memmove (page_map + i + 1,
|
||||
page_map + i,
|
||||
(page_map.length - 1 - i) * page_map.item_size);
|
||||
page_map[i] = map;
|
||||
}
|
||||
return &pages[page_map[i].index];
|
||||
}
|
||||
const page_t *page_for (hb_codepoint_t g) const
|
||||
{
|
||||
page_map_t key = {get_major (g)};
|
||||
const page_map_t *found = page_map.bsearch (key);
|
||||
if (found)
|
||||
return &pages[found->index];
|
||||
return nullptr;
|
||||
}
|
||||
page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
|
||||
const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
|
||||
unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
|
||||
hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_BIT_SET_HH */
|
||||
|
|
@ -88,7 +88,7 @@ struct hb_blob_ptr_t
|
|||
const T * get () const { return b->as<T> (); }
|
||||
hb_blob_t * get_blob () const { return b.get_raw (); }
|
||||
unsigned int get_length () const { return b.get ()->length; }
|
||||
void destroy () { hb_blob_destroy (b.get ()); b = nullptr; }
|
||||
void destroy () { hb_blob_destroy (b.get_raw ()); b = nullptr; }
|
||||
|
||||
private:
|
||||
hb_nonnull_ptr_t<hb_blob_t> b;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -96,14 +96,15 @@ hb_segment_properties_hash (const hb_segment_properties_t *p)
|
|||
* As an optimization, both info and out_info may point to the
|
||||
* same piece of memory, which is owned by info. This remains the
|
||||
* case as long as out_len doesn't exceed i at any time.
|
||||
* In that case, swap_buffers() is no-op and the glyph operations operate
|
||||
* mostly in-place.
|
||||
* In that case, swap_buffers() is mostly no-op and the glyph operations
|
||||
* operate mostly in-place.
|
||||
*
|
||||
* As soon as out_info gets longer than info, out_info is moved over
|
||||
* to an alternate buffer (which we reuse the pos buffer for!), and its
|
||||
* to an alternate buffer (which we reuse the pos buffer for), and its
|
||||
* current contents (out_len entries) are copied to the new place.
|
||||
*
|
||||
* This should all remain transparent to the user. swap_buffers() then
|
||||
* switches info and out_info.
|
||||
* switches info over to out_info and does housekeeping.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -223,6 +224,7 @@ hb_buffer_t::reset ()
|
|||
flags = HB_BUFFER_FLAG_DEFAULT;
|
||||
replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
|
||||
invisible = 0;
|
||||
not_found = 0;
|
||||
|
||||
clear ();
|
||||
}
|
||||
|
|
@ -281,22 +283,13 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
hb_buffer_t::remove_output ()
|
||||
{
|
||||
have_output = false;
|
||||
have_positions = false;
|
||||
|
||||
out_len = 0;
|
||||
out_info = info;
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::clear_output ()
|
||||
{
|
||||
have_output = true;
|
||||
have_positions = false;
|
||||
|
||||
idx = 0;
|
||||
out_len = 0;
|
||||
out_info = info;
|
||||
}
|
||||
|
|
@ -316,29 +309,23 @@ hb_buffer_t::clear_positions ()
|
|||
void
|
||||
hb_buffer_t::swap_buffers ()
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
assert (have_output);
|
||||
|
||||
assert (idx <= len);
|
||||
if (unlikely (!next_glyphs (len - idx))) return;
|
||||
|
||||
assert (have_output);
|
||||
have_output = false;
|
||||
if (unlikely (!successful || !next_glyphs (len - idx)))
|
||||
goto reset;
|
||||
|
||||
if (out_info != info)
|
||||
{
|
||||
hb_glyph_info_t *tmp;
|
||||
tmp = info;
|
||||
pos = (hb_glyph_position_t *) info;
|
||||
info = out_info;
|
||||
out_info = tmp;
|
||||
|
||||
pos = (hb_glyph_position_t *) out_info;
|
||||
}
|
||||
|
||||
unsigned int tmp;
|
||||
tmp = len;
|
||||
len = out_len;
|
||||
out_len = tmp;
|
||||
|
||||
reset:
|
||||
have_output = false;
|
||||
out_len = 0;
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
|
|
@ -373,12 +360,11 @@ hb_buffer_t::move_to (unsigned int i)
|
|||
/* This will blow in our face if memory allocation fails later
|
||||
* in this same lookup...
|
||||
*
|
||||
* We used to shift with extra 32 items, instead of the 0 below.
|
||||
* We used to shift with extra 32 items.
|
||||
* But that would leave empty slots in the buffer in case of allocation
|
||||
* failures. Setting to zero for now to avoid other problems (see
|
||||
* comments in shift_forward(). This can cause O(N^2) behavior more
|
||||
* severely than adding 32 empty slots can... */
|
||||
if (unlikely (idx < count && !shift_forward (count + 0))) return false;
|
||||
* failures. See comments in shift_forward(). This can cause O(N^2)
|
||||
* behavior more severely than adding 32 empty slots can... */
|
||||
if (unlikely (idx < count && !shift_forward (count - idx))) return false;
|
||||
|
||||
assert (idx >= count);
|
||||
|
||||
|
|
@ -409,52 +395,6 @@ hb_buffer_t::set_masks (hb_mask_t value,
|
|||
info[i].mask = (info[i].mask & not_mask) | value;
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::reverse_range (unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
if (end - start < 2)
|
||||
return;
|
||||
|
||||
hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end);
|
||||
|
||||
if (have_positions) {
|
||||
hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::reverse ()
|
||||
{
|
||||
if (unlikely (!len))
|
||||
return;
|
||||
|
||||
reverse_range (0, len);
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::reverse_clusters ()
|
||||
{
|
||||
unsigned int i, start, count, last_cluster;
|
||||
|
||||
if (unlikely (!len))
|
||||
return;
|
||||
|
||||
reverse ();
|
||||
|
||||
count = len;
|
||||
start = 0;
|
||||
last_cluster = info[0].cluster;
|
||||
for (i = 1; i < count; i++) {
|
||||
if (last_cluster != info[i].cluster) {
|
||||
reverse_range (start, i);
|
||||
start = i;
|
||||
last_cluster = info[i].cluster;
|
||||
}
|
||||
}
|
||||
reverse_range (start, i);
|
||||
}
|
||||
|
||||
void
|
||||
hb_buffer_t::merge_clusters_impl (unsigned int start,
|
||||
unsigned int end)
|
||||
|
|
@ -557,7 +497,7 @@ void
|
|||
hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
|
||||
{
|
||||
unsigned int cluster = UINT_MAX;
|
||||
cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster);
|
||||
cluster = _infos_find_min_cluster (info, start, end, cluster);
|
||||
_unsafe_to_break_set_mask (info, start, end, cluster);
|
||||
}
|
||||
void
|
||||
|
|
@ -573,8 +513,9 @@ hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int en
|
|||
assert (idx <= end);
|
||||
|
||||
unsigned int cluster = UINT_MAX;
|
||||
cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster);
|
||||
cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster);
|
||||
cluster = _infos_find_min_cluster (out_info, start, out_len, cluster);
|
||||
cluster = _infos_find_min_cluster (info, idx, end, cluster);
|
||||
|
||||
_unsafe_to_break_set_mask (out_info, start, out_len, cluster);
|
||||
_unsafe_to_break_set_mask (info, idx, end, cluster);
|
||||
}
|
||||
|
|
@ -623,6 +564,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
|
|||
HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
|
||||
HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
|
||||
0, /* invisible */
|
||||
0, /* not_found */
|
||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT,
|
||||
HB_BUFFER_MAX_LEN_DEFAULT,
|
||||
HB_BUFFER_MAX_OPS_DEFAULT,
|
||||
|
|
@ -630,7 +572,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
|
|||
HB_BUFFER_CONTENT_TYPE_INVALID,
|
||||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||
false, /* successful */
|
||||
true, /* have_output */
|
||||
false, /* have_output */
|
||||
true /* have_positions */
|
||||
|
||||
/* Zero is good enough for everything else. */
|
||||
|
|
@ -1173,6 +1115,46 @@ hb_buffer_get_invisible_glyph (hb_buffer_t *buffer)
|
|||
return buffer->invisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_buffer_set_not_found_glyph:
|
||||
* @buffer: An #hb_buffer_t
|
||||
* @not_found: the not-found #hb_codepoint_t
|
||||
*
|
||||
* Sets the #hb_codepoint_t that replaces characters not found in
|
||||
* the font during shaping.
|
||||
*
|
||||
* The not-found glyph defaults to zero, sometimes knows as the
|
||||
* ".notdef" glyph. This API allows for differentiating the two.
|
||||
*
|
||||
* Since: 3.1.0
|
||||
**/
|
||||
void
|
||||
hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
|
||||
hb_codepoint_t not_found)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (buffer)))
|
||||
return;
|
||||
|
||||
buffer->not_found = not_found;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_buffer_get_not_found_glyph:
|
||||
* @buffer: An #hb_buffer_t
|
||||
*
|
||||
* See hb_buffer_set_not_found_glyph().
|
||||
*
|
||||
* Return value:
|
||||
* The @buffer not-found #hb_codepoint_t
|
||||
*
|
||||
* Since: 3.1.0
|
||||
**/
|
||||
hb_codepoint_t
|
||||
hb_buffer_get_not_found_glyph (hb_buffer_t *buffer)
|
||||
{
|
||||
return buffer->not_found;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_buffer_reset:
|
||||
|
|
@ -1770,6 +1752,28 @@ hb_buffer_append (hb_buffer_t *buffer,
|
|||
memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0]));
|
||||
if (buffer->have_positions)
|
||||
memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0]));
|
||||
|
||||
if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE)
|
||||
{
|
||||
/* See similar logic in add_utf. */
|
||||
|
||||
/* pre-context */
|
||||
if (!orig_len && start + source->context_len[0] > 0)
|
||||
{
|
||||
buffer->clear_context (0);
|
||||
while (start > 0 && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
|
||||
buffer->context[0][buffer->context_len[0]++] = source->info[--start].codepoint;
|
||||
for (auto i = 0u; i < source->context_len[0] && buffer->context_len[0] < buffer->CONTEXT_LENGTH; i++)
|
||||
buffer->context[0][buffer->context_len[0]++] = source->context[0][i];
|
||||
}
|
||||
|
||||
/* post-context */
|
||||
buffer->clear_context (1);
|
||||
while (end < source->len && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
|
||||
buffer->context[1][buffer->context_len[1]++] = source->info[end++].codepoint;
|
||||
for (auto i = 0u; i < source->context_len[1] && buffer->context_len[1] < buffer->CONTEXT_LENGTH; i++)
|
||||
buffer->context[1][buffer->context_len[1]++] = source->context[1][i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -383,6 +383,13 @@ hb_buffer_set_invisible_glyph (hb_buffer_t *buffer,
|
|||
HB_EXTERN hb_codepoint_t
|
||||
hb_buffer_get_invisible_glyph (hb_buffer_t *buffer);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
|
||||
hb_codepoint_t not_found);
|
||||
|
||||
HB_EXTERN hb_codepoint_t
|
||||
hb_buffer_get_not_found_glyph (hb_buffer_t *buffer);
|
||||
|
||||
|
||||
HB_EXTERN void
|
||||
hb_buffer_reset (hb_buffer_t *buffer);
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ struct hb_buffer_t
|
|||
hb_buffer_cluster_level_t cluster_level;
|
||||
hb_codepoint_t replacement; /* U+FFFD or something else. */
|
||||
hb_codepoint_t invisible; /* 0 or something else. */
|
||||
hb_codepoint_t not_found; /* 0 or something else. */
|
||||
hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
|
||||
unsigned int max_len; /* Maximum allowed len. */
|
||||
int max_ops; /* Maximum allowed operations. */
|
||||
|
|
@ -107,7 +108,7 @@ struct hb_buffer_t
|
|||
|
||||
unsigned int idx; /* Cursor into ->info and ->pos arrays */
|
||||
unsigned int len; /* Length of ->info and ->pos arrays */
|
||||
unsigned int out_len; /* Length of ->out array if have_output */
|
||||
unsigned int out_len; /* Length of ->out_info array if have_output */
|
||||
|
||||
unsigned int allocated; /* Length of allocated arrays */
|
||||
hb_glyph_info_t *info;
|
||||
|
|
@ -189,13 +190,10 @@ struct hb_buffer_t
|
|||
hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; }
|
||||
hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
|
||||
|
||||
HB_NODISCARD bool has_separate_output () const { return info != out_info; }
|
||||
|
||||
|
||||
HB_INTERNAL void reset ();
|
||||
HB_INTERNAL void clear ();
|
||||
|
||||
unsigned int backtrack_len () const { return have_output? out_len : idx; }
|
||||
unsigned int backtrack_len () const { return have_output ? out_len : idx; }
|
||||
unsigned int lookahead_len () const { return len - idx; }
|
||||
unsigned int next_serial () { return serial++; }
|
||||
|
||||
|
|
@ -203,13 +201,58 @@ struct hb_buffer_t
|
|||
unsigned int cluster);
|
||||
HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
|
||||
|
||||
HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
|
||||
HB_INTERNAL void reverse ();
|
||||
HB_INTERNAL void reverse_clusters ();
|
||||
void reverse_range (unsigned start, unsigned end)
|
||||
{
|
||||
hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end);
|
||||
if (have_positions)
|
||||
hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end);
|
||||
}
|
||||
void reverse () { reverse_range (0, len); }
|
||||
|
||||
template <typename FuncType>
|
||||
void reverse_groups (const FuncType& group,
|
||||
bool merge_clusters = false)
|
||||
{
|
||||
if (unlikely (!len))
|
||||
return;
|
||||
|
||||
unsigned start = 0;
|
||||
unsigned i;
|
||||
for (i = 1; i < len; i++)
|
||||
{
|
||||
if (!group (info[i - 1], info[i]))
|
||||
{
|
||||
if (merge_clusters)
|
||||
this->merge_clusters (start, i);
|
||||
reverse_range (start, i);
|
||||
start = i;
|
||||
}
|
||||
}
|
||||
if (merge_clusters)
|
||||
this->merge_clusters (start, i);
|
||||
reverse_range (start, i);
|
||||
|
||||
reverse ();
|
||||
}
|
||||
|
||||
template <typename FuncType>
|
||||
unsigned group_end (unsigned start, const FuncType& group) const
|
||||
{
|
||||
while (++start < len && group (info[start - 1], info[start]))
|
||||
;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
static bool _cluster_group_func (const hb_glyph_info_t& a,
|
||||
const hb_glyph_info_t& b)
|
||||
{ return a.cluster == b.cluster; }
|
||||
|
||||
void reverse_clusters () { reverse_groups (_cluster_group_func); }
|
||||
|
||||
HB_INTERNAL void guess_segment_properties ();
|
||||
|
||||
HB_INTERNAL void swap_buffers ();
|
||||
HB_INTERNAL void remove_output ();
|
||||
HB_INTERNAL void clear_output ();
|
||||
HB_INTERNAL void clear_positions ();
|
||||
|
||||
|
|
@ -431,10 +474,10 @@ struct hb_buffer_t
|
|||
inf.cluster = cluster;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
_unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
|
||||
unsigned int start, unsigned int end,
|
||||
unsigned int cluster) const
|
||||
static unsigned
|
||||
_infos_find_min_cluster (const hb_glyph_info_t *infos,
|
||||
unsigned start, unsigned end,
|
||||
unsigned cluster)
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
cluster = hb_min (cluster, infos[i].cluster);
|
||||
|
|
@ -453,36 +496,24 @@ struct hb_buffer_t
|
|||
}
|
||||
}
|
||||
|
||||
void unsafe_to_break_all () { unsafe_to_break_impl (0, len); }
|
||||
void safe_to_break_all ()
|
||||
void clear_glyph_flags (hb_mask_t mask = 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
|
||||
info[i].mask = (info[i].mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED);
|
||||
}
|
||||
};
|
||||
DECLARE_NULL_INSTANCE (hb_buffer_t);
|
||||
|
||||
|
||||
/* Loop over clusters. Duplicated in foreach_syllable(). */
|
||||
#define foreach_cluster(buffer, start, end) \
|
||||
#define foreach_group(buffer, start, end, group_func) \
|
||||
for (unsigned int \
|
||||
_count = buffer->len, \
|
||||
start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
|
||||
start = 0, end = _count ? buffer->group_end (0, group_func) : 0; \
|
||||
start < _count; \
|
||||
start = end, end = _next_cluster (buffer, start))
|
||||
start = end, end = buffer->group_end (start, group_func))
|
||||
|
||||
static inline unsigned int
|
||||
_next_cluster (hb_buffer_t *buffer, unsigned int start)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
|
||||
unsigned int cluster = info[start].cluster;
|
||||
while (++start < count && cluster == info[start].cluster)
|
||||
;
|
||||
|
||||
return start;
|
||||
}
|
||||
#define foreach_cluster(buffer, start, end) \
|
||||
foreach_group (buffer, start, end, hb_buffer_t::_cluster_group_func)
|
||||
|
||||
|
||||
#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
|
||||
|
|
|
|||
|
|
@ -136,8 +136,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
|
|||
if (unlikely (!scalars.resize (region_count)))
|
||||
set_error ();
|
||||
else
|
||||
varStore->varStore.get_scalars (get_ivs (), coords, num_coords,
|
||||
&scalars[0], region_count);
|
||||
varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
|
||||
&scalars[0], region_count);
|
||||
}
|
||||
seen_blend = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,8 +280,7 @@ struct hb_language_item_t {
|
|||
|
||||
static hb_atomic_ptr_t <hb_language_item_t> langs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void
|
||||
static inline void
|
||||
free_langs ()
|
||||
{
|
||||
retry:
|
||||
|
|
@ -296,7 +295,6 @@ retry:
|
|||
first_lang = next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_language_item_t *
|
||||
lang_find_or_insert (const char *key)
|
||||
|
|
@ -327,10 +325,8 @@ retry:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
if (!first_lang)
|
||||
atexit (free_langs); /* First person registers atexit() callback. */
|
||||
#endif
|
||||
hb_atexit (free_langs); /* First person registers atexit() callback. */
|
||||
|
||||
return lang;
|
||||
}
|
||||
|
|
@ -599,6 +595,9 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
|||
case HB_SCRIPT_CHORASMIAN:
|
||||
case HB_SCRIPT_YEZIDI:
|
||||
|
||||
/* Unicode-14.0 additions */
|
||||
case HB_SCRIPT_OLD_UYGHUR:
|
||||
|
||||
return HB_DIRECTION_RTL;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -476,6 +476,11 @@ hb_language_get_default (void);
|
|||
* @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7
|
||||
* @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7
|
||||
* @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7
|
||||
* @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0
|
||||
* @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0
|
||||
* @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0
|
||||
* @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
|
||||
* @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
|
||||
* @HB_SCRIPT_INVALID: No script set
|
||||
*
|
||||
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
|
||||
|
|
@ -683,6 +688,15 @@ typedef enum
|
|||
HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/
|
||||
HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/
|
||||
|
||||
/*
|
||||
* Since 3.0.0
|
||||
*/
|
||||
HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/
|
||||
HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/
|
||||
HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/
|
||||
HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/
|
||||
HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/
|
||||
|
||||
/* No script set. */
|
||||
HB_SCRIPT_INVALID = HB_TAG_NONE,
|
||||
|
||||
|
|
|
|||
|
|
@ -86,8 +86,11 @@
|
|||
#define HB_NO_LEGACY
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_OVERRIDE_H
|
||||
#include "config-override.h"
|
||||
#if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H)
|
||||
#ifndef HB_CONFIG_OVERRIDE_H
|
||||
#define HB_CONFIG_OVERRIDE_H "config-override.h"
|
||||
#endif
|
||||
#include HB_CONFIG_OVERRIDE_H
|
||||
#endif
|
||||
|
||||
/* Closure of options. */
|
||||
|
|
|
|||
|
|
@ -332,6 +332,44 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (font->coords)
|
||||
{
|
||||
CFMutableDictionaryRef variations =
|
||||
CFDictionaryCreateMutable (kCFAllocatorDefault,
|
||||
font->num_coords,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
for (unsigned i = 0; i < font->num_coords; i++)
|
||||
{
|
||||
if (font->coords[i] == 0.) continue;
|
||||
|
||||
hb_ot_var_axis_info_t info;
|
||||
unsigned int c = 1;
|
||||
hb_ot_var_get_axis_infos (font->face, i, &c, &info);
|
||||
CFDictionarySetValue (variations,
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag),
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &font->design_coords[i])
|
||||
);
|
||||
}
|
||||
|
||||
CFDictionaryRef attributes =
|
||||
CFDictionaryCreate (kCFAllocatorDefault,
|
||||
(const void **) &kCTFontVariationAttribute,
|
||||
(const void **) &variations,
|
||||
1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
CTFontDescriptorRef varDesc = CTFontDescriptorCreateWithAttributes (attributes);
|
||||
CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0, nullptr, varDesc);
|
||||
|
||||
CFRelease (ct_font);
|
||||
CFRelease (attributes);
|
||||
CFRelease (variations);
|
||||
ct_font = new_ct_font;
|
||||
}
|
||||
|
||||
return (hb_coretext_font_data_t *) ct_font;
|
||||
}
|
||||
|
||||
|
|
@ -1175,7 +1213,7 @@ resize_and_retry:
|
|||
}
|
||||
}
|
||||
|
||||
buffer->unsafe_to_break_all ();
|
||||
buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK);
|
||||
|
||||
#undef FAIL
|
||||
|
||||
|
|
|
|||
|
|
@ -302,16 +302,16 @@ struct hb_auto_trace_t
|
|||
{
|
||||
if (unlikely (returned)) {
|
||||
fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n");
|
||||
return hb_forward<T> (v);
|
||||
return std::forward<T> (v);
|
||||
}
|
||||
|
||||
_hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
|
||||
"return %s (line %d)",
|
||||
hb_printer_t<decltype (v)>().print (v), line);
|
||||
hb_printer_t<hb_decay<decltype (v)>>().print (v), line);
|
||||
if (plevel) --*plevel;
|
||||
plevel = nullptr;
|
||||
returned = true;
|
||||
return hb_forward<T> (v);
|
||||
return std::forward<T> (v);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -333,7 +333,7 @@ struct hb_auto_trace_t<0, ret_t>
|
|||
template <typename T>
|
||||
T ret (T&& v,
|
||||
const char *func HB_UNUSED = nullptr,
|
||||
unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
|
||||
unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
|
||||
};
|
||||
|
||||
/* For disabled tracing; optimize out everything.
|
||||
|
|
@ -343,7 +343,7 @@ struct hb_no_trace_t {
|
|||
template <typename T>
|
||||
T ret (T&& v,
|
||||
const char *func HB_UNUSED = nullptr,
|
||||
unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
|
||||
unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
|
||||
};
|
||||
|
||||
#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
|
||||
|
|
|
|||
|
|
@ -107,9 +107,6 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
|
|||
hb_font_get_glyph_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN HB_DEPRECATED void
|
||||
hb_set_invert (hb_set_t *set);
|
||||
|
||||
/**
|
||||
* hb_unicode_eastasian_width_func_t:
|
||||
* @ufuncs: A Unicode-functions structure
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "hb-directwrite.h"
|
||||
|
||||
#include "hb-ms-feature-ranges.hh"
|
||||
|
||||
/**
|
||||
* SECTION:hb-directwrite
|
||||
|
|
@ -510,44 +511,6 @@ protected:
|
|||
* shaper
|
||||
*/
|
||||
|
||||
struct active_feature_t {
|
||||
DWRITE_FONT_FEATURE fea;
|
||||
unsigned int order;
|
||||
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb) {
|
||||
const active_feature_t *a = (const active_feature_t *) pa;
|
||||
const active_feature_t *b = (const active_feature_t *) pb;
|
||||
return a->fea.nameTag < b->fea.nameTag ? -1 : a->fea.nameTag > b->fea.nameTag ? 1 :
|
||||
a->order < b->order ? -1 : a->order > b->order ? 1 :
|
||||
a->fea.parameter < b->fea.parameter ? -1 : a->fea.parameter > b->fea.parameter ? 1 :
|
||||
0;
|
||||
}
|
||||
bool operator== (const active_feature_t *f)
|
||||
{ return cmp (this, f) == 0; }
|
||||
};
|
||||
|
||||
struct feature_event_t {
|
||||
unsigned int index;
|
||||
bool start;
|
||||
active_feature_t feature;
|
||||
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb)
|
||||
{
|
||||
const feature_event_t *a = (const feature_event_t *) pa;
|
||||
const feature_event_t *b = (const feature_event_t *) pb;
|
||||
return a->index < b->index ? -1 : a->index > b->index ? 1 :
|
||||
a->start < b->start ? -1 : a->start > b->start ? 1 :
|
||||
active_feature_t::cmp (&a->feature, &b->feature);
|
||||
}
|
||||
};
|
||||
|
||||
struct range_record_t {
|
||||
DWRITE_TYPOGRAPHIC_FEATURES features;
|
||||
unsigned int index_first; /* == start */
|
||||
unsigned int index_last; /* == end - 1 */
|
||||
};
|
||||
|
||||
|
||||
hb_bool_t
|
||||
_hb_directwrite_shape (hb_shape_plan_t *shape_plan,
|
||||
hb_font_t *font,
|
||||
|
|
@ -644,149 +607,24 @@ _hb_directwrite_shape (hb_shape_plan_t *shape_plan,
|
|||
/*
|
||||
* Set up features.
|
||||
*/
|
||||
hb_vector_t<DWRITE_FONT_FEATURE> feature_records;
|
||||
hb_vector_t<range_record_t> range_records;
|
||||
if (num_features)
|
||||
{
|
||||
/* Sort features by start/end events. */
|
||||
hb_vector_t<feature_event_t> feature_events;
|
||||
for (unsigned int i = 0; i < num_features; i++)
|
||||
{
|
||||
active_feature_t feature;
|
||||
feature.fea.nameTag = (DWRITE_FONT_FEATURE_TAG) hb_uint32_swap (features[i].tag);
|
||||
feature.fea.parameter = features[i].value;
|
||||
feature.order = i;
|
||||
|
||||
feature_event_t *event;
|
||||
|
||||
event = feature_events.push ();
|
||||
event->index = features[i].start;
|
||||
event->start = true;
|
||||
event->feature = feature;
|
||||
|
||||
event = feature_events.push ();
|
||||
event->index = features[i].end;
|
||||
event->start = false;
|
||||
event->feature = feature;
|
||||
}
|
||||
feature_events.qsort ();
|
||||
/* Add a strategic final event. */
|
||||
{
|
||||
active_feature_t feature;
|
||||
feature.fea.nameTag = (DWRITE_FONT_FEATURE_TAG) 0;
|
||||
feature.fea.parameter = 0;
|
||||
feature.order = num_features + 1;
|
||||
|
||||
feature_event_t *event = feature_events.push ();
|
||||
event->index = 0; /* This value does magic. */
|
||||
event->start = false;
|
||||
event->feature = feature;
|
||||
}
|
||||
|
||||
/* Scan events and save features for each range. */
|
||||
hb_vector_t<active_feature_t> active_features;
|
||||
unsigned int last_index = 0;
|
||||
for (unsigned int i = 0; i < feature_events.length; i++)
|
||||
{
|
||||
feature_event_t *event = &feature_events[i];
|
||||
|
||||
if (event->index != last_index)
|
||||
{
|
||||
/* Save a snapshot of active features and the range. */
|
||||
range_record_t *range = range_records.push ();
|
||||
|
||||
unsigned int offset = feature_records.length;
|
||||
|
||||
active_features.qsort ();
|
||||
for (unsigned int j = 0; j < active_features.length; j++)
|
||||
{
|
||||
if (!j || active_features[j].fea.nameTag != feature_records[feature_records.length - 1].nameTag)
|
||||
{
|
||||
feature_records.push (active_features[j].fea);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Overrides value for existing feature. */
|
||||
feature_records[feature_records.length - 1].parameter = active_features[j].fea.parameter;
|
||||
}
|
||||
}
|
||||
|
||||
/* Will convert to pointer after all is ready, since feature_records.array
|
||||
* may move as we grow it. */
|
||||
range->features.features = reinterpret_cast<DWRITE_FONT_FEATURE *> (offset);
|
||||
range->features.featureCount = feature_records.length - offset;
|
||||
range->index_first = last_index;
|
||||
range->index_last = event->index - 1;
|
||||
|
||||
last_index = event->index;
|
||||
}
|
||||
|
||||
if (event->start)
|
||||
{
|
||||
active_features.push (event->feature);
|
||||
}
|
||||
else
|
||||
{
|
||||
active_feature_t *feature = active_features.find (&event->feature);
|
||||
if (feature)
|
||||
active_features.remove (feature - active_features.arrayZ);
|
||||
}
|
||||
}
|
||||
|
||||
if (!range_records.length) /* No active feature found. */
|
||||
num_features = 0;
|
||||
|
||||
/* Fixup the pointers. */
|
||||
for (unsigned int i = 0; i < range_records.length; i++)
|
||||
{
|
||||
range_record_t *range = &range_records[i];
|
||||
range->features.features = (DWRITE_FONT_FEATURE *) feature_records + reinterpret_cast<uintptr_t> (range->features.features);
|
||||
}
|
||||
}
|
||||
|
||||
hb_vector_t<DWRITE_TYPOGRAPHIC_FEATURES *> range_features;
|
||||
static_assert ((sizeof (DWRITE_TYPOGRAPHIC_FEATURES) == sizeof (hb_ms_features_t)), "");
|
||||
static_assert ((sizeof (DWRITE_FONT_FEATURE) == sizeof (hb_ms_feature_t)), "");
|
||||
hb_vector_t<hb_ms_features_t *> range_features;
|
||||
hb_vector_t<uint32_t> range_char_counts;
|
||||
if (num_features)
|
||||
{
|
||||
range_features.shrink (0);
|
||||
range_char_counts.shrink (0);
|
||||
|
||||
range_record_t *last_range = &range_records[0];
|
||||
for (unsigned int i = 0; i < textLength; i++)
|
||||
{
|
||||
range_record_t *range = last_range;
|
||||
while (log_clusters[i] < range->index_first)
|
||||
range--;
|
||||
while (log_clusters[i] > range->index_last)
|
||||
range++;
|
||||
if (!range_features.length ||
|
||||
&range->features != range_features[range_features.length - 1])
|
||||
{
|
||||
auto **typoFeatures = range_features.push ();
|
||||
auto *c = range_char_counts.push ();
|
||||
if (unlikely (!typoFeatures || !c))
|
||||
{
|
||||
range_features.shrink (0);
|
||||
range_char_counts.shrink (0);
|
||||
break;
|
||||
}
|
||||
*typoFeatures = &range->features;
|
||||
*c = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
range_char_counts[range_char_counts.length - 1]++;
|
||||
}
|
||||
|
||||
last_range = range;
|
||||
}
|
||||
hb_vector_t<hb_ms_feature_t> feature_records;
|
||||
hb_vector_t<hb_ms_range_record_t> range_records;
|
||||
if (hb_ms_setup_features (features, num_features, feature_records, range_records))
|
||||
hb_ms_make_feature_ranges (feature_records,
|
||||
range_records,
|
||||
0,
|
||||
chars_len,
|
||||
log_clusters,
|
||||
range_features,
|
||||
range_char_counts);
|
||||
}
|
||||
|
||||
const auto **dwFeatures = (const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ;
|
||||
auto featureRanges = range_features.length;
|
||||
const auto *featureRangeLengths = range_char_counts.arrayZ;
|
||||
//
|
||||
|
||||
uint16_t* clusterMap;
|
||||
clusterMap = new uint16_t[textLength];
|
||||
DWRITE_SHAPING_TEXT_PROPERTIES* textProperties;
|
||||
|
|
@ -797,11 +635,23 @@ retry_getglyphs:
|
|||
DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties;
|
||||
glyphProperties = new DWRITE_SHAPING_GLYPH_PROPERTIES[maxGlyphCount];
|
||||
|
||||
hr = analyzer->GetGlyphs (textString, textLength, fontFace, false,
|
||||
isRightToLeft, &runHead->mScript, localeName,
|
||||
nullptr, dwFeatures, featureRangeLengths, featureRanges,
|
||||
maxGlyphCount, clusterMap, textProperties,
|
||||
glyphIndices, glyphProperties, &glyphCount);
|
||||
hr = analyzer->GetGlyphs (textString,
|
||||
chars_len,
|
||||
fontFace,
|
||||
false,
|
||||
isRightToLeft,
|
||||
&runHead->mScript,
|
||||
localeName,
|
||||
nullptr,
|
||||
(const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
|
||||
range_char_counts.arrayZ,
|
||||
range_features.length,
|
||||
maxGlyphCount,
|
||||
clusterMap,
|
||||
textProperties,
|
||||
glyphIndices,
|
||||
glyphProperties,
|
||||
&glyphCount);
|
||||
|
||||
if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
|
||||
{
|
||||
|
|
@ -837,12 +687,24 @@ retry_getglyphs:
|
|||
double x_mult = (double) font->x_scale / fontEmSize;
|
||||
double y_mult = (double) font->y_scale / fontEmSize;
|
||||
|
||||
hr = analyzer->GetGlyphPlacements (textString, clusterMap, textProperties,
|
||||
textLength, glyphIndices, glyphProperties,
|
||||
glyphCount, fontFace, fontEmSize,
|
||||
false, isRightToLeft, &runHead->mScript, localeName,
|
||||
dwFeatures, featureRangeLengths, featureRanges,
|
||||
glyphAdvances, glyphOffsets);
|
||||
hr = analyzer->GetGlyphPlacements (textString,
|
||||
clusterMap,
|
||||
textProperties,
|
||||
chars_len,
|
||||
glyphIndices,
|
||||
glyphProperties,
|
||||
glyphCount,
|
||||
fontFace,
|
||||
fontEmSize,
|
||||
false,
|
||||
isRightToLeft,
|
||||
&runHead->mScript,
|
||||
localeName,
|
||||
(const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ,
|
||||
range_char_counts.arrayZ,
|
||||
range_features.length,
|
||||
glyphAdvances,
|
||||
glyphOffsets);
|
||||
|
||||
if (FAILED (hr))
|
||||
FAIL ("Analyzer failed to get glyph placements.");
|
||||
|
|
@ -900,6 +762,8 @@ retry_getglyphs:
|
|||
|
||||
if (isRightToLeft) hb_buffer_reverse (buffer);
|
||||
|
||||
buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK);
|
||||
|
||||
delete [] clusterMap;
|
||||
delete [] glyphIndices;
|
||||
delete [] textProperties;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ struct hb_dispatch_context_t
|
|||
bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
|
||||
template <typename T, typename ...Ts>
|
||||
return_t dispatch (const T &obj, Ts&&... ds)
|
||||
{ return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); }
|
||||
{ return obj.dispatch (thiz (), std::forward<Ts> (ds)...); }
|
||||
static return_t no_dispatch_return_value () { return Context::default_return_value (); }
|
||||
static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
|
||||
unsigned debug_depth = 0;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "hb-open-file.hh"
|
||||
#include "hb-ot-face.hh"
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-map.hh"
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -623,22 +624,22 @@ hb_face_collect_variation_unicodes (hb_face_t *face,
|
|||
|
||||
struct hb_face_builder_data_t
|
||||
{
|
||||
struct table_entry_t
|
||||
{
|
||||
int cmp (hb_tag_t t) const
|
||||
{
|
||||
if (t < tag) return -1;
|
||||
if (t > tag) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
hb_tag_t tag;
|
||||
hb_blob_t *blob;
|
||||
};
|
||||
|
||||
hb_vector_t<table_entry_t> tables;
|
||||
hb_hashmap_t<hb_tag_t, hb_blob_t *> tables;
|
||||
};
|
||||
|
||||
static int compare_entries (const void* pa, const void* pb)
|
||||
{
|
||||
const auto& a = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pa;
|
||||
const auto& b = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pb;
|
||||
|
||||
/* Order by blob size first (smallest to largest) and then table tag */
|
||||
|
||||
if (a.second->length != b.second->length)
|
||||
return a.second->length < b.second->length ? -1 : +1;
|
||||
|
||||
return a.first < b.first ? -1 : a.first == b.first ? 0 : +1;
|
||||
}
|
||||
|
||||
static hb_face_builder_data_t *
|
||||
_hb_face_builder_data_create ()
|
||||
{
|
||||
|
|
@ -656,8 +657,8 @@ _hb_face_builder_data_destroy (void *user_data)
|
|||
{
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
|
||||
|
||||
for (unsigned int i = 0; i < data->tables.length; i++)
|
||||
hb_blob_destroy (data->tables[i].blob);
|
||||
for (hb_blob_t* b : data->tables.values())
|
||||
hb_blob_destroy (b);
|
||||
|
||||
data->tables.fini ();
|
||||
|
||||
|
|
@ -668,11 +669,11 @@ static hb_blob_t *
|
|||
_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
||||
{
|
||||
|
||||
unsigned int table_count = data->tables.length;
|
||||
unsigned int table_count = data->tables.get_population ();
|
||||
unsigned int face_length = table_count * 16 + 12;
|
||||
|
||||
for (unsigned int i = 0; i < table_count; i++)
|
||||
face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob));
|
||||
for (hb_blob_t* b : data->tables.values())
|
||||
face_length += hb_ceil_to_4 (hb_blob_get_length (b));
|
||||
|
||||
char *buf = (char *) hb_malloc (face_length);
|
||||
if (unlikely (!buf))
|
||||
|
|
@ -682,10 +683,21 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
|||
c.propagate_error (data->tables);
|
||||
OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
|
||||
|
||||
bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
|
||||
bool is_cff = (data->tables.has (HB_TAG ('C','F','F',' '))
|
||||
|| data->tables.has (HB_TAG ('C','F','F','2')));
|
||||
hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
|
||||
|
||||
bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ());
|
||||
// Sort the tags so that produced face is deterministic.
|
||||
hb_vector_t<hb_pair_t <hb_tag_t, hb_blob_t*>> sorted_entries;
|
||||
data->tables.iter () | hb_sink (sorted_entries);
|
||||
if (unlikely (sorted_entries.in_error ()))
|
||||
{
|
||||
hb_free (buf);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sorted_entries.qsort (compare_entries);
|
||||
bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter());
|
||||
|
||||
c.end_serialize ();
|
||||
|
||||
|
|
@ -706,11 +718,7 @@ _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
|
|||
if (!tag)
|
||||
return _hb_face_builder_data_reference_blob (data);
|
||||
|
||||
hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
|
||||
if (entry)
|
||||
return hb_blob_reference (entry->blob);
|
||||
|
||||
return nullptr;
|
||||
return hb_blob_reference (data->tables[tag]);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -750,17 +758,21 @@ hb_face_builder_create ()
|
|||
hb_bool_t
|
||||
hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
|
||||
{
|
||||
if (tag == HB_MAP_VALUE_INVALID)
|
||||
return false;
|
||||
|
||||
if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
|
||||
return false;
|
||||
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
|
||||
|
||||
hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
|
||||
if (unlikely (data->tables.in_error()))
|
||||
hb_blob_t* previous = data->tables.get (tag);
|
||||
if (!data->tables.set (tag, hb_blob_reference (blob)))
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
return false;
|
||||
}
|
||||
|
||||
entry->tag = tag;
|
||||
entry->blob = hb_blob_reference (blob);
|
||||
|
||||
hb_blob_destroy (previous);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
|||
if (HB_DIRECTION_IS_BACKWARD (direction))
|
||||
hb_buffer_reverse (buffer);
|
||||
|
||||
buffer->safe_to_break_all ();
|
||||
buffer->clear_glyph_flags ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2052,7 +2052,9 @@ hb_font_set_variations (hb_font_t *font,
|
|||
return;
|
||||
}
|
||||
|
||||
unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
auto axes = fvar.get_axes ();
|
||||
const unsigned coords_length = axes.length;
|
||||
|
||||
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
|
||||
|
|
@ -2064,17 +2066,16 @@ hb_font_set_variations (hb_font_t *font,
|
|||
return;
|
||||
}
|
||||
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
for (unsigned int i = 0; i < variations_length; i++)
|
||||
{
|
||||
hb_ot_var_axis_info_t info;
|
||||
if (hb_ot_var_find_axis_info (font->face, variations[i].tag, &info) &&
|
||||
info.axis_index < coords_length)
|
||||
{
|
||||
float v = variations[i].value;
|
||||
design_coords[info.axis_index] = v;
|
||||
normalized[info.axis_index] = fvar.normalize_axis_value (info.axis_index, v);
|
||||
}
|
||||
const auto tag = variations[i].tag;
|
||||
const auto v = variations[i].value;
|
||||
for (unsigned axis_index = 0; axis_index < coords_length; axis_index++)
|
||||
if (axes[axis_index].axisTag == tag)
|
||||
{
|
||||
design_coords[axis_index] = v;
|
||||
normalized[axis_index] = fvar.normalize_axis_value (axis_index, v);
|
||||
}
|
||||
}
|
||||
font->face->table.avar->map_coords (normalized, coords_length);
|
||||
|
||||
|
|
|
|||
|
|
@ -217,9 +217,10 @@ struct hb_font_t
|
|||
}
|
||||
|
||||
hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
|
||||
hb_codepoint_t *glyph)
|
||||
hb_codepoint_t *glyph,
|
||||
hb_codepoint_t not_found = 0)
|
||||
{
|
||||
*glyph = 0;
|
||||
*glyph = not_found;
|
||||
return klass->get.f.nominal_glyph (this, user_data,
|
||||
unicode, glyph,
|
||||
klass->user_data.nominal_glyph);
|
||||
|
|
@ -238,9 +239,10 @@ struct hb_font_t
|
|||
}
|
||||
|
||||
hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph)
|
||||
hb_codepoint_t *glyph,
|
||||
hb_codepoint_t not_found = 0)
|
||||
{
|
||||
*glyph = 0;
|
||||
*glyph = not_found;
|
||||
return klass->get.f.variation_glyph (this, user_data,
|
||||
unicode, variation_selector, glyph,
|
||||
klass->user_data.variation_glyph);
|
||||
|
|
@ -618,9 +620,7 @@ struct hb_font_t
|
|||
}
|
||||
|
||||
hb_position_t em_mult (int16_t v, int64_t mult)
|
||||
{
|
||||
return (hb_position_t) ((v * mult) >> 16);
|
||||
}
|
||||
{ return (hb_position_t) ((v * mult + 32768) >> 16); }
|
||||
hb_position_t em_scalef (float v, int scale)
|
||||
{ return (hb_position_t) roundf (v * scale / face->get_upem ()); }
|
||||
float em_fscale (int16_t v, int scale)
|
||||
|
|
|
|||
|
|
@ -361,6 +361,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
static hb_position_t
|
||||
hb_ft_get_glyph_v_advance (hb_font_t *font,
|
||||
void *font_data,
|
||||
|
|
@ -381,7 +382,9 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
|
|||
* have a Y growing upward. Hence the extra negation. */
|
||||
return (-v + (1<<9)) >> 10;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
static hb_bool_t
|
||||
hb_ft_get_glyph_v_origin (hb_font_t *font,
|
||||
void *font_data,
|
||||
|
|
@ -409,6 +412,7 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
|
|||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE_FALLBACK
|
||||
static hb_position_t
|
||||
|
|
@ -561,9 +565,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
|||
return true;
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ft_funcs ();
|
||||
#endif
|
||||
static inline void free_static_ft_funcs ();
|
||||
|
||||
static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
|
||||
{
|
||||
|
|
@ -571,15 +573,20 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
|
|||
{
|
||||
hb_font_funcs_t *funcs = hb_font_funcs_create ();
|
||||
|
||||
hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
|
||||
//hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
|
||||
hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
|
||||
hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
|
||||
|
||||
hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
|
||||
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
//hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE_FALLBACK
|
||||
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
|
||||
#endif
|
||||
|
|
@ -591,21 +598,17 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
|
|||
|
||||
hb_font_funcs_make_immutable (funcs);
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ft_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_ft_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_ft_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_ft_funcs ()
|
||||
{
|
||||
static_ft_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_font_funcs_t *
|
||||
_hb_ft_get_font_funcs ()
|
||||
|
|
@ -905,9 +908,7 @@ hb_ft_font_create_referenced (FT_Face ft_face)
|
|||
return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ft_library ();
|
||||
#endif
|
||||
static inline void free_static_ft_library ();
|
||||
|
||||
static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<FT_Library>,
|
||||
hb_ft_library_lazy_loader_t>
|
||||
|
|
@ -918,9 +919,7 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<F
|
|||
if (FT_Init_FreeType (&l))
|
||||
return nullptr;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ft_library);
|
||||
#endif
|
||||
hb_atexit (free_static_ft_library);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
|
@ -934,13 +933,11 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<F
|
|||
}
|
||||
} static_ft_library;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_ft_library ()
|
||||
{
|
||||
static_ft_library.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static FT_Library
|
||||
get_ft_library ()
|
||||
|
|
|
|||
|
|
@ -218,9 +218,7 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
|||
}
|
||||
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_glib_funcs ();
|
||||
#endif
|
||||
static inline void free_static_glib_funcs ();
|
||||
|
||||
static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_glib_unicode_funcs_lazy_loader_t>
|
||||
{
|
||||
|
|
@ -237,21 +235,17 @@ static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader
|
|||
|
||||
hb_unicode_funcs_make_immutable (funcs);
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_glib_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_glib_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_glib_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_glib_funcs ()
|
||||
{
|
||||
static_glib_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_glib_get_unicode_funcs:
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
|||
if (feats) gr_featureval_destroy (feats);
|
||||
gr_seg_destroy (seg);
|
||||
|
||||
buffer->unsafe_to_break_all ();
|
||||
buffer->clear_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,9 +233,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
|||
}
|
||||
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_icu_funcs ();
|
||||
#endif
|
||||
static inline void free_static_icu_funcs ();
|
||||
|
||||
static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_icu_unicode_funcs_lazy_loader_t>
|
||||
{
|
||||
|
|
@ -257,21 +255,17 @@ static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_
|
|||
|
||||
hb_unicode_funcs_make_immutable (funcs);
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_icu_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_icu_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_icu_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_icu_funcs ()
|
||||
{
|
||||
static_icu_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_icu_get_unicode_funcs:
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ struct
|
|||
{
|
||||
template <typename T> hb_iter_type<T>
|
||||
operator () (T&& c) const
|
||||
{ return hb_deref (hb_forward<T> (c)).iter (); }
|
||||
{ return hb_deref (std::forward<T> (c)).iter (); }
|
||||
|
||||
/* Specialization for C arrays. */
|
||||
|
||||
|
|
@ -353,7 +353,7 @@ static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).
|
|||
template <typename Lhs, typename Rhs,
|
||||
hb_requires (hb_is_iterator (Lhs))>
|
||||
static inline auto
|
||||
operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (hb_forward<Rhs> (rhs) (hb_forward<Lhs> (lhs)))
|
||||
operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (std::forward<Rhs> (rhs) (std::forward<Lhs> (lhs)))
|
||||
|
||||
/* hb_map(), hb_filter(), hb_reduce() */
|
||||
|
||||
|
|
@ -581,6 +581,91 @@ struct
|
|||
}
|
||||
HB_FUNCOBJ (hb_zip);
|
||||
|
||||
/* hb_concat() */
|
||||
|
||||
template <typename A, typename B>
|
||||
struct hb_concat_iter_t :
|
||||
hb_iter_t<hb_concat_iter_t<A, B>, typename A::item_t>
|
||||
{
|
||||
hb_concat_iter_t () {}
|
||||
hb_concat_iter_t (A& a, B& b) : a (a), b (b) {}
|
||||
hb_concat_iter_t (const A& a, const B& b) : a (a), b (b) {}
|
||||
|
||||
|
||||
typedef typename A::item_t __item_t__;
|
||||
static constexpr bool is_random_access_iterator =
|
||||
A::is_random_access_iterator &&
|
||||
B::is_random_access_iterator;
|
||||
static constexpr bool is_sorted_iterator = false;
|
||||
|
||||
__item_t__ __item__ () const
|
||||
{
|
||||
if (!a)
|
||||
return *b;
|
||||
return *a;
|
||||
}
|
||||
|
||||
__item_t__ __item_at__ (unsigned i) const
|
||||
{
|
||||
unsigned a_len = a.len ();
|
||||
if (i < a_len)
|
||||
return a[i];
|
||||
return b[i - a_len];
|
||||
}
|
||||
|
||||
bool __more__ () const { return bool (a) || bool (b); }
|
||||
|
||||
unsigned __len__ () const { return a.len () + b.len (); }
|
||||
|
||||
void __next__ ()
|
||||
{
|
||||
if (a)
|
||||
++a;
|
||||
else
|
||||
++b;
|
||||
}
|
||||
|
||||
void __forward__ (unsigned n)
|
||||
{
|
||||
if (!n) return;
|
||||
if (!is_random_access_iterator) {
|
||||
while (n-- && *this) {
|
||||
(*this)++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned a_len = a.len ();
|
||||
if (n > a_len) {
|
||||
n -= a_len;
|
||||
a.__forward__ (a_len);
|
||||
b.__forward__ (n);
|
||||
} else {
|
||||
a.__forward__ (n);
|
||||
}
|
||||
}
|
||||
|
||||
hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); }
|
||||
bool operator != (const hb_concat_iter_t& o) const
|
||||
{
|
||||
return a != o.a
|
||||
|| b != o.b;
|
||||
}
|
||||
|
||||
private:
|
||||
A a;
|
||||
B b;
|
||||
};
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename A, typename B,
|
||||
hb_requires (hb_is_iterable (A) && hb_is_iterable (B))>
|
||||
hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>>
|
||||
operator () (A&& a, B&& b) const
|
||||
{ return hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); }
|
||||
}
|
||||
HB_FUNCOBJ (hb_concat);
|
||||
|
||||
/* hb_apply() */
|
||||
|
||||
template <typename Appl>
|
||||
|
|
@ -674,8 +759,8 @@ struct hb_iota_iter_t :
|
|||
template <typename S2 = S>
|
||||
auto
|
||||
inc (hb_type_identity<S2> s, hb_priority<1>)
|
||||
-> hb_void_t<decltype (hb_invoke (hb_forward<S2> (s), hb_declval<T&> ()))>
|
||||
{ v = hb_invoke (hb_forward<S2> (s), v); }
|
||||
-> hb_void_t<decltype (hb_invoke (std::forward<S2> (s), hb_declval<T&> ()))>
|
||||
{ v = hb_invoke (std::forward<S2> (s), v); }
|
||||
|
||||
void
|
||||
inc (S s, hb_priority<0>)
|
||||
|
|
@ -874,7 +959,7 @@ struct
|
|||
Proj&& f = hb_identity) const
|
||||
{
|
||||
for (auto it = hb_iter (c); it; ++it)
|
||||
if (!hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
|
||||
if (!hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -891,7 +976,7 @@ struct
|
|||
Proj&& f = hb_identity) const
|
||||
{
|
||||
for (auto it = hb_iter (c); it; ++it)
|
||||
if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
|
||||
if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -908,7 +993,7 @@ struct
|
|||
Proj&& f = hb_identity) const
|
||||
{
|
||||
for (auto it = hb_iter (c); it; ++it)
|
||||
if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
|
||||
if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ hb_map_set (hb_map_t *map,
|
|||
hb_codepoint_t key,
|
||||
hb_codepoint_t value)
|
||||
{
|
||||
/* Immutable-safe. */
|
||||
map->set (key, value);
|
||||
}
|
||||
|
||||
|
|
@ -220,6 +221,7 @@ void
|
|||
hb_map_del (hb_map_t *map,
|
||||
hb_codepoint_t key)
|
||||
{
|
||||
/* Immutable-safe. */
|
||||
map->del (key);
|
||||
}
|
||||
|
||||
|
|
@ -253,9 +255,6 @@ hb_map_has (const hb_map_t *map,
|
|||
void
|
||||
hb_map_clear (hb_map_t *map)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (map)))
|
||||
return;
|
||||
|
||||
return map->clear ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,16 +35,39 @@
|
|||
*/
|
||||
|
||||
template <typename K, typename V,
|
||||
K kINVALID = hb_is_pointer (K) ? 0 : hb_is_signed (K) ? hb_int_min (K) : (K) -1,
|
||||
V vINVALID = hb_is_pointer (V) ? 0 : hb_is_signed (V) ? hb_int_min (V) : (V) -1>
|
||||
typename k_invalid_t = K,
|
||||
typename v_invalid_t = V,
|
||||
k_invalid_t kINVALID = hb_is_pointer (K) ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1,
|
||||
v_invalid_t vINVALID = hb_is_pointer (V) ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1>
|
||||
struct hb_hashmap_t
|
||||
{
|
||||
HB_DELETE_COPY_ASSIGN (hb_hashmap_t);
|
||||
static constexpr K INVALID_KEY = kINVALID;
|
||||
static constexpr V INVALID_VALUE = vINVALID;
|
||||
|
||||
hb_hashmap_t () { init (); }
|
||||
~hb_hashmap_t () { fini (); }
|
||||
|
||||
static_assert (hb_is_integral (K) || hb_is_pointer (K), "");
|
||||
static_assert (hb_is_integral (V) || hb_is_pointer (V), "");
|
||||
hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { hb_copy (o, *this); }
|
||||
hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
|
||||
hb_hashmap_t& operator= (const hb_hashmap_t& o) { hb_copy (o, *this); return *this; }
|
||||
hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; }
|
||||
|
||||
hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t ()
|
||||
{
|
||||
for (auto&& item : lst)
|
||||
set (item.first, item.second);
|
||||
}
|
||||
template <typename Iterable,
|
||||
hb_requires (hb_is_iterable (Iterable))>
|
||||
hb_hashmap_t (const Iterable &o) : hb_hashmap_t ()
|
||||
{
|
||||
hb_copy (o, *this);
|
||||
}
|
||||
|
||||
static_assert (std::is_trivially_copyable<K>::value, "");
|
||||
static_assert (std::is_trivially_copyable<V>::value, "");
|
||||
static_assert (std::is_trivially_destructible<K>::value, "");
|
||||
static_assert (std::is_trivially_destructible<V>::value, "");
|
||||
|
||||
struct item_t
|
||||
{
|
||||
|
|
@ -70,6 +93,16 @@ struct hb_hashmap_t
|
|||
unsigned int prime;
|
||||
item_t *items;
|
||||
|
||||
friend void swap (hb_hashmap_t& a, hb_hashmap_t& b)
|
||||
{
|
||||
if (unlikely (!a.successful || !b.successful))
|
||||
return;
|
||||
hb_swap (a.population, b.population);
|
||||
hb_swap (a.occupancy, b.occupancy);
|
||||
hb_swap (a.mask, b.mask);
|
||||
hb_swap (a.prime, b.prime);
|
||||
hb_swap (a.items, b.items);
|
||||
}
|
||||
void init_shallow ()
|
||||
{
|
||||
successful = true;
|
||||
|
|
@ -133,17 +166,15 @@ struct hb_hashmap_t
|
|||
if (old_items[i].is_real ())
|
||||
set_with_hash (old_items[i].key,
|
||||
old_items[i].hash,
|
||||
old_items[i].value);
|
||||
std::move (old_items[i].value));
|
||||
|
||||
hb_free (old_items);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set (K key, V value)
|
||||
{
|
||||
return set_with_hash (key, hb_hash (key), value);
|
||||
}
|
||||
bool set (K key, const V& value) { return set_with_hash (key, hb_hash (key), value); }
|
||||
bool set (K key, V&& value) { return set_with_hash (key, hb_hash (key), std::move (value)); }
|
||||
|
||||
V get (K key) const
|
||||
{
|
||||
|
|
@ -169,6 +200,8 @@ struct hb_hashmap_t
|
|||
|
||||
void clear ()
|
||||
{
|
||||
if (unlikely (!successful)) return;
|
||||
|
||||
if (items)
|
||||
for (auto &_ : hb_iter (items, mask + 1))
|
||||
_.clear ();
|
||||
|
|
@ -211,7 +244,8 @@ struct hb_hashmap_t
|
|||
|
||||
protected:
|
||||
|
||||
bool set_with_hash (K key, uint32_t hash, V value)
|
||||
template <typename VV>
|
||||
bool set_with_hash (K key, uint32_t hash, VV&& value)
|
||||
{
|
||||
if (unlikely (!successful)) return false;
|
||||
if (unlikely (key == kINVALID)) return true;
|
||||
|
|
@ -224,7 +258,7 @@ struct hb_hashmap_t
|
|||
if (!items[i].is_unused ())
|
||||
{
|
||||
occupancy--;
|
||||
if (items[i].is_tombstone ())
|
||||
if (!items[i].is_tombstone ())
|
||||
population--;
|
||||
}
|
||||
|
||||
|
|
@ -317,9 +351,28 @@ struct hb_hashmap_t
|
|||
*/
|
||||
|
||||
struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
|
||||
hb_codepoint_t,
|
||||
hb_codepoint_t,
|
||||
hb_codepoint_t,
|
||||
HB_MAP_VALUE_INVALID,
|
||||
HB_MAP_VALUE_INVALID> {};
|
||||
HB_MAP_VALUE_INVALID>
|
||||
{
|
||||
using hashmap = hb_hashmap_t<hb_codepoint_t,
|
||||
hb_codepoint_t,
|
||||
hb_codepoint_t,
|
||||
hb_codepoint_t,
|
||||
HB_MAP_VALUE_INVALID,
|
||||
HB_MAP_VALUE_INVALID>;
|
||||
|
||||
hb_map_t () = default;
|
||||
~hb_map_t () = default;
|
||||
hb_map_t (hb_map_t&) = default;
|
||||
hb_map_t& operator= (const hb_map_t&) = default;
|
||||
hb_map_t& operator= (hb_map_t&&) = default;
|
||||
hb_map_t (std::initializer_list<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> lst) : hashmap (lst) {}
|
||||
template <typename Iterable,
|
||||
hb_requires (hb_is_iterable (Iterable))>
|
||||
hb_map_t (const Iterable &o) : hashmap (o) {}
|
||||
};
|
||||
|
||||
#endif /* HB_MAP_HH */
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
|
||||
#include "hb.hh"
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
|
||||
/*
|
||||
* C++ template meta-programming & fundamentals used with them.
|
||||
|
|
@ -101,14 +104,14 @@ HB_FUNCOBJ (hb_addressof);
|
|||
template <typename T> static inline T hb_declval ();
|
||||
#define hb_declval(T) (hb_declval<T> ())
|
||||
|
||||
template <typename T> struct hb_match_const : hb_type_identity_t<T>, hb_bool_constant<false>{};
|
||||
template <typename T> struct hb_match_const<const T> : hb_type_identity_t<T>, hb_bool_constant<true> {};
|
||||
template <typename T> struct hb_match_const : hb_type_identity_t<T>, hb_false_type {};
|
||||
template <typename T> struct hb_match_const<const T> : hb_type_identity_t<T>, hb_true_type {};
|
||||
template <typename T> using hb_remove_const = typename hb_match_const<T>::type;
|
||||
template <typename T> using hb_add_const = const T;
|
||||
#define hb_is_const(T) hb_match_const<T>::value
|
||||
template <typename T> struct hb_match_reference : hb_type_identity_t<T>, hb_bool_constant<false>{};
|
||||
template <typename T> struct hb_match_reference<T &> : hb_type_identity_t<T>, hb_bool_constant<true> {};
|
||||
template <typename T> struct hb_match_reference<T &&> : hb_type_identity_t<T>, hb_bool_constant<true> {};
|
||||
template <typename T> struct hb_match_reference : hb_type_identity_t<T>, hb_false_type {};
|
||||
template <typename T> struct hb_match_reference<T &> : hb_type_identity_t<T>, hb_true_type {};
|
||||
template <typename T> struct hb_match_reference<T &&> : hb_type_identity_t<T>, hb_true_type {};
|
||||
template <typename T> using hb_remove_reference = typename hb_match_reference<T>::type;
|
||||
template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<1>) -> hb_type_identity<T&>;
|
||||
template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
|
||||
|
|
@ -117,8 +120,8 @@ template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_t
|
|||
template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
|
||||
template <typename T> using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference<T> (hb_prioritize));
|
||||
#define hb_is_reference(T) hb_match_reference<T>::value
|
||||
template <typename T> struct hb_match_pointer : hb_type_identity_t<T>, hb_bool_constant<false>{};
|
||||
template <typename T> struct hb_match_pointer<T *> : hb_type_identity_t<T>, hb_bool_constant<true> {};
|
||||
template <typename T> struct hb_match_pointer : hb_type_identity_t<T>, hb_false_type {};
|
||||
template <typename T> struct hb_match_pointer<T *> : hb_type_identity_t<T>, hb_true_type {};
|
||||
template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
|
||||
template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<hb_remove_reference<T>*>;
|
||||
template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<T>;
|
||||
|
|
@ -129,40 +132,7 @@ template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (h
|
|||
/* TODO Add feature-parity to std::decay. */
|
||||
template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
|
||||
|
||||
|
||||
template<bool B, class T, class F>
|
||||
struct _hb_conditional { typedef T type; };
|
||||
template<class T, class F>
|
||||
struct _hb_conditional<false, T, F> { typedef F type; };
|
||||
template<bool B, class T, class F>
|
||||
using hb_conditional = typename _hb_conditional<B, T, F>::type;
|
||||
|
||||
|
||||
template <typename From, typename To>
|
||||
struct hb_is_convertible
|
||||
{
|
||||
private:
|
||||
static constexpr bool from_void = hb_is_same (void, hb_decay<From>);
|
||||
static constexpr bool to_void = hb_is_same (void, hb_decay<To> );
|
||||
static constexpr bool either_void = from_void || to_void;
|
||||
static constexpr bool both_void = from_void && to_void;
|
||||
|
||||
static hb_true_type impl2 (hb_conditional<to_void, int, To>);
|
||||
|
||||
template <typename T>
|
||||
static auto impl (hb_priority<1>) -> decltype (impl2 (hb_declval (T)));
|
||||
template <typename T>
|
||||
static hb_false_type impl (hb_priority<0>);
|
||||
public:
|
||||
static constexpr bool value = both_void ||
|
||||
(!either_void &&
|
||||
decltype (impl<hb_conditional<from_void, int, From>> (hb_prioritize))::value);
|
||||
};
|
||||
#define hb_is_convertible(From,To) hb_is_convertible<From, To>::value
|
||||
|
||||
template <typename Base, typename Derived>
|
||||
using hb_is_base_of = hb_is_convertible<hb_decay<Derived> *, hb_decay<Base> *>;
|
||||
#define hb_is_base_of(Base,Derived) hb_is_base_of<Base, Derived>::value
|
||||
#define hb_is_convertible(From,To) std::is_convertible<From, To>::value
|
||||
|
||||
template <typename From, typename To>
|
||||
using hb_is_cr_convertible = hb_bool_constant<
|
||||
|
|
@ -172,20 +142,11 @@ using hb_is_cr_convertible = hb_bool_constant<
|
|||
>;
|
||||
#define hb_is_cr_convertible(From,To) hb_is_cr_convertible<From, To>::value
|
||||
|
||||
/* std::move and std::forward */
|
||||
|
||||
template <typename T>
|
||||
static constexpr hb_remove_reference<T>&& hb_move (T&& t) { return (hb_remove_reference<T>&&) (t); }
|
||||
|
||||
template <typename T>
|
||||
static constexpr T&& hb_forward (hb_remove_reference<T>& t) { return (T&&) t; }
|
||||
template <typename T>
|
||||
static constexpr T&& hb_forward (hb_remove_reference<T>&& t) { return (T&&) t; }
|
||||
|
||||
struct
|
||||
{
|
||||
template <typename T> constexpr auto
|
||||
operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
|
||||
operator () (T&& v) const HB_AUTO_RETURN (std::forward<T> (v))
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (T *v) const HB_AUTO_RETURN (*v)
|
||||
|
|
@ -195,7 +156,7 @@ HB_FUNCOBJ (hb_deref);
|
|||
struct
|
||||
{
|
||||
template <typename T> constexpr auto
|
||||
operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
|
||||
operator () (T&& v) const HB_AUTO_RETURN (std::forward<T> (v))
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v))
|
||||
|
|
@ -226,50 +187,6 @@ struct hb_reference_wrapper<T&>
|
|||
|
||||
/* Type traits */
|
||||
|
||||
template <typename T>
|
||||
using hb_is_integral = hb_bool_constant<
|
||||
hb_is_same (hb_decay<T>, char) ||
|
||||
hb_is_same (hb_decay<T>, signed char) ||
|
||||
hb_is_same (hb_decay<T>, unsigned char) ||
|
||||
hb_is_same (hb_decay<T>, signed int) ||
|
||||
hb_is_same (hb_decay<T>, unsigned int) ||
|
||||
hb_is_same (hb_decay<T>, signed short) ||
|
||||
hb_is_same (hb_decay<T>, unsigned short) ||
|
||||
hb_is_same (hb_decay<T>, signed long) ||
|
||||
hb_is_same (hb_decay<T>, unsigned long) ||
|
||||
hb_is_same (hb_decay<T>, signed long long) ||
|
||||
hb_is_same (hb_decay<T>, unsigned long long) ||
|
||||
false
|
||||
>;
|
||||
#define hb_is_integral(T) hb_is_integral<T>::value
|
||||
template <typename T>
|
||||
using hb_is_floating_point = hb_bool_constant<
|
||||
hb_is_same (hb_decay<T>, float) ||
|
||||
hb_is_same (hb_decay<T>, double) ||
|
||||
hb_is_same (hb_decay<T>, long double) ||
|
||||
false
|
||||
>;
|
||||
#define hb_is_floating_point(T) hb_is_floating_point<T>::value
|
||||
template <typename T>
|
||||
using hb_is_arithmetic = hb_bool_constant<
|
||||
hb_is_integral (T) ||
|
||||
hb_is_floating_point (T) ||
|
||||
false
|
||||
>;
|
||||
#define hb_is_arithmetic(T) hb_is_arithmetic<T>::value
|
||||
|
||||
|
||||
template <typename T>
|
||||
using hb_is_signed = hb_conditional<hb_is_arithmetic (T),
|
||||
hb_bool_constant<(T) -1 < (T) 0>,
|
||||
hb_false_type>;
|
||||
#define hb_is_signed(T) hb_is_signed<T>::value
|
||||
template <typename T>
|
||||
using hb_is_unsigned = hb_conditional<hb_is_arithmetic (T),
|
||||
hb_bool_constant<(T) 0 < (T) -1>,
|
||||
hb_false_type>;
|
||||
#define hb_is_unsigned(T) hb_is_unsigned<T>::value
|
||||
|
||||
template <typename T> struct hb_int_min;
|
||||
template <> struct hb_int_min<char> : hb_integral_constant<char, CHAR_MIN> {};
|
||||
template <> struct hb_int_min<signed char> : hb_integral_constant<signed char, SCHAR_MIN> {};
|
||||
|
|
@ -282,6 +199,7 @@ template <> struct hb_int_min<signed long> : hb_integral_constant<signed long,
|
|||
template <> struct hb_int_min<unsigned long> : hb_integral_constant<unsigned long, 0> {};
|
||||
template <> struct hb_int_min<signed long long> : hb_integral_constant<signed long long, LLONG_MIN> {};
|
||||
template <> struct hb_int_min<unsigned long long> : hb_integral_constant<unsigned long long, 0> {};
|
||||
template <typename T> struct hb_int_min<T *> : hb_integral_constant<T *, nullptr> {};
|
||||
#define hb_int_min(T) hb_int_min<T>::value
|
||||
template <typename T> struct hb_int_max;
|
||||
template <> struct hb_int_max<char> : hb_integral_constant<char, CHAR_MAX> {};
|
||||
|
|
@ -308,108 +226,6 @@ template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigne
|
|||
TypeName(const TypeName&) = delete; \
|
||||
void operator=(const TypeName&) = delete
|
||||
|
||||
template <typename T, typename>
|
||||
struct _hb_is_destructible : hb_false_type {};
|
||||
template <typename T>
|
||||
struct _hb_is_destructible<T, hb_void_t<decltype (hb_declval (T).~T ())>> : hb_true_type {};
|
||||
template <typename T>
|
||||
using hb_is_destructible = _hb_is_destructible<T, void>;
|
||||
#define hb_is_destructible(T) hb_is_destructible<T>::value
|
||||
|
||||
template <typename T, typename, typename ...Ts>
|
||||
struct _hb_is_constructible : hb_false_type {};
|
||||
template <typename T, typename ...Ts>
|
||||
struct _hb_is_constructible<T, hb_void_t<decltype (T (hb_declval (Ts)...))>, Ts...> : hb_true_type {};
|
||||
template <typename T, typename ...Ts>
|
||||
using hb_is_constructible = _hb_is_constructible<T, void, Ts...>;
|
||||
#define hb_is_constructible(...) hb_is_constructible<__VA_ARGS__>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_default_constructible = hb_is_constructible<T>;
|
||||
#define hb_is_default_constructible(T) hb_is_default_constructible<T>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_copy_constructible = hb_is_constructible<T, hb_add_lvalue_reference<hb_add_const<T>>>;
|
||||
#define hb_is_copy_constructible(T) hb_is_copy_constructible<T>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_move_constructible = hb_is_constructible<T, hb_add_rvalue_reference<hb_add_const<T>>>;
|
||||
#define hb_is_move_constructible(T) hb_is_move_constructible<T>::value
|
||||
|
||||
template <typename T, typename U, typename>
|
||||
struct _hb_is_assignable : hb_false_type {};
|
||||
template <typename T, typename U>
|
||||
struct _hb_is_assignable<T, U, hb_void_t<decltype (hb_declval (T) = hb_declval (U))>> : hb_true_type {};
|
||||
template <typename T, typename U>
|
||||
using hb_is_assignable = _hb_is_assignable<T, U, void>;
|
||||
#define hb_is_assignable(T,U) hb_is_assignable<T, U>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_copy_assignable = hb_is_assignable<hb_add_lvalue_reference<T>,
|
||||
hb_add_lvalue_reference<hb_add_const<T>>>;
|
||||
#define hb_is_copy_assignable(T) hb_is_copy_assignable<T>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_move_assignable = hb_is_assignable<hb_add_lvalue_reference<T>,
|
||||
hb_add_rvalue_reference<T>>;
|
||||
#define hb_is_move_assignable(T) hb_is_move_assignable<T>::value
|
||||
|
||||
/* Trivial versions. */
|
||||
|
||||
template <typename T> union hb_trivial { T value; };
|
||||
|
||||
template <typename T>
|
||||
using hb_is_trivially_destructible= hb_is_destructible<hb_trivial<T>>;
|
||||
#define hb_is_trivially_destructible(T) hb_is_trivially_destructible<T>::value
|
||||
|
||||
/* Don't know how to do the following. */
|
||||
//template <typename T, typename ...Ts>
|
||||
//using hb_is_trivially_constructible= hb_is_constructible<hb_trivial<T>, hb_trivial<Ts>...>;
|
||||
//#define hb_is_trivially_constructible(...) hb_is_trivially_constructible<__VA_ARGS__>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_trivially_default_constructible= hb_is_default_constructible<hb_trivial<T>>;
|
||||
#define hb_is_trivially_default_constructible(T) hb_is_trivially_default_constructible<T>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_trivially_copy_constructible= hb_is_copy_constructible<hb_trivial<T>>;
|
||||
#define hb_is_trivially_copy_constructible(T) hb_is_trivially_copy_constructible<T>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_trivially_move_constructible= hb_is_move_constructible<hb_trivial<T>>;
|
||||
#define hb_is_trivially_move_constructible(T) hb_is_trivially_move_constructible<T>::value
|
||||
|
||||
/* Don't know how to do the following. */
|
||||
//template <typename T, typename U>
|
||||
//using hb_is_trivially_assignable= hb_is_assignable<hb_trivial<T>, hb_trivial<U>>;
|
||||
//#define hb_is_trivially_assignable(T,U) hb_is_trivially_assignable<T, U>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_trivially_copy_assignable= hb_is_copy_assignable<hb_trivial<T>>;
|
||||
#define hb_is_trivially_copy_assignable(T) hb_is_trivially_copy_assignable<T>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_trivially_move_assignable= hb_is_move_assignable<hb_trivial<T>>;
|
||||
#define hb_is_trivially_move_assignable(T) hb_is_trivially_move_assignable<T>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_trivially_copyable= hb_bool_constant<
|
||||
hb_is_trivially_destructible (T) &&
|
||||
(!hb_is_move_assignable (T) || hb_is_trivially_move_assignable (T)) &&
|
||||
(!hb_is_move_constructible (T) || hb_is_trivially_move_constructible (T)) &&
|
||||
(!hb_is_copy_assignable (T) || hb_is_trivially_copy_assignable (T)) &&
|
||||
(!hb_is_copy_constructible (T) || hb_is_trivially_copy_constructible (T)) &&
|
||||
true
|
||||
>;
|
||||
#define hb_is_trivially_copyable(T) hb_is_trivially_copyable<T>::value
|
||||
|
||||
template <typename T>
|
||||
using hb_is_trivial= hb_bool_constant<
|
||||
hb_is_trivially_copyable (T) &&
|
||||
hb_is_trivially_default_constructible (T)
|
||||
>;
|
||||
#define hb_is_trivial(T) hb_is_trivial<T>::value
|
||||
|
||||
/* hb_unwrap_type (T)
|
||||
* If T has no T::type, returns T. Otherwise calls itself on T::type recursively.
|
||||
*/
|
||||
|
|
|
|||
177
gfx/harfbuzz/src/hb-ms-feature-ranges.cc
Normal file
177
gfx/harfbuzz/src/hb-ms-feature-ranges.cc
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright © 2011,2012,2013 Google, Inc.
|
||||
* Copyright © 2021 Khaled Hosny
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "hb-ms-feature-ranges.hh"
|
||||
|
||||
bool
|
||||
hb_ms_setup_features (const hb_feature_t *features,
|
||||
unsigned int num_features,
|
||||
hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */
|
||||
hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */)
|
||||
{
|
||||
feature_records.shrink(0);
|
||||
range_records.shrink(0);
|
||||
|
||||
/* Sort features by start/end events. */
|
||||
hb_vector_t<hb_ms_feature_event_t> feature_events;
|
||||
for (unsigned int i = 0; i < num_features; i++)
|
||||
{
|
||||
hb_ms_active_feature_t feature;
|
||||
feature.fea.tag_le = hb_uint32_swap (features[i].tag);
|
||||
feature.fea.value = features[i].value;
|
||||
feature.order = i;
|
||||
|
||||
hb_ms_feature_event_t *event;
|
||||
|
||||
event = feature_events.push ();
|
||||
event->index = features[i].start;
|
||||
event->start = true;
|
||||
event->feature = feature;
|
||||
|
||||
event = feature_events.push ();
|
||||
event->index = features[i].end;
|
||||
event->start = false;
|
||||
event->feature = feature;
|
||||
}
|
||||
feature_events.qsort ();
|
||||
/* Add a strategic final event. */
|
||||
{
|
||||
hb_ms_active_feature_t feature;
|
||||
feature.fea.tag_le = 0;
|
||||
feature.fea.value = 0;
|
||||
feature.order = num_features + 1;
|
||||
|
||||
auto *event = feature_events.push ();
|
||||
event->index = 0; /* This value does magic. */
|
||||
event->start = false;
|
||||
event->feature = feature;
|
||||
}
|
||||
|
||||
/* Scan events and save features for each range. */
|
||||
hb_vector_t<hb_ms_active_feature_t> active_features;
|
||||
unsigned int last_index = 0;
|
||||
for (unsigned int i = 0; i < feature_events.length; i++)
|
||||
{
|
||||
auto *event = &feature_events[i];
|
||||
|
||||
if (event->index != last_index)
|
||||
{
|
||||
/* Save a snapshot of active features and the range. */
|
||||
auto *range = range_records.push ();
|
||||
auto offset = feature_records.length;
|
||||
|
||||
active_features.qsort ();
|
||||
for (unsigned int j = 0; j < active_features.length; j++)
|
||||
{
|
||||
if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le)
|
||||
{
|
||||
feature_records.push (active_features[j].fea);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Overrides value for existing feature. */
|
||||
feature_records[feature_records.length - 1].value = active_features[j].fea.value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Will convert to pointer after all is ready, since feature_records.array
|
||||
* may move as we grow it. */
|
||||
range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset);
|
||||
range->features.num_features = feature_records.length - offset;
|
||||
range->index_first = last_index;
|
||||
range->index_last = event->index - 1;
|
||||
|
||||
last_index = event->index;
|
||||
}
|
||||
|
||||
if (event->start)
|
||||
{
|
||||
active_features.push (event->feature);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto *feature = active_features.find (&event->feature);
|
||||
if (feature)
|
||||
active_features.remove (feature - active_features.arrayZ);
|
||||
}
|
||||
}
|
||||
|
||||
if (!range_records.length) /* No active feature found. */
|
||||
num_features = 0;
|
||||
|
||||
/* Fixup the pointers. */
|
||||
for (unsigned int i = 0; i < range_records.length; i++)
|
||||
{
|
||||
auto *range = &range_records[i];
|
||||
range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features);
|
||||
}
|
||||
|
||||
return !!num_features;
|
||||
}
|
||||
|
||||
void
|
||||
hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records,
|
||||
hb_vector_t<hb_ms_range_record_t> &range_records,
|
||||
unsigned int chars_offset,
|
||||
unsigned int chars_len,
|
||||
uint16_t *log_clusters,
|
||||
hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */
|
||||
hb_vector_t<uint32_t> &range_counts /* OUT */)
|
||||
{
|
||||
range_features.shrink (0);
|
||||
range_counts.shrink (0);
|
||||
|
||||
auto *last_range = &range_records[0];
|
||||
for (unsigned int i = chars_offset; i < chars_len; i++)
|
||||
{
|
||||
auto *range = last_range;
|
||||
while (log_clusters[i] < range->index_first)
|
||||
range--;
|
||||
while (log_clusters[i] > range->index_last)
|
||||
range++;
|
||||
if (!range_features.length ||
|
||||
&range->features != range_features[range_features.length - 1])
|
||||
{
|
||||
auto **features = range_features.push ();
|
||||
auto *c = range_counts.push ();
|
||||
if (unlikely (!features || !c))
|
||||
{
|
||||
range_features.shrink (0);
|
||||
range_counts.shrink (0);
|
||||
break;
|
||||
}
|
||||
*features = &range->features;
|
||||
*c = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
range_counts[range_counts.length - 1]++;
|
||||
}
|
||||
|
||||
last_range = range;
|
||||
}
|
||||
}
|
||||
96
gfx/harfbuzz/src/hb-ms-feature-ranges.hh
Normal file
96
gfx/harfbuzz/src/hb-ms-feature-ranges.hh
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright © 2011,2012,2013 Google, Inc.
|
||||
* Copyright © 2021 Khaled Hosny
|
||||
*
|
||||
* 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_MS_FEATURE_RANGES_HH
|
||||
#define HB_MS_FEATURE_RANGES_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
typedef struct hb_ms_feature_t {
|
||||
uint32_t tag_le;
|
||||
uint32_t value;
|
||||
} hb_ms_feature_t;
|
||||
|
||||
typedef struct hb_ms_features_t {
|
||||
hb_ms_feature_t *features;
|
||||
uint32_t num_features;
|
||||
} hb_ms_features_t;
|
||||
|
||||
struct hb_ms_active_feature_t {
|
||||
hb_ms_feature_t fea;
|
||||
unsigned int order;
|
||||
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb) {
|
||||
const auto *a = (const hb_ms_active_feature_t *) pa;
|
||||
const auto *b = (const hb_ms_active_feature_t *) pb;
|
||||
return a->fea.tag_le < b->fea.tag_le ? -1 : a->fea.tag_le > b->fea.tag_le ? 1 :
|
||||
a->order < b->order ? -1 : a->order > b->order ? 1 :
|
||||
a->fea.value < b->fea.value ? -1 : a->fea.value > b->fea.value ? 1 :
|
||||
0;
|
||||
}
|
||||
bool operator== (const hb_ms_active_feature_t *f)
|
||||
{ return cmp (this, f) == 0; }
|
||||
};
|
||||
|
||||
struct hb_ms_feature_event_t {
|
||||
unsigned int index;
|
||||
bool start;
|
||||
hb_ms_active_feature_t feature;
|
||||
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb)
|
||||
{
|
||||
const auto *a = (const hb_ms_feature_event_t *) pa;
|
||||
const auto *b = (const hb_ms_feature_event_t *) pb;
|
||||
return a->index < b->index ? -1 : a->index > b->index ? 1 :
|
||||
a->start < b->start ? -1 : a->start > b->start ? 1 :
|
||||
hb_ms_active_feature_t::cmp (&a->feature, &b->feature);
|
||||
}
|
||||
};
|
||||
|
||||
struct hb_ms_range_record_t {
|
||||
hb_ms_features_t features;
|
||||
unsigned int index_first; /* == start */
|
||||
unsigned int index_last; /* == end - 1 */
|
||||
};
|
||||
|
||||
HB_INTERNAL bool
|
||||
hb_ms_setup_features (const hb_feature_t *features,
|
||||
unsigned int num_features,
|
||||
hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */
|
||||
hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */);
|
||||
|
||||
|
||||
HB_INTERNAL void
|
||||
hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records,
|
||||
hb_vector_t<hb_ms_range_record_t> &range_records,
|
||||
unsigned int chars_offset,
|
||||
unsigned int chars_len,
|
||||
uint16_t *log_clusters,
|
||||
hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */
|
||||
hb_vector_t<uint32_t> &range_counts /* OUT */);
|
||||
|
||||
#endif /* HB_MS_FEATURE_RANGES_HH */
|
||||
|
|
@ -39,8 +39,7 @@
|
|||
|
||||
/* We need external help for these */
|
||||
|
||||
#if defined(HB_MUTEX_IMPL_INIT) \
|
||||
&& defined(hb_mutex_impl_init) \
|
||||
#if defined(hb_mutex_impl_init) \
|
||||
&& defined(hb_mutex_impl_lock) \
|
||||
&& defined(hb_mutex_impl_unlock) \
|
||||
&& defined(hb_mutex_impl_finish)
|
||||
|
|
@ -48,21 +47,19 @@
|
|||
/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
|
||||
|
||||
|
||||
#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
|
||||
#elif !defined(HB_NO_MT) && !defined(HB_MUTEX_IMPL_STD_MUTEX) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
|
||||
|
||||
#include <pthread.h>
|
||||
typedef pthread_mutex_t hb_mutex_impl_t;
|
||||
#define HB_MUTEX_IMPL_INIT PTHREAD_MUTEX_INITIALIZER
|
||||
#define hb_mutex_impl_init(M) pthread_mutex_init (M, nullptr)
|
||||
#define hb_mutex_impl_lock(M) pthread_mutex_lock (M)
|
||||
#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M)
|
||||
#define hb_mutex_impl_finish(M) pthread_mutex_destroy (M)
|
||||
|
||||
|
||||
#elif !defined(HB_NO_MT) && defined(_WIN32)
|
||||
#elif !defined(HB_NO_MT) && !defined(HB_MUTEX_IMPL_STD_MUTEX) && defined(_WIN32)
|
||||
|
||||
typedef CRITICAL_SECTION hb_mutex_impl_t;
|
||||
#define HB_MUTEX_IMPL_INIT {0}
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0)
|
||||
#else
|
||||
|
|
@ -73,34 +70,40 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
|
|||
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
|
||||
|
||||
|
||||
#elif defined(HB_NO_MT)
|
||||
#elif !defined(HB_NO_MT)
|
||||
|
||||
#include <mutex>
|
||||
typedef std::mutex hb_mutex_impl_t;
|
||||
#define hb_mutex_impl_init(M) HB_STMT_START { new (M) hb_mutex_impl_t; } HB_STMT_END
|
||||
#define hb_mutex_impl_lock(M) (M)->lock ()
|
||||
#define hb_mutex_impl_unlock(M) (M)->unlock ()
|
||||
#define hb_mutex_impl_finish(M) HB_STMT_START { (M)->~hb_mutex_impl_t(); } HB_STMT_END
|
||||
|
||||
|
||||
#else /* defined(HB_NO_MT) */
|
||||
|
||||
typedef int hb_mutex_impl_t;
|
||||
#define HB_MUTEX_IMPL_INIT 0
|
||||
#define hb_mutex_impl_init(M) HB_STMT_START {} HB_STMT_END
|
||||
#define hb_mutex_impl_lock(M) HB_STMT_START {} HB_STMT_END
|
||||
#define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END
|
||||
#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#error "Could not find any system to define mutex macros."
|
||||
#error "Check hb-mutex.hh for possible resolutions."
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT}
|
||||
|
||||
struct hb_mutex_t
|
||||
{
|
||||
hb_mutex_impl_t m;
|
||||
/* Create space for, but do not initialize m. */
|
||||
alignas(hb_mutex_impl_t) char m[sizeof (hb_mutex_impl_t)];
|
||||
|
||||
void init () { hb_mutex_impl_init (&m); }
|
||||
void lock () { hb_mutex_impl_lock (&m); }
|
||||
void unlock () { hb_mutex_impl_unlock (&m); }
|
||||
void fini () { hb_mutex_impl_finish (&m); }
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
void init () { hb_mutex_impl_init ((hb_mutex_impl_t *) m); }
|
||||
void lock () { hb_mutex_impl_lock ((hb_mutex_impl_t *) m); }
|
||||
void unlock () { hb_mutex_impl_unlock ((hb_mutex_impl_t *) m); }
|
||||
void fini () { hb_mutex_impl_finish ((hb_mutex_impl_t *) m); }
|
||||
#pragma GCC diagnostic pop
|
||||
};
|
||||
|
||||
struct hb_lock_t
|
||||
|
|
|
|||
|
|
@ -140,8 +140,6 @@ struct hb_lockable_set_t
|
|||
* Reference-count.
|
||||
*/
|
||||
|
||||
#define HB_REFERENCE_COUNT_INIT {0}
|
||||
|
||||
struct hb_reference_count_t
|
||||
{
|
||||
mutable hb_atomic_int_t ref_count;
|
||||
|
|
@ -197,6 +195,8 @@ struct hb_object_header_t
|
|||
hb_reference_count_t ref_count;
|
||||
mutable hb_atomic_int_t writable = 0;
|
||||
hb_atomic_ptr_t<hb_user_data_array_t> user_data;
|
||||
|
||||
bool is_inert () const { return !ref_count.get_relaxed (); }
|
||||
};
|
||||
#define HB_OBJECT_HEADER_STATIC {}
|
||||
|
||||
|
|
@ -234,11 +234,6 @@ static inline void hb_object_init (Type *obj)
|
|||
obj->header.user_data.init ();
|
||||
}
|
||||
template <typename Type>
|
||||
static inline bool hb_object_is_inert (const Type *obj)
|
||||
{
|
||||
return unlikely (obj->header.ref_count.is_inert ());
|
||||
}
|
||||
template <typename Type>
|
||||
static inline bool hb_object_is_valid (const Type *obj)
|
||||
{
|
||||
return likely (obj->header.ref_count.is_valid ());
|
||||
|
|
@ -257,7 +252,7 @@ template <typename Type>
|
|||
static inline Type *hb_object_reference (Type *obj)
|
||||
{
|
||||
hb_object_trace (obj, HB_FUNC);
|
||||
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||
if (unlikely (!obj || obj->header.is_inert ()))
|
||||
return obj;
|
||||
assert (hb_object_is_valid (obj));
|
||||
obj->header.ref_count.inc ();
|
||||
|
|
@ -267,7 +262,7 @@ template <typename Type>
|
|||
static inline bool hb_object_destroy (Type *obj)
|
||||
{
|
||||
hb_object_trace (obj, HB_FUNC);
|
||||
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||
if (unlikely (!obj || obj->header.is_inert ()))
|
||||
return false;
|
||||
assert (hb_object_is_valid (obj));
|
||||
if (obj->header.ref_count.dec () != 1)
|
||||
|
|
@ -295,7 +290,7 @@ static inline bool hb_object_set_user_data (Type *obj,
|
|||
hb_destroy_func_t destroy,
|
||||
hb_bool_t replace)
|
||||
{
|
||||
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||
if (unlikely (!obj || obj->header.is_inert ()))
|
||||
return false;
|
||||
assert (hb_object_is_valid (obj));
|
||||
|
||||
|
|
@ -322,7 +317,7 @@ template <typename Type>
|
|||
static inline void *hb_object_get_user_data (Type *obj,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
if (unlikely (!obj || hb_object_is_inert (obj)))
|
||||
if (unlikely (!obj || obj->header.is_inert ()))
|
||||
return nullptr;
|
||||
assert (hb_object_is_valid (obj));
|
||||
hb_user_data_array_t *user_data = obj->header.user_data.get ();
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
namespace OT {
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* The OpenType Font File
|
||||
|
|
@ -102,7 +101,13 @@ typedef struct OpenTypeOffsetTable
|
|||
{
|
||||
Tag t;
|
||||
t = tag;
|
||||
return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
/* Use lfind for small fonts; there are fonts that have unsorted table entries;
|
||||
* those tend to work in other tools, so tolerate them.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/3065 */
|
||||
if (tables.len < 16)
|
||||
return tables.lfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
else
|
||||
return tables.bfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
}
|
||||
const TableRecord& get_table_by_tag (hb_tag_t tag) const
|
||||
{
|
||||
|
|
@ -113,44 +118,53 @@ typedef struct OpenTypeOffsetTable
|
|||
|
||||
public:
|
||||
|
||||
template <typename item_t>
|
||||
template <typename Iterator,
|
||||
hb_requires ((hb_is_source_of<Iterator, hb_pair_t<hb_tag_t, hb_blob_t *>>::value))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_tag_t sfnt_tag,
|
||||
hb_array_t<item_t> items)
|
||||
Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
/* Alloc 12 for the OTHeader. */
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
/* Write sfntVersion (bytes 0..3). */
|
||||
sfnt_version = sfnt_tag;
|
||||
/* Take space for numTables, searchRange, entrySelector, RangeShift
|
||||
* and the TableRecords themselves. */
|
||||
if (unlikely (!tables.serialize (c, items.length))) return_trace (false);
|
||||
unsigned num_items = it.len ();
|
||||
if (unlikely (!tables.serialize (c, num_items))) return_trace (false);
|
||||
|
||||
const char *dir_end = (const char *) c->head;
|
||||
HBUINT32 *checksum_adjustment = nullptr;
|
||||
|
||||
/* Write OffsetTables, alloc for and write actual table blobs. */
|
||||
for (unsigned int i = 0; i < tables.len; i++)
|
||||
unsigned i = 0;
|
||||
for (hb_pair_t<hb_tag_t, hb_blob_t*> entry : it)
|
||||
{
|
||||
TableRecord &rec = tables.arrayZ[i];
|
||||
hb_blob_t *blob = items[i].blob;
|
||||
rec.tag = items[i].tag;
|
||||
rec.length = blob->length;
|
||||
rec.offset.serialize (c, this);
|
||||
hb_blob_t *blob = entry.second;
|
||||
unsigned len = blob->length;
|
||||
|
||||
/* Allocate room for the table and copy it. */
|
||||
char *start = (char *) c->allocate_size<void> (rec.length);
|
||||
char *start = (char *) c->allocate_size<void> (len);
|
||||
if (unlikely (!start)) return false;
|
||||
|
||||
if (likely (rec.length))
|
||||
memcpy (start, blob->data, rec.length);
|
||||
TableRecord &rec = tables.arrayZ[i];
|
||||
rec.tag = entry.first;
|
||||
rec.length = len;
|
||||
rec.offset = 0;
|
||||
if (unlikely (!c->check_assign (rec.offset,
|
||||
(unsigned) ((char *) start - (char *) this),
|
||||
HB_SERIALIZE_ERROR_OFFSET_OVERFLOW)))
|
||||
return_trace (false);
|
||||
|
||||
if (likely (len))
|
||||
memcpy (start, blob->data, len);
|
||||
|
||||
/* 4-byte alignment. */
|
||||
c->align (4);
|
||||
const char *end = (const char *) c->head;
|
||||
|
||||
if (items[i].tag == HB_OT_TAG_head &&
|
||||
if (entry.first == HB_OT_TAG_head &&
|
||||
(unsigned) (end - start) >= head::static_size)
|
||||
{
|
||||
head *h = (head *) start;
|
||||
|
|
@ -159,6 +173,7 @@ typedef struct OpenTypeOffsetTable
|
|||
}
|
||||
|
||||
rec.checkSum.set_for_data (start, end - start);
|
||||
i++;
|
||||
}
|
||||
|
||||
tables.qsort ();
|
||||
|
|
@ -170,7 +185,7 @@ typedef struct OpenTypeOffsetTable
|
|||
/* The following line is a slower version of the following block. */
|
||||
//checksum.set_for_data (this, (const char *) c->head - (const char *) this);
|
||||
checksum.set_for_data (this, dir_end - (const char *) this);
|
||||
for (unsigned int i = 0; i < items.length; i++)
|
||||
for (unsigned int i = 0; i < num_items; i++)
|
||||
{
|
||||
TableRecord &rec = tables.arrayZ[i];
|
||||
checksum = checksum + rec.checkSum;
|
||||
|
|
@ -477,14 +492,15 @@ struct OpenTypeFontFile
|
|||
}
|
||||
}
|
||||
|
||||
template <typename item_t>
|
||||
template <typename Iterator,
|
||||
hb_requires ((hb_is_source_of<Iterator, hb_pair_t<hb_tag_t, hb_blob_t *>>::value))>
|
||||
bool serialize_single (hb_serialize_context_t *c,
|
||||
hb_tag_t sfnt_tag,
|
||||
hb_array_t<item_t> items)
|
||||
Iterator items)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
assert (sfnt_tag != TTCTag);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
return_trace (u.fontFace.serialize (c, sfnt_tag, items));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ struct IntType
|
|||
IntType& operator = (Type i) { v = i; return *this; }
|
||||
/* For reason we define cast out operator for signed/unsigned, instead of Type, see:
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/2875/commits/09836013995cab2b9f07577a179ad7b024130467 */
|
||||
operator hb_conditional<hb_is_signed (Type), signed, unsigned> () const { return v; }
|
||||
operator typename std::conditional<std::is_signed<Type>::value, signed, unsigned>::type () const { return v; }
|
||||
|
||||
bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; }
|
||||
bool operator != (const IntType &o) const { return !(*this == o); }
|
||||
|
|
@ -86,7 +86,7 @@ struct IntType
|
|||
return pb->cmp (*pa);
|
||||
}
|
||||
template <typename Type2,
|
||||
hb_enable_if (hb_is_integral (Type2) &&
|
||||
hb_enable_if (std::is_integral<Type2>::value &&
|
||||
sizeof (Type2) < sizeof (int) &&
|
||||
sizeof (Type) < sizeof (int))>
|
||||
int cmp (Type2 a) const
|
||||
|
|
@ -122,6 +122,15 @@ typedef IntType<int32_t> HBINT32; /* 32-bit signed integer. */
|
|||
* Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
|
||||
typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
|
||||
|
||||
/* 15-bit unsigned number; top bit used for extension. */
|
||||
struct HBUINT15 : HBUINT16
|
||||
{
|
||||
/* TODO Flesh out; actually mask top bit. */
|
||||
HBUINT15& operator = (uint16_t i ) { HBUINT16::operator= (i); return *this; }
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
|
||||
typedef HBINT16 FWORD;
|
||||
|
||||
|
|
@ -182,9 +191,9 @@ struct Tag : HBUINT32
|
|||
};
|
||||
|
||||
/* Glyph index number, same as uint16 (length = 16 bits) */
|
||||
struct HBGlyphID : HBUINT16
|
||||
struct HBGlyphID16 : HBUINT16
|
||||
{
|
||||
HBGlyphID& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
|
||||
HBGlyphID16& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
|
||||
};
|
||||
|
||||
/* Script/language-system/feature index */
|
||||
|
|
@ -212,15 +221,6 @@ struct Offset : Type
|
|||
|
||||
bool is_null () const { return has_null && 0 == *this; }
|
||||
|
||||
void *serialize (hb_serialize_context_t *c, const void *base)
|
||||
{
|
||||
void *t = c->start_embed<void> ();
|
||||
c->check_assign (*this,
|
||||
(unsigned) ((char *) t - (char *) base),
|
||||
HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
|
||||
return t;
|
||||
}
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (sizeof (Type));
|
||||
};
|
||||
|
|
@ -341,7 +341,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
|
||||
s->push ();
|
||||
|
||||
bool ret = c->dispatch (src_base+src, hb_forward<Ts> (ds)...);
|
||||
bool ret = c->dispatch (src_base+src, std::forward<Ts> (ds)...);
|
||||
|
||||
if (ret || !has_null)
|
||||
s->add_link (*this, s->pop_pack ());
|
||||
|
|
@ -358,7 +358,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
*this = 0;
|
||||
|
||||
Type* obj = c->push<Type> ();
|
||||
bool ret = obj->serialize (c, hb_forward<Ts> (ds)...);
|
||||
bool ret = obj->serialize (c, std::forward<Ts> (ds)...);
|
||||
|
||||
if (ret)
|
||||
c->add_link (*this, c->pop_pack ());
|
||||
|
|
@ -384,7 +384,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
|
||||
c->push ();
|
||||
|
||||
bool ret = c->copy (src_base+src, hb_forward<Ts> (ds)...);
|
||||
bool ret = c->copy (src_base+src, std::forward<Ts> (ds)...);
|
||||
|
||||
c->add_link (*this, c->pop_pack (), whence, dst_bias);
|
||||
|
||||
|
|
@ -410,7 +410,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
TRACE_SANITIZE (this);
|
||||
return_trace (sanitize_shallow (c, base) &&
|
||||
(this->is_null () ||
|
||||
c->dispatch (StructAtOffset<Type> (base, *this), hb_forward<Ts> (ds)...) ||
|
||||
c->dispatch (StructAtOffset<Type> (base, *this), std::forward<Ts> (ds)...) ||
|
||||
neuter (c)));
|
||||
}
|
||||
|
||||
|
|
@ -477,8 +477,10 @@ struct UnsizedArrayOf
|
|||
const Type &lsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const
|
||||
{ return *as_array (len).lsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
bool lfind (unsigned int len, const T &x, unsigned *pos = nullptr) const
|
||||
{ return as_array (len).lfind (x, pos); }
|
||||
bool lfind (unsigned int len, const T &x, unsigned int *i = nullptr,
|
||||
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{ return as_array (len).lfind (x, i, not_found, to_store); }
|
||||
|
||||
void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
|
||||
{ as_array (len).qsort (start, end); }
|
||||
|
|
@ -486,7 +488,7 @@ struct UnsizedArrayOf
|
|||
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend (*this, items_len))) return_trace (false);
|
||||
if (unlikely (!c->extend (this, items_len))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
template <typename Iterator,
|
||||
|
|
@ -516,9 +518,9 @@ struct UnsizedArrayOf
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
|
||||
if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
|
||||
if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
|
||||
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
|
||||
return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
@ -563,7 +565,7 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace ((UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
|
||||
::sanitize (c, count, this, hb_forward<Ts> (ds)...)));
|
||||
::sanitize (c, count, this, std::forward<Ts> (ds)...)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -586,7 +588,7 @@ struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
|
|||
{ return *as_array (len).bsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
bool bfind (unsigned int len, 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
|
||||
{ return as_array (len).bfind (x, i, not_found, to_store); }
|
||||
};
|
||||
|
|
@ -648,8 +650,10 @@ struct ArrayOf
|
|||
const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const
|
||||
{ return *as_array ().lsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
bool lfind (const T &x, unsigned *pos = nullptr) const
|
||||
{ return as_array ().lfind (x, pos); }
|
||||
bool lfind (const T &x, unsigned int *i = nullptr,
|
||||
hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{ return as_array ().lfind (x, i, not_found, to_store); }
|
||||
|
||||
void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
|
||||
{ as_array ().qsort (start, end); }
|
||||
|
|
@ -657,9 +661,9 @@ struct ArrayOf
|
|||
HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
|
||||
if (unlikely (!c->extend (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend (this))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
template <typename Iterator,
|
||||
|
|
@ -680,7 +684,7 @@ struct ArrayOf
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
len++;
|
||||
if (unlikely (!len || !c->extend (*this)))
|
||||
if (unlikely (!len || !c->extend (this)))
|
||||
{
|
||||
len--;
|
||||
return_trace (nullptr);
|
||||
|
|
@ -703,10 +707,10 @@ struct ArrayOf
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||
if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
|
||||
if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
|
||||
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
|
||||
return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
@ -764,7 +768,7 @@ struct List16OfOffset16To : Array16OfOffset16To<Type>
|
|||
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (Array16OfOffset16To<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
|
||||
return_trace (Array16OfOffset16To<Type>::sanitize (c, this, std::forward<Ts> (ds)...));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -807,9 +811,9 @@ struct HeadlessArrayOf
|
|||
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW);
|
||||
if (unlikely (!c->extend (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend (this))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
template <typename Iterator,
|
||||
|
|
@ -831,10 +835,10 @@ struct HeadlessArrayOf
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||
if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
|
||||
if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
|
||||
unsigned int count = get_length ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
|
||||
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
|
||||
return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
@ -880,10 +884,10 @@ struct ArrayOfM1
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||
if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
|
||||
if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
|
||||
unsigned int count = lenM1 + 1;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
|
||||
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
|
||||
return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
@ -950,7 +954,7 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
|
|||
{ return *as_array ().bsearch (x, ¬_found); }
|
||||
template <typename T>
|
||||
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
|
||||
{ return as_array ().bfind (x, i, not_found, to_store); }
|
||||
};
|
||||
|
|
@ -1066,10 +1070,10 @@ struct VarSizedBinSearchArrayOf
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!sanitize_shallow (c))) return_trace (false);
|
||||
if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
|
||||
if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
|
||||
unsigned int count = get_length ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!(*this)[i].sanitize (c, hb_forward<Ts> (ds)...)))
|
||||
if (unlikely (!(*this)[i].sanitize (c, std::forward<Ts> (ds)...)))
|
||||
return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ struct CFFIndex
|
|||
else
|
||||
{
|
||||
/* serialize CFFIndex header */
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
this->count = byteArray.length;
|
||||
this->offSize = offSize_;
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
|
||||
|
|
@ -214,7 +214,7 @@ struct CFFIndex
|
|||
unsigned off_size = calcOffSize (total);
|
||||
|
||||
/* serialize CFFIndex header */
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
this->count = it.len ();
|
||||
this->offSize = off_size;
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (off_size * (it.len () + 1))))
|
||||
|
|
@ -335,7 +335,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
/* serialize CFFIndex header */
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
this->count = dataArrayLen;
|
||||
this->offSize = offSize_;
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
|
||||
|
|
@ -373,7 +373,7 @@ struct Dict : UnsizedByteStr
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
for (unsigned int i = 0; i < dictval.get_count (); i++)
|
||||
if (unlikely (!opszr.serialize (c, dictval[i], hb_forward<Ts> (ds)...)))
|
||||
if (unlikely (!opszr.serialize (c, dictval[i], std::forward<Ts> (ds)...)))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (true);
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ struct Encoding
|
|||
const hb_vector_t<code_pair_t>& supp_codes)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
Encoding *dest = c->extend_min (*this);
|
||||
Encoding *dest = c->extend_min (this);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
|
||||
switch (format) {
|
||||
|
|
@ -457,7 +457,7 @@ struct Charset
|
|||
const hb_vector_t<code_pair_t>& sid_ranges)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
Charset *dest = c->extend_min (*this);
|
||||
Charset *dest = c->extend_min (this);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
dest->format = format;
|
||||
switch (format)
|
||||
|
|
@ -713,6 +713,7 @@ struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
|
|||
case OpCode_Notice:
|
||||
case OpCode_Copyright:
|
||||
case OpCode_FullName:
|
||||
case OpCode_FontName:
|
||||
case OpCode_FamilyName:
|
||||
case OpCode_Weight:
|
||||
case OpCode_PostScript:
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ struct CmapSubtableFormat0
|
|||
*glyph = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
for (unsigned int i = 0; i < 256; i++)
|
||||
|
|
@ -87,120 +93,192 @@ struct CmapSubtableFormat0
|
|||
struct CmapSubtableFormat4
|
||||
{
|
||||
|
||||
|
||||
template<typename Iterator,
|
||||
typename Writer,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
HBUINT16* serialize_endcode_array (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
void to_ranges (Iterator it, Writer& range_writer)
|
||||
{
|
||||
HBUINT16 *endCode = c->start_embed<HBUINT16> ();
|
||||
hb_codepoint_t prev_endcp = 0xFFFF;
|
||||
hb_codepoint_t start_cp = 0, prev_run_start_cp = 0, run_start_cp = 0, end_cp = 0, last_gid = 0;
|
||||
int run_length = 0 , delta = 0, prev_delta = 0;
|
||||
|
||||
for (const auto& _ : +it)
|
||||
{
|
||||
if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
|
||||
{
|
||||
HBUINT16 end_code;
|
||||
end_code = prev_endcp;
|
||||
c->copy<HBUINT16> (end_code);
|
||||
enum {
|
||||
FIRST_SUB_RANGE,
|
||||
FOLLOWING_SUB_RANGE,
|
||||
} mode;
|
||||
|
||||
while (it) {
|
||||
// Start a new range
|
||||
start_cp = (*it).first;
|
||||
prev_run_start_cp = (*it).first;
|
||||
run_start_cp = (*it).first;
|
||||
end_cp = (*it).first;
|
||||
last_gid = (*it).second;
|
||||
run_length = 1;
|
||||
prev_delta = 0;
|
||||
|
||||
delta = (*it).second - (*it).first;
|
||||
mode = FIRST_SUB_RANGE;
|
||||
it++;
|
||||
|
||||
while (it) {
|
||||
// Process range
|
||||
hb_codepoint_t next_cp = (*it).first;
|
||||
hb_codepoint_t next_gid = (*it).second;
|
||||
if (next_cp != end_cp + 1) {
|
||||
// Current range is over, stop processing.
|
||||
break;
|
||||
}
|
||||
|
||||
if (next_gid == last_gid + 1) {
|
||||
// The current run continues.
|
||||
end_cp = next_cp;
|
||||
run_length++;
|
||||
last_gid = next_gid;
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// A new run is starting, decide if we want to commit the current run.
|
||||
int split_cost = (mode == FIRST_SUB_RANGE) ? 8 : 16;
|
||||
int run_cost = run_length * 2;
|
||||
if (run_cost >= split_cost) {
|
||||
commit_current_range(start_cp,
|
||||
prev_run_start_cp,
|
||||
run_start_cp,
|
||||
end_cp,
|
||||
delta,
|
||||
prev_delta,
|
||||
split_cost,
|
||||
range_writer);
|
||||
start_cp = next_cp;
|
||||
}
|
||||
|
||||
// Start the new run
|
||||
mode = FOLLOWING_SUB_RANGE;
|
||||
prev_run_start_cp = run_start_cp;
|
||||
run_start_cp = next_cp;
|
||||
end_cp = next_cp;
|
||||
prev_delta = delta;
|
||||
delta = next_gid - run_start_cp;
|
||||
run_length = 1;
|
||||
last_gid = next_gid;
|
||||
it++;
|
||||
}
|
||||
prev_endcp = _.first;
|
||||
|
||||
// Finalize range
|
||||
commit_current_range (start_cp,
|
||||
prev_run_start_cp,
|
||||
run_start_cp,
|
||||
end_cp,
|
||||
delta,
|
||||
prev_delta,
|
||||
8,
|
||||
range_writer);
|
||||
}
|
||||
|
||||
{
|
||||
// last endCode
|
||||
HBUINT16 endcode;
|
||||
endcode = prev_endcp;
|
||||
if (unlikely (!c->copy<HBUINT16> (endcode))) return nullptr;
|
||||
// There must be a final entry with end_code == 0xFFFF.
|
||||
if (prev_endcp != 0xFFFF)
|
||||
{
|
||||
HBUINT16 finalcode;
|
||||
finalcode = 0xFFFF;
|
||||
if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr;
|
||||
if (likely (end_cp != 0xFFFF)) {
|
||||
range_writer (0xFFFF, 0xFFFF, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes the current range as either one or two ranges depending on what is most efficient.
|
||||
*/
|
||||
template<typename Writer>
|
||||
void commit_current_range (hb_codepoint_t start,
|
||||
hb_codepoint_t prev_run_start,
|
||||
hb_codepoint_t run_start,
|
||||
hb_codepoint_t end,
|
||||
int run_delta,
|
||||
int previous_run_delta,
|
||||
int split_cost,
|
||||
Writer& range_writer) {
|
||||
bool should_split = false;
|
||||
if (start < run_start && run_start < end) {
|
||||
int run_cost = (end - run_start + 1) * 2;
|
||||
if (run_cost >= split_cost) {
|
||||
should_split = true;
|
||||
}
|
||||
}
|
||||
|
||||
return endCode;
|
||||
// TODO(grieger): handle case where delta is legitimately 0, mark range offset array instead?
|
||||
if (should_split) {
|
||||
if (start == prev_run_start)
|
||||
range_writer (start, run_start - 1, previous_run_delta);
|
||||
else
|
||||
range_writer (start, run_start - 1, 0);
|
||||
range_writer (run_start, end, run_delta);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (start == run_start) {
|
||||
// Range is only a run
|
||||
range_writer (start, end, run_delta);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write only a single non-run range.
|
||||
range_writer (start, end, 0);
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
HBUINT16* serialize_startcode_array (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{
|
||||
HBUINT16 *startCode = c->start_embed<HBUINT16> ();
|
||||
hb_codepoint_t prev_cp = 0xFFFF;
|
||||
unsigned serialize_find_segcount (Iterator it) {
|
||||
struct Counter {
|
||||
unsigned segcount = 0;
|
||||
|
||||
for (const auto& _ : +it)
|
||||
{
|
||||
if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
|
||||
{
|
||||
HBUINT16 start_code;
|
||||
start_code = _.first;
|
||||
c->copy<HBUINT16> (start_code);
|
||||
void operator() (hb_codepoint_t start,
|
||||
hb_codepoint_t end,
|
||||
int delta) {
|
||||
segcount++;
|
||||
}
|
||||
} counter;
|
||||
|
||||
prev_cp = _.first;
|
||||
}
|
||||
|
||||
// There must be a final entry with end_code == 0xFFFF.
|
||||
if (it.len () == 0 || prev_cp != 0xFFFF)
|
||||
{
|
||||
HBUINT16 finalcode;
|
||||
finalcode = 0xFFFF;
|
||||
if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr;
|
||||
}
|
||||
|
||||
return startCode;
|
||||
to_ranges (+it, counter);
|
||||
return counter.segcount;
|
||||
}
|
||||
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
HBINT16* serialize_idDelta_array (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
HBUINT16 *endCode,
|
||||
HBUINT16 *startCode,
|
||||
unsigned segcount)
|
||||
bool serialize_start_end_delta_arrays (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
int segcount)
|
||||
{
|
||||
unsigned i = 0;
|
||||
hb_codepoint_t last_gid = 0, start_gid = 0, last_cp = 0xFFFF;
|
||||
bool use_delta = true;
|
||||
struct Writer {
|
||||
hb_serialize_context_t *serializer_;
|
||||
HBUINT16* end_code_;
|
||||
HBUINT16* start_code_;
|
||||
HBINT16* id_delta_;
|
||||
int index_;
|
||||
|
||||
HBINT16 *idDelta = c->start_embed<HBINT16> ();
|
||||
if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size)
|
||||
return nullptr;
|
||||
|
||||
for (const auto& _ : +it)
|
||||
{
|
||||
if (_.first == startCode[i])
|
||||
{
|
||||
use_delta = true;
|
||||
start_gid = _.second;
|
||||
Writer(hb_serialize_context_t *serializer)
|
||||
: serializer_(serializer),
|
||||
end_code_(nullptr),
|
||||
start_code_(nullptr),
|
||||
id_delta_(nullptr),
|
||||
index_ (0) {}
|
||||
void operator() (hb_codepoint_t start,
|
||||
hb_codepoint_t end,
|
||||
int delta) {
|
||||
start_code_[index_] = start;
|
||||
end_code_[index_] = end;
|
||||
id_delta_[index_] = delta;
|
||||
index_++;
|
||||
}
|
||||
else if (_.second != last_gid + 1) use_delta = false;
|
||||
} writer(c);
|
||||
|
||||
if (_.first == endCode[i])
|
||||
{
|
||||
HBINT16 delta;
|
||||
if (use_delta) delta = (int)start_gid - (int)startCode[i];
|
||||
else delta = 0;
|
||||
c->copy<HBINT16> (delta);
|
||||
writer.end_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
|
||||
c->allocate_size<HBUINT16> (2); // padding
|
||||
writer.start_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
|
||||
writer.id_delta_ = c->allocate_size<HBINT16> (HBINT16::static_size * segcount);
|
||||
|
||||
i++;
|
||||
}
|
||||
if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false;
|
||||
|
||||
last_gid = _.second;
|
||||
last_cp = _.first;
|
||||
}
|
||||
|
||||
if (it.len () == 0 || last_cp != 0xFFFF)
|
||||
{
|
||||
HBINT16 delta;
|
||||
delta = 1;
|
||||
if (unlikely (!c->copy<HBINT16> (delta))) return nullptr;
|
||||
}
|
||||
|
||||
return idDelta;
|
||||
to_ranges (+it, writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
|
|
@ -212,29 +290,24 @@ struct CmapSubtableFormat4
|
|||
HBINT16 *idDelta,
|
||||
unsigned segcount)
|
||||
{
|
||||
hb_hashmap_t<hb_codepoint_t, hb_codepoint_t> cp_to_gid;
|
||||
+ it | hb_sink (cp_to_gid);
|
||||
|
||||
HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
|
||||
if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
|
||||
if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
|
||||
|
||||
+ hb_range (segcount)
|
||||
| hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; })
|
||||
| hb_apply ([&] (const unsigned i)
|
||||
{
|
||||
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
|
||||
|
||||
+ it
|
||||
| hb_filter ([&] (const hb_item_type<Iterator> _) { return _.first >= startCode[i] && _.first <= endCode[i]; })
|
||||
| hb_apply ([&] (const hb_item_type<Iterator> _)
|
||||
{
|
||||
HBUINT16 glyID;
|
||||
glyID = _.second;
|
||||
c->copy<HBUINT16> (glyID);
|
||||
})
|
||||
;
|
||||
|
||||
|
||||
})
|
||||
;
|
||||
for (unsigned i : + hb_range (segcount)
|
||||
| hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
|
||||
{
|
||||
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
|
||||
for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++)
|
||||
{
|
||||
HBUINT16 gid;
|
||||
gid = cp_to_gid[cp];
|
||||
c->copy<HBUINT16> (gid);
|
||||
}
|
||||
}
|
||||
|
||||
return idRangeOffset;
|
||||
}
|
||||
|
|
@ -253,32 +326,32 @@ struct CmapSubtableFormat4
|
|||
if (format4_iter.len () == 0) return;
|
||||
|
||||
unsigned table_initpos = c->length ();
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
if (unlikely (!c->extend_min (this))) return;
|
||||
this->format = 4;
|
||||
|
||||
//serialize endCode[]
|
||||
HBUINT16 *endCode = serialize_endcode_array (c, format4_iter);
|
||||
if (unlikely (!endCode)) return;
|
||||
//serialize endCode[], startCode[], idDelta[]
|
||||
HBUINT16* endCode = c->start_embed<HBUINT16> ();
|
||||
unsigned segcount = serialize_find_segcount (format4_iter);
|
||||
if (unlikely (!serialize_start_end_delta_arrays (c, format4_iter, segcount)))
|
||||
return;
|
||||
|
||||
unsigned segcount = (c->length () - min_size) / HBUINT16::static_size;
|
||||
|
||||
// 2 bytes of padding.
|
||||
if (unlikely (!c->allocate_size<HBUINT16> (HBUINT16::static_size))) return; // 2 bytes of padding.
|
||||
|
||||
// serialize startCode[]
|
||||
HBUINT16 *startCode = serialize_startcode_array (c, format4_iter);
|
||||
if (unlikely (!startCode)) return;
|
||||
|
||||
//serialize idDelta[]
|
||||
HBINT16 *idDelta = serialize_idDelta_array (c, format4_iter, endCode, startCode, segcount);
|
||||
if (unlikely (!idDelta)) return;
|
||||
HBUINT16 *startCode = endCode + segcount + 1;
|
||||
HBINT16 *idDelta = ((HBINT16*)startCode) + segcount;
|
||||
|
||||
HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
|
||||
if (unlikely (!c->check_success (idRangeOffset))) return;
|
||||
|
||||
if (unlikely (!c->check_assign(this->length,
|
||||
c->length () - table_initpos,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
|
||||
this->length = c->length () - table_initpos;
|
||||
if ((long long) this->length != (long long) c->length () - table_initpos)
|
||||
{
|
||||
// Length overflowed. Discard the current object before setting the error condition, otherwise
|
||||
// discard is a noop which prevents the higher level code from reverting the serializer to the
|
||||
// pre-error state in cmap4 overflow handling code.
|
||||
c->pop_discard ();
|
||||
c->err (HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
return;
|
||||
}
|
||||
|
||||
this->segCountX2 = segcount * 2;
|
||||
this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1;
|
||||
this->searchRange = 2 * (1u << this->entrySelector);
|
||||
|
|
@ -287,6 +360,11 @@ struct CmapSubtableFormat4
|
|||
: 0;
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
accelerator_t () {}
|
||||
|
|
@ -549,6 +627,12 @@ struct CmapSubtableTrimmed
|
|||
*glyph = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
hb_codepoint_t start = startCharCode;
|
||||
|
|
@ -584,7 +668,7 @@ struct CmapSubtableTrimmed
|
|||
UINT length; /* Byte length of this subtable. */
|
||||
UINT language; /* Ignore. */
|
||||
UINT startCharCode; /* First character code covered. */
|
||||
ArrayOf<HBGlyphID, UINT>
|
||||
ArrayOf<HBGlyphID16, UINT>
|
||||
glyphIdArray; /* Array of glyph index values for character
|
||||
* codes in the range. */
|
||||
public:
|
||||
|
|
@ -608,6 +692,11 @@ struct CmapSubtableLongSegmented
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
|
||||
{
|
||||
for (unsigned int i = 0; i < this->groups.len; i++)
|
||||
|
|
@ -693,7 +782,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
|
|||
{
|
||||
if (it.len () == 0) return;
|
||||
unsigned table_initpos = c->length ();
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
if (unlikely (!c->extend_min (this))) return;
|
||||
|
||||
hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
|
||||
hb_codepoint_t glyphID = 0;
|
||||
|
|
@ -875,7 +964,7 @@ struct UVSMapping
|
|||
}
|
||||
|
||||
HBUINT24 unicodeValue; /* Base Unicode value of the UVS */
|
||||
HBGlyphID glyphID; /* Glyph ID of the UVS */
|
||||
HBGlyphID16 glyphID; /* Glyph ID of the UVS */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (5);
|
||||
};
|
||||
|
|
@ -1077,7 +1166,7 @@ struct CmapSubtableFormat14
|
|||
unsigned table_initpos = c->length ();
|
||||
const char* init_tail = c->tail;
|
||||
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
if (unlikely (!c->extend_min (this))) return;
|
||||
this->format = 14;
|
||||
|
||||
auto src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (base);
|
||||
|
|
@ -1238,6 +1327,20 @@ struct CmapSubtable
|
|||
}
|
||||
}
|
||||
|
||||
unsigned get_language () const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 0: return u.format0 .get_language ();
|
||||
case 4: return u.format4 .get_language ();
|
||||
case 6: return u.format6 .get_language ();
|
||||
case 10: return u.format10.get_language ();
|
||||
case 12: return u.format12.get_language ();
|
||||
case 13: return u.format13.get_language ();
|
||||
case 14:
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
|
|
@ -1353,60 +1456,112 @@ struct cmap
|
|||
|
||||
template<typename Iterator, typename EncodingRecIter,
|
||||
hb_requires (hb_is_iterator (EncodingRecIter))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
EncodingRecIter encodingrec_iter,
|
||||
const void *base,
|
||||
const hb_subset_plan_t *plan)
|
||||
const hb_subset_plan_t *plan,
|
||||
bool drop_format_4 = false)
|
||||
{
|
||||
if (unlikely (!c->extend_min ((*this)))) return;
|
||||
if (unlikely (!c->extend_min ((*this)))) return false;
|
||||
this->version = 0;
|
||||
|
||||
unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
|
||||
auto snap = c->snapshot ();
|
||||
|
||||
for (const EncodingRecord& _ : encodingrec_iter)
|
||||
{
|
||||
if (c->in_error ())
|
||||
return false;
|
||||
|
||||
unsigned format = (base+_.subtable).u.format;
|
||||
if (!plan->glyphs_requested->is_empty ())
|
||||
if (format != 4 && format != 12 && format != 14) continue;
|
||||
|
||||
hb_set_t unicodes_set;
|
||||
(base+_.subtable).collect_unicodes (&unicodes_set);
|
||||
|
||||
if (!drop_format_4 && format == 4)
|
||||
{
|
||||
hb_set_t unicodes_set;
|
||||
hb_map_t cp_glyphid_map;
|
||||
(base+_.subtable).collect_mapping (&unicodes_set, &cp_glyphid_map);
|
||||
|
||||
auto table_iter =
|
||||
+ hb_zip (unicodes_set.iter(), unicodes_set.iter() | hb_map(cp_glyphid_map))
|
||||
| hb_filter (plan->_glyphset, hb_second)
|
||||
| hb_filter ([plan] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& p)
|
||||
{
|
||||
return plan->unicodes->has (p.first) ||
|
||||
plan->glyphs_requested->has (p.second);
|
||||
})
|
||||
| hb_map ([plan] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& p_org)
|
||||
{
|
||||
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (p_org.first, plan->glyph_map->get(p_org.second));
|
||||
})
|
||||
;
|
||||
|
||||
if (format == 4) c->copy (_, table_iter, 4u, base, plan, &format4objidx);
|
||||
else if (format == 12) c->copy (_, table_iter, 12u, base, plan, &format12objidx);
|
||||
else if (format == 14) c->copy (_, table_iter, 14u, base, plan, &format14objidx);
|
||||
c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
|
||||
if (c->in_error () && c->only_overflow ())
|
||||
{
|
||||
// cmap4 overflowed, reset and retry serialization without format 4 subtables.
|
||||
c->revert (snap);
|
||||
return serialize (c, it,
|
||||
encodingrec_iter,
|
||||
base,
|
||||
plan,
|
||||
true);
|
||||
}
|
||||
}
|
||||
/* when --gids option is not used, we iterate input unicodes instead of
|
||||
* all codepoints in each subtable, which is more efficient */
|
||||
else
|
||||
|
||||
else if (format == 12)
|
||||
{
|
||||
hb_set_t unicodes_set;
|
||||
(base+_.subtable).collect_unicodes (&unicodes_set);
|
||||
|
||||
if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
|
||||
else if (format == 12) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
|
||||
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
|
||||
if (_can_drop (_, unicodes_set, base, + it | hb_map (hb_first), encodingrec_iter)) continue;
|
||||
c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
|
||||
}
|
||||
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
|
||||
}
|
||||
|
||||
c->check_assign(this->encodingRecord.len,
|
||||
(c->length () - cmap::min_size)/EncodingRecord::static_size,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
|
||||
// Fail if format 4 was dropped and there is no cmap12.
|
||||
return !drop_format_4 || format12objidx;
|
||||
}
|
||||
|
||||
template<typename Iterator, typename EncodingRecordIterator,
|
||||
hb_requires (hb_is_iterator (Iterator)),
|
||||
hb_requires (hb_is_iterator (EncodingRecordIterator))>
|
||||
bool _can_drop (const EncodingRecord& cmap12,
|
||||
const hb_set_t& cmap12_unicodes,
|
||||
const void* base,
|
||||
Iterator subset_unicodes,
|
||||
EncodingRecordIterator encoding_records)
|
||||
{
|
||||
for (auto cp : + subset_unicodes | hb_filter (cmap12_unicodes))
|
||||
{
|
||||
if (cp >= 0x10000) return false;
|
||||
}
|
||||
|
||||
unsigned target_platform;
|
||||
unsigned target_encoding;
|
||||
unsigned target_language = (base+cmap12.subtable).get_language ();
|
||||
|
||||
if (cmap12.platformID == 0 && cmap12.encodingID == 4)
|
||||
{
|
||||
target_platform = 0;
|
||||
target_encoding = 3;
|
||||
} else if (cmap12.platformID == 3 && cmap12.encodingID == 10) {
|
||||
target_platform = 3;
|
||||
target_encoding = 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& _ : encoding_records)
|
||||
{
|
||||
if (_.platformID != target_platform
|
||||
|| _.encodingID != target_encoding
|
||||
|| (base+_.subtable).get_language() != target_language)
|
||||
continue;
|
||||
|
||||
hb_set_t sibling_unicodes;
|
||||
(base+_.subtable).collect_unicodes (&sibling_unicodes);
|
||||
|
||||
auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes);
|
||||
auto sibling = + subset_unicodes | hb_filter (sibling_unicodes);
|
||||
for (; cmap12 && sibling; cmap12++, sibling++)
|
||||
{
|
||||
unsigned a = *cmap12;
|
||||
unsigned b = *sibling;
|
||||
if (a != b) return false;
|
||||
}
|
||||
|
||||
return !cmap12 && !sibling;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void closure_glyphs (const hb_set_t *unicodes,
|
||||
|
|
@ -1473,8 +1628,8 @@ struct cmap
|
|||
| hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
|
||||
{ return (_.second != HB_MAP_VALUE_INVALID); })
|
||||
;
|
||||
cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan);
|
||||
return_trace (true);
|
||||
|
||||
return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan));
|
||||
}
|
||||
|
||||
const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
|
||||
|
|
|
|||
|
|
@ -508,8 +508,8 @@ struct IndexSubtableRecord
|
|||
offset, length, format);
|
||||
}
|
||||
|
||||
HBGlyphID firstGlyphIndex;
|
||||
HBGlyphID lastGlyphIndex;
|
||||
HBGlyphID16 firstGlyphIndex;
|
||||
HBGlyphID16 lastGlyphIndex;
|
||||
Offset32To<IndexSubtable> offsetToSubtable;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
|
|
@ -679,8 +679,8 @@ struct BitmapSizeTable
|
|||
HBUINT32 colorRef;
|
||||
SBitLineMetrics horizontal;
|
||||
SBitLineMetrics vertical;
|
||||
HBGlyphID startGlyphIndex;
|
||||
HBGlyphID endGlyphIndex;
|
||||
HBGlyphID16 startGlyphIndex;
|
||||
HBGlyphID16 endGlyphIndex;
|
||||
HBUINT8 ppemX;
|
||||
HBUINT8 ppemY;
|
||||
HBUINT8 bitDepth;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -40,7 +40,7 @@ namespace OT {
|
|||
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 PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
|
|||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -83,8 +83,13 @@ struct CPALV1Tail
|
|||
auto *out = c->allocate_size<CPALV1Tail> (static_size);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
out->paletteFlagsZ = 0;
|
||||
if (paletteFlagsZ)
|
||||
out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
|
||||
out->paletteLabelsZ = 0;
|
||||
if (paletteLabelsZ)
|
||||
out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
|
||||
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
|
||||
if (colorLabelsZ)
|
||||
|
|
@ -119,6 +124,8 @@ struct CPALV1Tail
|
|||
}
|
||||
|
||||
protected:
|
||||
// TODO(garretrieger): these offsets can hold nulls so we should not be using non-null offsets
|
||||
// here. Currently they are needed since UnsizedArrayOf doesn't define null_size
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT32>>
|
||||
paletteFlagsZ; /* Offset from the beginning of CPAL table to
|
||||
* the Palette Type Array. Set to 0 if no array
|
||||
|
|
@ -234,7 +241,7 @@ struct CPAL
|
|||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
|
||||
out->version = version;
|
||||
out->numColors = retained_color_indices.get_population ();
|
||||
out->numPalettes = numPalettes;
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ struct SBIXStrike
|
|||
auto* out = c->serializer->start_embed<SBIXStrike> ();
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (unlikely (!c->serializer->extend (*out, num_output_glyphs + 1))) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false);
|
||||
out->ppem = ppem;
|
||||
out->resolution = resolution;
|
||||
HBUINT32 head;
|
||||
|
|
|
|||
|
|
@ -67,8 +67,11 @@ HB_OT_ACCELERATOR (OT, meta)
|
|||
#endif
|
||||
|
||||
/* Vertical layout. */
|
||||
#ifndef HB_NO_VERTICAL
|
||||
HB_OT_TABLE (OT, vhea)
|
||||
HB_OT_ACCELERATOR (OT, vmtx)
|
||||
HB_OT_TABLE (OT, VORG)
|
||||
#endif
|
||||
|
||||
/* TrueType outlines. */
|
||||
HB_OT_ACCELERATOR (OT, glyf)
|
||||
|
|
@ -77,7 +80,6 @@ HB_OT_ACCELERATOR (OT, glyf)
|
|||
#ifndef HB_NO_CFF
|
||||
HB_OT_ACCELERATOR (OT, cff1)
|
||||
HB_OT_ACCELERATOR (OT, cff2)
|
||||
HB_OT_TABLE (OT, VORG)
|
||||
#endif
|
||||
|
||||
/* OpenType variations. */
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
static void
|
||||
hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
||||
unsigned count,
|
||||
|
|
@ -137,7 +138,9 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
|||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_v_origin (hb_font_t *font,
|
||||
void *font_data,
|
||||
|
|
@ -150,14 +153,12 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
|
|||
|
||||
*x = font->get_glyph_h_advance (glyph) / 2;
|
||||
|
||||
#ifndef HB_NO_OT_FONT_CFF
|
||||
const OT::VORG &VORG = *ot_face->VORG;
|
||||
if (VORG.has_data ())
|
||||
{
|
||||
*y = font->em_scale_y (VORG.get_y_origin (glyph));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
hb_glyph_extents_t extents = {0};
|
||||
if (ot_face->glyf->get_extents (font, glyph, &extents))
|
||||
|
|
@ -174,6 +175,7 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
|
|||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_extents (hb_font_t *font,
|
||||
|
|
@ -242,6 +244,7 @@ hb_ot_get_font_h_extents (hb_font_t *font,
|
|||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
static hb_bool_t
|
||||
hb_ot_get_font_v_extents (hb_font_t *font,
|
||||
void *font_data HB_UNUSED,
|
||||
|
|
@ -252,28 +255,33 @@ hb_ot_get_font_v_extents (hb_font_t *font,
|
|||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_ot_funcs ();
|
||||
#endif
|
||||
|
||||
static inline void free_static_ot_funcs ();
|
||||
|
||||
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
|
||||
{
|
||||
static hb_font_funcs_t *create ()
|
||||
{
|
||||
hb_font_funcs_t *funcs = hb_font_funcs_create ();
|
||||
|
||||
hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
|
||||
hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
|
||||
hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
|
||||
|
||||
hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
|
||||
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
|
||||
//hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
|
||||
|
||||
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
|
||||
hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
|
||||
|
|
@ -281,21 +289,17 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
|
|||
|
||||
hb_font_funcs_make_immutable (funcs);
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_ot_funcs);
|
||||
#endif
|
||||
hb_atexit (free_static_ot_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_ot_funcs;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
static inline
|
||||
void free_static_ot_funcs ()
|
||||
{
|
||||
static_ot_funcs.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static hb_font_funcs_t *
|
||||
_hb_ot_get_font_funcs ()
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ namespace OT {
|
|||
*/
|
||||
#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
|
||||
|
||||
#ifndef HB_MAX_COMPOSITE_OPERATIONS
|
||||
#define HB_MAX_COMPOSITE_OPERATIONS 100000
|
||||
#endif
|
||||
|
||||
|
||||
struct loca
|
||||
{
|
||||
|
|
@ -89,22 +93,16 @@ struct glyf
|
|||
template<typename Iterator,
|
||||
hb_requires (hb_is_source_of (Iterator, unsigned int))>
|
||||
static bool
|
||||
_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets)
|
||||
_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
|
||||
{
|
||||
unsigned max_offset =
|
||||
+ padded_offsets
|
||||
| hb_reduce (hb_add, 0)
|
||||
;
|
||||
unsigned num_offsets = padded_offsets.len () + 1;
|
||||
bool use_short_loca = max_offset < 0x1FFFF;
|
||||
unsigned entry_size = use_short_loca ? 2 : 4;
|
||||
char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
|
||||
|
||||
if (unlikely (!loca_prime_data)) return false;
|
||||
|
||||
DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d "
|
||||
"max_offset %d size %d",
|
||||
entry_size, num_offsets, max_offset, entry_size * num_offsets);
|
||||
DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
|
||||
entry_size, num_offsets, entry_size * num_offsets);
|
||||
|
||||
if (use_short_loca)
|
||||
_write_loca (padded_offsets, 1, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
|
||||
|
|
@ -147,11 +145,12 @@ struct glyf
|
|||
template <typename Iterator>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
bool use_short_loca,
|
||||
const hb_subset_plan_t *plan)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
unsigned init_len = c->length ();
|
||||
for (const auto &_ : it) _.serialize (c, plan);
|
||||
for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
|
||||
|
||||
/* As a special case when all glyph in the font are empty, add a zero byte
|
||||
* to the table, so that OTS doesn’t reject it, and to make the table work
|
||||
|
|
@ -179,16 +178,28 @@ struct glyf
|
|||
hb_vector_t<SubsetGlyph> glyphs;
|
||||
_populate_subset_glyphs (c->plan, &glyphs);
|
||||
|
||||
glyf_prime->serialize (c->serializer, hb_iter (glyphs), c->plan);
|
||||
|
||||
auto padded_offsets =
|
||||
+ hb_iter (glyphs)
|
||||
| hb_map (&SubsetGlyph::padded_size)
|
||||
;
|
||||
|
||||
unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
|
||||
bool use_short_loca = max_offset < 0x1FFFF;
|
||||
|
||||
|
||||
glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
|
||||
if (!use_short_loca) {
|
||||
padded_offsets =
|
||||
+ hb_iter (glyphs)
|
||||
| hb_map (&SubsetGlyph::length)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
if (unlikely (c->serializer->in_error ())) return_trace (false);
|
||||
return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
|
||||
padded_offsets)));
|
||||
padded_offsets,
|
||||
use_short_loca)));
|
||||
}
|
||||
|
||||
template <typename SubsetGlyph>
|
||||
|
|
@ -209,13 +220,15 @@ struct glyf
|
|||
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
|
||||
return subset_glyph;
|
||||
|
||||
if (new_gid == 0 && !plan->notdef_outline)
|
||||
if (new_gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||
subset_glyph.source_glyph = Glyph ();
|
||||
else
|
||||
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
|
||||
if (plan->drop_hints) subset_glyph.drop_hints_bytes ();
|
||||
else subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
subset_glyph.drop_hints_bytes ();
|
||||
else
|
||||
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||
return subset_glyph;
|
||||
})
|
||||
| hb_sink (glyphs)
|
||||
|
|
@ -382,7 +395,7 @@ struct glyf
|
|||
|
||||
protected:
|
||||
HBUINT16 flags;
|
||||
HBGlyphID glyphIndex;
|
||||
HBGlyphID16 glyphIndex;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (4);
|
||||
};
|
||||
|
|
@ -391,9 +404,12 @@ struct glyf
|
|||
{
|
||||
typedef const CompositeGlyphChain *__item_t__;
|
||||
composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
|
||||
glyph (glyph_), current (current_)
|
||||
{ if (!check_range (current)) current = nullptr; }
|
||||
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr) {}
|
||||
glyph (glyph_), current (nullptr), current_size (0)
|
||||
{
|
||||
set_next (current_);
|
||||
}
|
||||
|
||||
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
|
||||
|
||||
const CompositeGlyphChain &__item__ () const { return *current; }
|
||||
bool __more__ () const { return current; }
|
||||
|
|
@ -401,23 +417,36 @@ struct glyf
|
|||
{
|
||||
if (!current->has_more ()) { current = nullptr; return; }
|
||||
|
||||
const CompositeGlyphChain *possible = &StructAfter<CompositeGlyphChain,
|
||||
CompositeGlyphChain> (*current);
|
||||
if (!check_range (possible)) { current = nullptr; return; }
|
||||
current = possible;
|
||||
set_next (&StructAtOffset<CompositeGlyphChain> (current, current_size));
|
||||
}
|
||||
bool operator != (const composite_iter_t& o) const
|
||||
{ return glyph != o.glyph || current != o.current; }
|
||||
|
||||
bool check_range (const CompositeGlyphChain *composite) const
|
||||
|
||||
void set_next (const CompositeGlyphChain *composite)
|
||||
{
|
||||
return glyph.check_range (composite, CompositeGlyphChain::min_size)
|
||||
&& glyph.check_range (composite, composite->get_size ());
|
||||
if (!glyph.check_range (composite, CompositeGlyphChain::min_size))
|
||||
{
|
||||
current = nullptr;
|
||||
current_size = 0;
|
||||
return;
|
||||
}
|
||||
unsigned size = composite->get_size ();
|
||||
if (!glyph.check_range (composite, size))
|
||||
{
|
||||
current = nullptr;
|
||||
current_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
current = composite;
|
||||
current_size = size;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_bytes_t glyph;
|
||||
__item_t__ current;
|
||||
unsigned current_size;
|
||||
};
|
||||
|
||||
enum phantom_point_index_t
|
||||
|
|
@ -503,8 +532,8 @@ struct glyf
|
|||
const Glyph trim_padding () const
|
||||
{
|
||||
/* based on FontTools _g_l_y_f.py::trim */
|
||||
const char *glyph = bytes.arrayZ;
|
||||
const char *glyph_end = glyph + bytes.length;
|
||||
const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
|
||||
const uint8_t *glyph_end = glyph + bytes.length;
|
||||
/* simple glyph w/contours, possibly trimmable */
|
||||
glyph += instruction_len_offset ();
|
||||
|
||||
|
|
@ -770,10 +799,23 @@ struct glyf
|
|||
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
||||
{
|
||||
for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
|
||||
int h_delta = (int) header->xMin - glyf_accelerator.hmtx->get_side_bearing (gid);
|
||||
int v_orig = (int) header->yMax + glyf_accelerator.vmtx->get_side_bearing (gid);
|
||||
int h_delta = (int) header->xMin -
|
||||
glyf_accelerator.hmtx->get_side_bearing (gid);
|
||||
int v_orig = (int) header->yMax +
|
||||
#ifndef HB_NO_VERTICAL
|
||||
glyf_accelerator.vmtx->get_side_bearing (gid)
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
;
|
||||
unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid);
|
||||
unsigned v_adv = glyf_accelerator.vmtx->get_advance (gid);
|
||||
unsigned v_adv =
|
||||
#ifndef HB_NO_VERTICAL
|
||||
glyf_accelerator.vmtx->get_advance (gid)
|
||||
#else
|
||||
- font->face->get_upem ()
|
||||
#endif
|
||||
;
|
||||
phantoms[PHANTOM_LEFT].x = h_delta;
|
||||
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
|
||||
phantoms[PHANTOM_TOP].y = v_orig;
|
||||
|
|
@ -888,7 +930,9 @@ struct glyf
|
|||
gvar = nullptr;
|
||||
#endif
|
||||
hmtx = nullptr;
|
||||
#ifndef HB_NO_VERTICAL
|
||||
vmtx = nullptr;
|
||||
#endif
|
||||
face = face_;
|
||||
const OT::head &head = *face->table.head;
|
||||
if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
|
||||
|
|
@ -902,7 +946,9 @@ struct glyf
|
|||
gvar = face->table.gvar;
|
||||
#endif
|
||||
hmtx = face->table.hmtx;
|
||||
#ifndef HB_NO_VERTICAL
|
||||
vmtx = face->table.vmtx;
|
||||
#endif
|
||||
|
||||
num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
|
||||
num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
|
||||
|
|
@ -1015,7 +1061,11 @@ struct glyf
|
|||
success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
|
||||
|
||||
if (unlikely (!success))
|
||||
return is_vertical ? vmtx->get_advance (gid) : hmtx->get_advance (gid);
|
||||
return
|
||||
#ifndef HB_NO_VERTICAL
|
||||
is_vertical ? vmtx->get_advance (gid) :
|
||||
#endif
|
||||
hmtx->get_advance (gid);
|
||||
|
||||
float result = is_vertical
|
||||
? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y
|
||||
|
|
@ -1031,7 +1081,11 @@ struct glyf
|
|||
|
||||
contour_point_t phantoms[PHANTOM_COUNT];
|
||||
if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms))))
|
||||
return is_vertical ? vmtx->get_side_bearing (gid) : hmtx->get_side_bearing (gid);
|
||||
return
|
||||
#ifndef HB_NO_VERTICAL
|
||||
is_vertical ? vmtx->get_side_bearing (gid) :
|
||||
#endif
|
||||
hmtx->get_side_bearing (gid);
|
||||
|
||||
return is_vertical
|
||||
? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
|
||||
|
|
@ -1079,18 +1133,28 @@ struct glyf
|
|||
return needs_padding_removal ? glyph.trim_padding () : glyph;
|
||||
}
|
||||
|
||||
void
|
||||
add_gid_and_children (hb_codepoint_t gid, hb_set_t *gids_to_retain,
|
||||
unsigned int depth = 0) const
|
||||
unsigned
|
||||
add_gid_and_children (hb_codepoint_t gid,
|
||||
hb_set_t *gids_to_retain,
|
||||
unsigned depth = 0,
|
||||
unsigned operation_count = 0) const
|
||||
{
|
||||
if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return;
|
||||
if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
|
||||
if (unlikely (operation_count++ > HB_MAX_COMPOSITE_OPERATIONS)) return operation_count;
|
||||
/* Check if is already visited */
|
||||
if (gids_to_retain->has (gid)) return;
|
||||
if (gids_to_retain->has (gid)) return operation_count;
|
||||
|
||||
gids_to_retain->add (gid);
|
||||
|
||||
for (auto &item : glyph_for_gid (gid).get_composite_iterator ())
|
||||
add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth);
|
||||
auto it = glyph_for_gid (gid).get_composite_iterator ();
|
||||
while (it)
|
||||
{
|
||||
auto item = *(it++);
|
||||
operation_count =
|
||||
add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
|
||||
}
|
||||
|
||||
return operation_count;
|
||||
}
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
|
|
@ -1218,7 +1282,9 @@ struct glyf
|
|||
const gvar_accelerator_t *gvar;
|
||||
#endif
|
||||
const hmtx_accelerator_t *hmtx;
|
||||
#ifndef HB_NO_VERTICAL
|
||||
const vmtx_accelerator_t *vmtx;
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool short_offset;
|
||||
|
|
@ -1237,13 +1303,14 @@ struct glyf
|
|||
hb_bytes_t dest_end; /* region of source_glyph to copy second */
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
bool use_short_loca,
|
||||
const hb_subset_plan_t *plan) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
hb_bytes_t dest_glyph = dest_start.copy (c);
|
||||
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
|
||||
unsigned int pad_length = padding ();
|
||||
unsigned int pad_length = use_short_loca ? padding () : 0;
|
||||
DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
|
||||
|
||||
HBUINT8 pad;
|
||||
|
|
@ -1264,9 +1331,10 @@ struct glyf
|
|||
const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
|
||||
}
|
||||
|
||||
if (plan->drop_hints) Glyph (dest_glyph).drop_hints ();
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
Glyph (dest_glyph).drop_hints ();
|
||||
|
||||
if (plan->overlaps_flag)
|
||||
if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
|
||||
Glyph (dest_glyph).set_overlaps_flag ();
|
||||
|
||||
return_trace (true);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ struct DeviceRecord
|
|||
|
||||
unsigned length = it.len ();
|
||||
|
||||
if (unlikely (!c->extend (*this, length))) return_trace (false);
|
||||
if (unlikely (!c->extend (this, length))) return_trace (false);
|
||||
|
||||
this->pixelSize = pixelSize;
|
||||
this->maxWidth =
|
||||
|
|
|
|||
|
|
@ -72,12 +72,14 @@ struct head
|
|||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -165,7 +165,14 @@ struct hmtxvmtx
|
|||
{
|
||||
default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
|
||||
|
||||
num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics;
|
||||
num_advances = T::is_horizontal ?
|
||||
face->table.hhea->numberOfLongMetrics :
|
||||
#ifndef HB_NO_VERTICAL
|
||||
face->table.vhea->numberOfLongMetrics
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
;
|
||||
|
||||
table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
|
||||
|
||||
|
|
|
|||
|
|
@ -134,11 +134,11 @@ struct KernSubTable
|
|||
switch (subtable_type) {
|
||||
case 0: return_trace (c->dispatch (u.format0));
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
case 1: return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward<Ts> (ds)...) : c->default_return_value ());
|
||||
case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
|
||||
#endif
|
||||
case 2: return_trace (c->dispatch (u.format2));
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
case 3: return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward<Ts> (ds)...) : c->default_return_value ());
|
||||
case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
|
||||
#endif
|
||||
default: return_trace (c->default_return_value ());
|
||||
}
|
||||
|
|
@ -325,9 +325,9 @@ struct kern
|
|||
unsigned int subtable_type = get_type ();
|
||||
TRACE_DISPATCH (this, subtable_type);
|
||||
switch (subtable_type) {
|
||||
case 0: return_trace (c->dispatch (u.ot, hb_forward<Ts> (ds)...));
|
||||
case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
case 1: return_trace (c->dispatch (u.aat, hb_forward<Ts> (ds)...));
|
||||
case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default: return_trace (c->default_return_value ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ struct BaseCoordFormat2
|
|||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
FWORD coordinate; /* X or Y value, in design units */
|
||||
HBGlyphID referenceGlyph; /* Glyph ID of control glyph */
|
||||
HBGlyphID16 referenceGlyph; /* Glyph ID of control glyph */
|
||||
HBUINT16 coordPoint; /* Index of contour point on the
|
||||
* reference glyph */
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@
|
|||
#define HB_MAX_FEATURE_INDICES 1500
|
||||
#endif
|
||||
|
||||
#ifndef HB_MAX_LOOKUP_INDICES
|
||||
#define HB_MAX_LOOKUP_INDICES 20000
|
||||
#ifndef HB_MAX_LOOKUP_VISIT_COUNT
|
||||
#define HB_MAX_LOOKUP_VISIT_COUNT 35000
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ static inline void ClassDef_serialize (hb_serialize_context_t *c,
|
|||
|
||||
static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
|
||||
const hb_map_t &gid_klass_map,
|
||||
hb_sorted_vector_t<HBGlyphID> &glyphs,
|
||||
hb_sorted_vector_t<HBGlyphID16> &glyphs,
|
||||
const hb_set_t &klasses,
|
||||
bool use_class_zero,
|
||||
hb_map_t *klass_map /*INOUT*/);
|
||||
|
|
@ -98,7 +98,7 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
|
|||
struct hb_prune_langsys_context_t
|
||||
{
|
||||
hb_prune_langsys_context_t (const void *table_,
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_,
|
||||
hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
|
||||
const hb_map_t *duplicate_feature_map_,
|
||||
hb_set_t *new_collected_feature_indexes_)
|
||||
:table (table_),
|
||||
|
|
@ -137,7 +137,7 @@ struct hb_prune_langsys_context_t
|
|||
|
||||
public:
|
||||
const void *table;
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map;
|
||||
hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
|
||||
const hb_map_t *duplicate_feature_map;
|
||||
hb_set_t *new_feature_indexes;
|
||||
|
||||
|
|
@ -173,20 +173,20 @@ struct hb_subset_layout_context_t :
|
|||
bool visitLookupIndex()
|
||||
{
|
||||
lookup_index_count++;
|
||||
return lookup_index_count < HB_MAX_LOOKUP_INDICES;
|
||||
return lookup_index_count < HB_MAX_LOOKUP_VISIT_COUNT;
|
||||
}
|
||||
|
||||
hb_subset_context_t *subset_context;
|
||||
const hb_tag_t table_tag;
|
||||
const hb_map_t *lookup_index_map;
|
||||
const hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map;
|
||||
const hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
|
||||
const hb_map_t *feature_index_map;
|
||||
unsigned cur_script_index;
|
||||
|
||||
hb_subset_layout_context_t (hb_subset_context_t *c_,
|
||||
hb_tag_t tag_,
|
||||
hb_map_t *lookup_map_,
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map_,
|
||||
hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
|
||||
hb_map_t *feature_index_map_) :
|
||||
subset_context (c_),
|
||||
table_tag (tag_),
|
||||
|
|
@ -237,9 +237,9 @@ struct subset_offset_array_t
|
|||
template <typename T>
|
||||
bool operator () (T&& offset)
|
||||
{
|
||||
auto snap = subset_context->serializer->snapshot ();
|
||||
auto *o = out.serialize_append (subset_context->serializer);
|
||||
if (unlikely (!o)) return false;
|
||||
auto snap = subset_context->serializer->snapshot ();
|
||||
bool ret = o->serialize_subset (subset_context, offset, base);
|
||||
if (!ret)
|
||||
{
|
||||
|
|
@ -268,9 +268,9 @@ struct subset_offset_array_arg_t
|
|||
template <typename T>
|
||||
bool operator () (T&& offset)
|
||||
{
|
||||
auto snap = subset_context->serializer->snapshot ();
|
||||
auto *o = out.serialize_append (subset_context->serializer);
|
||||
if (unlikely (!o)) return false;
|
||||
auto snap = subset_context->serializer->snapshot ();
|
||||
bool ret = o->serialize_subset (subset_context, offset, base, arg);
|
||||
if (!ret)
|
||||
{
|
||||
|
|
@ -346,6 +346,43 @@ struct
|
|||
}
|
||||
HB_FUNCOBJ (subset_record_array);
|
||||
|
||||
|
||||
template<typename OutputArray>
|
||||
struct serialize_math_record_array_t
|
||||
{
|
||||
serialize_math_record_array_t (hb_serialize_context_t *serialize_context_,
|
||||
OutputArray& out_,
|
||||
const void *base_) : serialize_context (serialize_context_),
|
||||
out (out_), base (base_) {}
|
||||
|
||||
template <typename T>
|
||||
bool operator () (T&& record)
|
||||
{
|
||||
if (!serialize_context->copy (record, base)) return false;
|
||||
out.len++;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_serialize_context_t *serialize_context;
|
||||
OutputArray &out;
|
||||
const void *base;
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper to serialize an array of MATH records.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
template<typename OutputArray>
|
||||
serialize_math_record_array_t<OutputArray>
|
||||
operator () (hb_serialize_context_t *serialize_context, OutputArray& out,
|
||||
const void *base) const
|
||||
{ return serialize_math_record_array_t<OutputArray> (serialize_context, out, base); }
|
||||
|
||||
}
|
||||
HB_FUNCOBJ (serialize_math_record_array);
|
||||
|
||||
/*
|
||||
*
|
||||
* OpenType Layout Common Table Formats
|
||||
|
|
@ -415,7 +452,7 @@ struct RecordArrayOf : SortedArray16Of<Record<Type>>
|
|||
}
|
||||
bool find_index (hb_tag_t tag, unsigned int *index) const
|
||||
{
|
||||
return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -508,8 +545,8 @@ struct RangeRecord
|
|||
bool collect_coverage (set_t *glyphs) const
|
||||
{ return glyphs->add_range (first, last); }
|
||||
|
||||
HBGlyphID first; /* First GlyphID in the range */
|
||||
HBGlyphID last; /* Last GlyphID in the range */
|
||||
HBGlyphID16 first; /* First GlyphID in the range */
|
||||
HBGlyphID16 last; /* Last GlyphID in the range */
|
||||
HBUINT16 value; /* Value */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
|
|
@ -1249,7 +1286,7 @@ struct Lookup
|
|||
TRACE_DISPATCH (this, lookup_type);
|
||||
unsigned int count = get_subtable_count ();
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, hb_forward<Ts> (ds)...);
|
||||
typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, std::forward<Ts> (ds)...);
|
||||
if (c->stop_sublookup_iteration (r))
|
||||
return_trace (r);
|
||||
}
|
||||
|
|
@ -1262,13 +1299,13 @@ struct Lookup
|
|||
unsigned int num_subtables)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
lookupType = lookup_type;
|
||||
lookupFlag = lookup_props & 0xFFFFu;
|
||||
if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
|
||||
if (lookupFlag & LookupFlag::UseMarkFilteringSet)
|
||||
{
|
||||
if (unlikely (!c->extend (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend (this))) return_trace (false);
|
||||
HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
|
||||
markFilteringSet = lookup_props >> 16;
|
||||
}
|
||||
|
|
@ -1299,7 +1336,7 @@ struct Lookup
|
|||
outMarkFilteringSet = markFilteringSet;
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
return_trace (out->subTable.len);
|
||||
}
|
||||
|
||||
template <typename TSubTable>
|
||||
|
|
@ -1320,7 +1357,7 @@ struct Lookup
|
|||
if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
|
||||
if (unlikely (get_type () == TSubTable::Extension && subtables && !c->get_edit_count ()))
|
||||
{
|
||||
/* The spec says all subtables of an Extension lookup should
|
||||
* have the same type, which shall not be the Extension type
|
||||
|
|
@ -1393,7 +1430,7 @@ struct CoverageFormat1
|
|||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
unsigned int i;
|
||||
glyphArray.bfind (glyph_id, &i, HB_BFIND_NOT_FOUND_STORE, NOT_COVERED);
|
||||
glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -1454,7 +1491,7 @@ struct CoverageFormat1
|
|||
|
||||
protected:
|
||||
HBUINT16 coverageFormat; /* Format identifier--format = 1 */
|
||||
SortedArray16Of<HBGlyphID>
|
||||
SortedArray16Of<HBGlyphID16>
|
||||
glyphArray; /* Array of GlyphIDs--in numerical order */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, glyphArray);
|
||||
|
|
@ -1478,7 +1515,7 @@ struct CoverageFormat2
|
|||
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
if (unlikely (!glyphs))
|
||||
{
|
||||
|
|
@ -1657,7 +1694,7 @@ struct Coverage
|
|||
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
unsigned count = 0;
|
||||
unsigned num_ranges = 0;
|
||||
|
|
@ -1832,7 +1869,7 @@ Coverage_serialize (hb_serialize_context_t *c,
|
|||
|
||||
static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
|
||||
const hb_map_t &gid_klass_map,
|
||||
hb_sorted_vector_t<HBGlyphID> &glyphs,
|
||||
hb_sorted_vector_t<HBGlyphID16> &glyphs,
|
||||
const hb_set_t &klasses,
|
||||
bool use_class_zero,
|
||||
hb_map_t *klass_map /*INOUT*/)
|
||||
|
|
@ -1859,7 +1896,7 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
|
|||
|
||||
auto it =
|
||||
+ glyphs.iter ()
|
||||
| hb_map_retains_sorting ([&] (const HBGlyphID& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
|
||||
| hb_map_retains_sorting ([&] (const HBGlyphID16& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
|
||||
{
|
||||
unsigned new_klass = klass_map->get (gid_klass_map[gid]);
|
||||
return hb_pair ((hb_codepoint_t)gid, new_klass);
|
||||
|
|
@ -1890,7 +1927,7 @@ struct ClassDefFormat1
|
|||
Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
if (unlikely (!it))
|
||||
{
|
||||
|
|
@ -1926,7 +1963,7 @@ struct ClassDefFormat1
|
|||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
hb_sorted_vector_t<HBGlyphID> glyphs;
|
||||
hb_sorted_vector_t<HBGlyphID16> glyphs;
|
||||
hb_set_t orig_klasses;
|
||||
hb_map_t gid_org_klass_map;
|
||||
|
||||
|
|
@ -2044,9 +2081,25 @@ struct ClassDefFormat1
|
|||
intersect_glyphs->add (startGlyph + i);
|
||||
}
|
||||
|
||||
void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
|
||||
{
|
||||
if (glyphs->is_empty ()) return;
|
||||
hb_codepoint_t end_glyph = startGlyph + classValue.len - 1;
|
||||
if (glyphs->get_min () < startGlyph ||
|
||||
glyphs->get_max () > end_glyph)
|
||||
intersect_classes->add (0);
|
||||
|
||||
for (const auto& _ : + hb_enumerate (classValue))
|
||||
{
|
||||
hb_codepoint_t g = startGlyph + _.first;
|
||||
if (glyphs->has (g))
|
||||
intersect_classes->add (_.second);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 classFormat; /* Format identifier--format = 1 */
|
||||
HBGlyphID startGlyph; /* First GlyphID of the classValueArray */
|
||||
HBGlyphID16 startGlyph; /* First GlyphID of the classValueArray */
|
||||
Array16Of<HBUINT16>
|
||||
classValue; /* Array of Class Values--one per GlyphID */
|
||||
public:
|
||||
|
|
@ -2069,7 +2122,7 @@ struct ClassDefFormat2
|
|||
Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
if (unlikely (!it))
|
||||
{
|
||||
|
|
@ -2128,7 +2181,7 @@ struct ClassDefFormat2
|
|||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
hb_sorted_vector_t<HBGlyphID> glyphs;
|
||||
hb_sorted_vector_t<HBGlyphID16> glyphs;
|
||||
hb_set_t orig_klasses;
|
||||
hb_map_t gid_org_klass_map;
|
||||
|
||||
|
|
@ -2277,6 +2330,31 @@ struct ClassDefFormat2
|
|||
}
|
||||
}
|
||||
|
||||
void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
|
||||
{
|
||||
if (glyphs->is_empty ()) return;
|
||||
|
||||
unsigned count = rangeRecord.len;
|
||||
hb_codepoint_t g = HB_SET_VALUE_INVALID;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (!hb_set_next (glyphs, &g))
|
||||
break;
|
||||
if (g < rangeRecord[i].first)
|
||||
{
|
||||
intersect_classes->add (0);
|
||||
break;
|
||||
}
|
||||
g = rangeRecord[i].last;
|
||||
}
|
||||
if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
|
||||
intersect_classes->add (0);
|
||||
|
||||
for (const RangeRecord& record : rangeRecord.iter ())
|
||||
if (record.intersects (glyphs))
|
||||
intersect_classes->add (record.value);
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 classFormat; /* Format identifier--format = 2 */
|
||||
SortedArray16Of<RangeRecord>
|
||||
|
|
@ -2311,7 +2389,7 @@ struct ClassDef
|
|||
bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
auto it = + it_with_class_zero | hb_filter (hb_second);
|
||||
|
||||
|
|
@ -2429,6 +2507,16 @@ struct ClassDef
|
|||
}
|
||||
}
|
||||
|
||||
void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1: return u.format1.intersected_classes (glyphs, intersect_classes);
|
||||
case 2: return u.format2.intersected_classes (glyphs, intersect_classes);
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
|
|
@ -2516,19 +2604,19 @@ struct VarRegionList
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
|
||||
return_trace (c->check_struct (this) && axesZ.sanitize (c, axisCount * regionCount));
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_bimap_t ®ion_map)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
VarRegionList *out = c->allocate_min<VarRegionList> ();
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
axisCount = src->axisCount;
|
||||
regionCount = region_map.get_population ();
|
||||
if (unlikely (!c->allocate_size<VarRegionList> (get_size () - min_size))) return_trace (false);
|
||||
unsigned int region_count = src->get_region_count ();
|
||||
if (unlikely (hb_unsigned_mul_overflows (axisCount * regionCount,
|
||||
VarRegionAxis::static_size))) return_trace (false);
|
||||
if (unlikely (!c->extend (this))) return_trace (false);
|
||||
unsigned int region_count = src->regionCount;
|
||||
for (unsigned int r = 0; r < regionCount; r++)
|
||||
{
|
||||
unsigned int backward = region_map.backward (r);
|
||||
|
|
@ -2540,11 +2628,11 @@ struct VarRegionList
|
|||
}
|
||||
|
||||
unsigned int get_size () const { return min_size + VarRegionAxis::static_size * axisCount * regionCount; }
|
||||
unsigned int get_region_count () const { return regionCount; }
|
||||
|
||||
protected:
|
||||
public:
|
||||
HBUINT16 axisCount;
|
||||
HBUINT16 regionCount;
|
||||
HBUINT15 regionCount;
|
||||
protected:
|
||||
UnsizedArrayOf<VarRegionAxis>
|
||||
axesZ;
|
||||
public:
|
||||
|
|
@ -2560,7 +2648,10 @@ struct VarData
|
|||
{ return shortCount + regionIndices.len; }
|
||||
|
||||
unsigned int get_size () const
|
||||
{ return itemCount * get_row_size (); }
|
||||
{ return min_size
|
||||
- regionIndices.min_size + regionIndices.get_size ()
|
||||
+ itemCount * get_row_size ();
|
||||
}
|
||||
|
||||
float get_delta (unsigned int inner,
|
||||
const int *coords, unsigned int coord_count,
|
||||
|
|
@ -2594,10 +2685,10 @@ struct VarData
|
|||
return delta;
|
||||
}
|
||||
|
||||
void get_scalars (const int *coords, unsigned int coord_count,
|
||||
const VarRegionList ®ions,
|
||||
float *scalars /*OUT */,
|
||||
unsigned int num_scalars) const
|
||||
void get_region_scalars (const int *coords, unsigned int coord_count,
|
||||
const VarRegionList ®ions,
|
||||
float *scalars /*OUT */,
|
||||
unsigned int num_scalars) const
|
||||
{
|
||||
unsigned count = hb_min (num_scalars, regionIndices.len);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
|
|
@ -2623,7 +2714,7 @@ struct VarData
|
|||
const hb_bimap_t ®ion_map)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
itemCount = inner_map.get_next_value ();
|
||||
|
||||
/* Optimize short count */
|
||||
|
|
@ -2665,9 +2756,7 @@ struct VarData
|
|||
shortCount = new_short_count;
|
||||
regionIndices.len = new_ri_count;
|
||||
|
||||
unsigned int size = regionIndices.get_size () - HBUINT16::static_size/*regionIndices.len*/ + (get_row_size () * itemCount);
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (size)))
|
||||
return_trace (false);
|
||||
if (unlikely (!c->extend (this))) return_trace (false);
|
||||
|
||||
for (r = 0; r < ri_count; r++)
|
||||
if (delta_sz[r]) regionIndices[ri_map[r]] = region_map[src->regionIndices[r]];
|
||||
|
|
@ -2682,16 +2771,16 @@ struct VarData
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
void collect_region_refs (hb_inc_bimap_t ®ion_map, const hb_inc_bimap_t &inner_map) const
|
||||
void collect_region_refs (hb_set_t ®ion_indices, const hb_inc_bimap_t &inner_map) const
|
||||
{
|
||||
for (unsigned int r = 0; r < regionIndices.len; r++)
|
||||
{
|
||||
unsigned int region = regionIndices[r];
|
||||
if (region_map.has (region)) continue;
|
||||
if (region_indices.has (region)) continue;
|
||||
for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
|
||||
if (get_item_delta (inner_map.backward (i), r) != 0)
|
||||
{
|
||||
region_map.add (region);
|
||||
region_indices.add (region);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2777,32 +2866,48 @@ struct VariationStore
|
|||
const hb_array_t <hb_inc_bimap_t> &inner_maps)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
unsigned int set_count = 0;
|
||||
for (unsigned int i = 0; i < inner_maps.length; i++)
|
||||
if (inner_maps[i].get_population () > 0) set_count++;
|
||||
if (inner_maps[i].get_population ())
|
||||
set_count++;
|
||||
|
||||
unsigned int size = min_size + HBUINT32::static_size * set_count;
|
||||
if (unlikely (!c->allocate_size<HBUINT32> (size))) return_trace (false);
|
||||
format = 1;
|
||||
|
||||
hb_inc_bimap_t region_map;
|
||||
for (unsigned int i = 0; i < inner_maps.length; i++)
|
||||
(src+src->dataSets[i]).collect_region_refs (region_map, inner_maps[i]);
|
||||
region_map.sort ();
|
||||
const auto &src_regions = src+src->regions;
|
||||
|
||||
if (unlikely (!regions.serialize_serialize (c, &(src+src->regions), region_map)))
|
||||
hb_set_t region_indices;
|
||||
for (unsigned int i = 0; i < inner_maps.length; i++)
|
||||
(src+src->dataSets[i]).collect_region_refs (region_indices, inner_maps[i]);
|
||||
|
||||
if (region_indices.in_error ())
|
||||
return_trace (false);
|
||||
|
||||
region_indices.del_range ((src_regions).regionCount, hb_set_t::INVALID);
|
||||
|
||||
/* TODO use constructor when our data-structures support that. */
|
||||
hb_inc_bimap_t region_map;
|
||||
+ hb_iter (region_indices)
|
||||
| hb_apply ([®ion_map] (unsigned _) { region_map.add(_); })
|
||||
;
|
||||
if (region_map.in_error())
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!regions.serialize_serialize (c, &src_regions, region_map)))
|
||||
return_trace (false);
|
||||
|
||||
/* TODO: The following code could be simplified when
|
||||
* List16OfOffset16To::subset () can take a custom param to be passed to VarData::serialize ()
|
||||
*/
|
||||
dataSets.len = set_count;
|
||||
if (unlikely (!c->extend (dataSets))) return_trace (false);
|
||||
|
||||
/* TODO: The following code could be simplified when
|
||||
* List16OfOffset16To::subset () can take a custom param to be passed to VarData::serialize () */
|
||||
unsigned int set_index = 0;
|
||||
for (unsigned int i = 0; i < inner_maps.length; i++)
|
||||
{
|
||||
if (inner_maps[i].get_population () == 0) continue;
|
||||
if (!inner_maps[i].get_population ()) continue;
|
||||
if (unlikely (!dataSets[set_index++]
|
||||
.serialize_serialize (c, &(src+src->dataSets[i]), inner_maps[i], region_map)))
|
||||
.serialize_serialize (c, &(src+src->dataSets[i]), inner_maps[i], region_map)))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
|
|
@ -2847,13 +2952,13 @@ struct VariationStore
|
|||
&& varstore_prime->dataSets);
|
||||
}
|
||||
|
||||
unsigned int get_region_index_count (unsigned int ivs) const
|
||||
{ return (this+dataSets[ivs]).get_region_index_count (); }
|
||||
unsigned int get_region_index_count (unsigned int major) const
|
||||
{ return (this+dataSets[major]).get_region_index_count (); }
|
||||
|
||||
void get_scalars (unsigned int ivs,
|
||||
const int *coords, unsigned int coord_count,
|
||||
float *scalars /*OUT*/,
|
||||
unsigned int num_scalars) const
|
||||
void get_region_scalars (unsigned int major,
|
||||
const int *coords, unsigned int coord_count,
|
||||
float *scalars /*OUT*/,
|
||||
unsigned int num_scalars) const
|
||||
{
|
||||
#ifdef HB_NO_VAR
|
||||
for (unsigned i = 0; i < num_scalars; i++)
|
||||
|
|
@ -2861,8 +2966,9 @@ struct VariationStore
|
|||
return;
|
||||
#endif
|
||||
|
||||
(this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
|
||||
&scalars[0], num_scalars);
|
||||
(this+dataSets[major]).get_region_scalars (coords, coord_count,
|
||||
this+regions,
|
||||
&scalars[0], num_scalars);
|
||||
}
|
||||
|
||||
unsigned int get_sub_table_count () const { return dataSets.len; }
|
||||
|
|
@ -2872,7 +2978,7 @@ struct VariationStore
|
|||
Offset32To<VarRegionList> regions;
|
||||
Array16OfOffset32To<VarData> dataSets;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, dataSets);
|
||||
DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -2929,7 +3035,7 @@ struct Condition
|
|||
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 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ struct AttachList
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
|
|
@ -248,9 +248,9 @@ struct CaretValue
|
|||
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)...));
|
||||
case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...));
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -371,7 +371,7 @@ struct LigCaretList
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset ();
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
|
|
|
|||
|
|
@ -118,7 +118,13 @@ struct ValueFormat : HBUINT16
|
|||
if (!format) return ret;
|
||||
|
||||
hb_font_t *font = c->font;
|
||||
bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
|
||||
bool horizontal =
|
||||
#ifndef HB_NO_VERTICAL
|
||||
HB_DIRECTION_IS_HORIZONTAL (c->direction)
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
;
|
||||
|
||||
if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
|
||||
if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
|
||||
|
|
@ -538,7 +544,7 @@ struct Anchor
|
|||
switch (u.format) {
|
||||
case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
|
||||
case 2:
|
||||
if (c->plan->drop_hints)
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
{
|
||||
// AnchorFormat 2 just containins extra hinting information, so
|
||||
// if hints are being dropped convert to format 1.
|
||||
|
|
@ -805,7 +811,7 @@ struct SinglePosFormat1
|
|||
ValueFormat newFormat,
|
||||
const hb_map_t *layout_variation_idx_map)
|
||||
{
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
if (unlikely (!c->extend_min (this))) return;
|
||||
if (unlikely (!c->check_assign (valueFormat,
|
||||
newFormat,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
|
||||
|
|
@ -925,7 +931,7 @@ struct SinglePosFormat2
|
|||
ValueFormat newFormat,
|
||||
const hb_map_t *layout_variation_idx_map)
|
||||
{
|
||||
auto out = c->extend_min (*this);
|
||||
auto out = c->extend_min (this);
|
||||
if (unlikely (!out)) return;
|
||||
if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
|
||||
if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
|
||||
|
|
@ -1050,8 +1056,8 @@ struct SinglePos
|
|||
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)...));
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -1144,7 +1150,7 @@ struct PairValueRecord
|
|||
}
|
||||
|
||||
protected:
|
||||
HBGlyphID secondGlyph; /* GlyphID of second glyph in the
|
||||
HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the
|
||||
* pair--first glyph is listed in the
|
||||
* Coverage table */
|
||||
ValueRecord values; /* Positioning data for the first glyph
|
||||
|
|
@ -1220,9 +1226,9 @@ struct PairSet
|
|||
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++;
|
||||
|
|
@ -1373,7 +1379,7 @@ struct PairPosFormat1
|
|||
out->format = format;
|
||||
out->valueFormat[0] = valueFormat[0];
|
||||
out->valueFormat[1] = valueFormat[1];
|
||||
if (c->plan->drop_hints)
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
{
|
||||
hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
|
||||
out->valueFormat[0] = newFormats.first;
|
||||
|
|
@ -1386,9 +1392,9 @@ struct PairPosFormat1
|
|||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter ([this, c, out] (const Offset16To<PairSet>& _)
|
||||
{
|
||||
auto snap = c->serializer->snapshot ();
|
||||
auto *o = out->pairSet.serialize_append (c->serializer);
|
||||
if (unlikely (!o)) return false;
|
||||
auto snap = c->serializer->snapshot ();
|
||||
bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
|
||||
if (!ret)
|
||||
{
|
||||
|
|
@ -1560,9 +1566,9 @@ struct PairPosFormat2
|
|||
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;
|
||||
|
|
@ -1591,7 +1597,7 @@ struct PairPosFormat2
|
|||
unsigned len2 = valueFormat2.get_len ();
|
||||
|
||||
hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
|
||||
if (c->plan->drop_hints)
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
newFormats = compute_effective_value_formats (klass1_map, klass2_map);
|
||||
|
||||
out->valueFormat1 = newFormats.first;
|
||||
|
|
@ -1702,8 +1708,8 @@ struct PairPos
|
|||
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)...));
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -1959,7 +1965,7 @@ struct CursivePos
|
|||
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 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -2194,7 +2200,7 @@ struct MarkBasePos
|
|||
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 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -2434,7 +2440,7 @@ struct MarkLigPos
|
|||
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 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -2653,7 +2659,7 @@ struct MarkMarkPos
|
|||
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 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -2704,15 +2710,15 @@ struct PosLookupSubTable
|
|||
{
|
||||
TRACE_DISPATCH (this, lookup_type);
|
||||
switch (lookup_type) {
|
||||
case Single: return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Pair: return_trace (u.pair.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Cursive: return_trace (u.cursive.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case MarkBase: return_trace (u.markBase.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case MarkLig: return_trace (u.markLig.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case MarkMark: return_trace (u.markMark.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Context: return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Extension: return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
|
||||
default: return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -2800,7 +2806,7 @@ struct PosLookup : Lookup
|
|||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{ return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
|
||||
{ return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{ return Lookup::subset<SubTable> (c); }
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ struct SingleSubstFormat1
|
|||
unsigned delta)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
|
||||
c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
return_trace (true);
|
||||
|
|
@ -209,7 +209,7 @@ struct SingleSubstFormat2
|
|||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
|
||||
if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
|
||||
return_trace (true);
|
||||
|
|
@ -225,7 +225,7 @@ struct SingleSubstFormat2
|
|||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (glyphset, hb_second)
|
||||
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t
|
||||
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
|
||||
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
|
||||
;
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ struct SingleSubstFormat2
|
|||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
Array16Of<HBGlyphID>
|
||||
Array16Of<HBGlyphID16>
|
||||
substitute; /* Array of substitute
|
||||
* GlyphIDs--ordered by Coverage Index */
|
||||
public:
|
||||
|
|
@ -290,8 +290,8 @@ struct SingleSubst
|
|||
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)...));
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -343,9 +343,14 @@ struct Sequence
|
|||
|
||||
unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
|
||||
unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
|
||||
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
/* If is attached to a ligature, don't disturb that.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/3069 */
|
||||
if (!lig_id)
|
||||
_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
|
||||
c->output_glyph_for_component (substitute.arrayZ[i], klass);
|
||||
}
|
||||
c->buffer->skip_glyph ();
|
||||
|
|
@ -386,7 +391,7 @@ struct Sequence
|
|||
}
|
||||
|
||||
protected:
|
||||
Array16Of<HBGlyphID>
|
||||
Array16Of<HBGlyphID16>
|
||||
substitute; /* String of GlyphIDs to substitute */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, substitute);
|
||||
|
|
@ -408,7 +413,6 @@ struct MultipleSubstFormat1
|
|||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const Sequence &_) { _.closure (c); })
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
|
@ -439,12 +443,12 @@ struct MultipleSubstFormat1
|
|||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID> glyphs,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> substitute_len_list,
|
||||
hb_array_t<const HBGlyphID> substitute_glyphs_list)
|
||||
hb_array_t<const HBGlyphID16> substitute_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < glyphs.length; i++)
|
||||
{
|
||||
|
|
@ -500,9 +504,9 @@ struct MultipleSubstFormat1
|
|||
struct MultipleSubst
|
||||
{
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID> glyphs,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> substitute_len_list,
|
||||
hb_array_t<const HBGlyphID> substitute_glyphs_list)
|
||||
hb_array_t<const HBGlyphID16> substitute_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (u.format))) return_trace (false);
|
||||
|
|
@ -520,7 +524,7 @@ struct MultipleSubst
|
|||
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 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -559,7 +563,12 @@ struct AlternateSet
|
|||
|
||||
/* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
|
||||
if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
|
||||
{
|
||||
/* Maybe we can do better than unsafe-to-break all; but since we are
|
||||
* changing random state, it would be hard to track that. Good 'nough. */
|
||||
c->buffer->unsafe_to_break (0, c->buffer->len);
|
||||
alt_index = c->random_number () % count + 1;
|
||||
}
|
||||
|
||||
if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
|
||||
|
||||
|
|
@ -615,7 +624,7 @@ struct AlternateSet
|
|||
}
|
||||
|
||||
protected:
|
||||
Array16Of<HBGlyphID>
|
||||
Array16Of<HBGlyphID16>
|
||||
alternates; /* Array of alternate GlyphIDs--in
|
||||
* arbitrary order */
|
||||
public:
|
||||
|
|
@ -677,12 +686,12 @@ struct AlternateSubstFormat1
|
|||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID> glyphs,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> alternate_len_list,
|
||||
hb_array_t<const HBGlyphID> alternate_glyphs_list)
|
||||
hb_array_t<const HBGlyphID16> alternate_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < glyphs.length; i++)
|
||||
{
|
||||
|
|
@ -738,9 +747,9 @@ struct AlternateSubstFormat1
|
|||
struct AlternateSubst
|
||||
{
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID> glyphs,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> alternate_len_list,
|
||||
hb_array_t<const HBGlyphID> alternate_glyphs_list)
|
||||
hb_array_t<const HBGlyphID16> alternate_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (u.format))) return_trace (false);
|
||||
|
|
@ -758,7 +767,7 @@ struct AlternateSubst
|
|||
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 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -846,19 +855,21 @@ struct Ligature
|
|||
Iterator components /* Starting from second */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
ligGlyph = ligature;
|
||||
if (unlikely (!component.serialize (c, components))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
|
||||
// Ensure Coverage table is always packed after this.
|
||||
c->serializer->add_virtual_link (coverage_idx);
|
||||
|
||||
auto it =
|
||||
+ hb_iter (component)
|
||||
|
|
@ -879,8 +890,8 @@ struct Ligature
|
|||
}
|
||||
|
||||
protected:
|
||||
HBGlyphID ligGlyph; /* GlyphID of ligature to substitute */
|
||||
HeadlessArrayOf<HBGlyphID>
|
||||
HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */
|
||||
HeadlessArrayOf<HBGlyphID16>
|
||||
component; /* Array of component GlyphIDs--start
|
||||
* with the second component--ordered
|
||||
* in writing direction */
|
||||
|
|
@ -940,12 +951,12 @@ struct LigatureSet
|
|||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_array_t<const HBGlyphID> ligatures,
|
||||
hb_array_t<const HBGlyphID16> ligatures,
|
||||
hb_array_t<const unsigned int> component_count_list,
|
||||
hb_array_t<const HBGlyphID> &component_list /* Starting from second for each ligature */)
|
||||
hb_array_t<const HBGlyphID16> &component_list /* Starting from second for each ligature */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < ligatures.length; i++)
|
||||
{
|
||||
|
|
@ -959,16 +970,21 @@ struct LigatureSet
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
+ hb_iter (ligature)
|
||||
| hb_filter (subset_offset_array (c, out->ligature, this))
|
||||
| hb_filter (subset_offset_array (c, out->ligature, this, coverage_idx))
|
||||
| hb_drain
|
||||
;
|
||||
|
||||
if (bool (out->ligature))
|
||||
// Ensure Coverage table is always packed after this.
|
||||
c->serializer->add_virtual_link (coverage_idx);
|
||||
|
||||
return_trace (bool (out->ligature));
|
||||
}
|
||||
|
||||
|
|
@ -1050,14 +1066,14 @@ struct LigatureSubstFormat1
|
|||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID> first_glyphs,
|
||||
hb_sorted_array_t<const HBGlyphID16> first_glyphs,
|
||||
hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
|
||||
hb_array_t<const HBGlyphID> ligatures_list,
|
||||
hb_array_t<const HBGlyphID16> ligatures_list,
|
||||
hb_array_t<const unsigned int> component_count_list,
|
||||
hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */)
|
||||
hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < first_glyphs.length; i++)
|
||||
{
|
||||
|
|
@ -1083,15 +1099,38 @@ struct LigatureSubstFormat1
|
|||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ hb_zip (this+coverage, ligatureSet)
|
||||
// Due to a bug in some older versions of windows 7 the Coverage table must be
|
||||
// packed after the LigatureSet and Ligature tables, so serialize Coverage first
|
||||
// which places it last in the packed order.
|
||||
hb_set_t new_coverage;
|
||||
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (subset_offset_array (c, out->ligatureSet, this), hb_second)
|
||||
| hb_filter ([&] (const LigatureSet& _) {
|
||||
return _.intersects (&glyphset);
|
||||
}, hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
| hb_sink (new_coverage);
|
||||
|
||||
if (!c->serializer->push<Coverage> ()
|
||||
->serialize (c->serializer,
|
||||
+ new_coverage.iter () | hb_map_retains_sorting (glyph_map)))
|
||||
{
|
||||
c->serializer->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned coverage_idx = c->serializer->pop_pack ();
|
||||
c->serializer->add_link (out->coverage, coverage_idx);
|
||||
|
||||
+ hb_zip (this+coverage, ligatureSet)
|
||||
| hb_filter (new_coverage, hb_first)
|
||||
| hb_map (hb_second)
|
||||
// to ensure that the repacker always orders the coverage table after the LigatureSet
|
||||
// and LigatureSubtable's they will be linked to the Coverage table via a virtual link
|
||||
// the coverage table object idx is passed down to facilitate this.
|
||||
| hb_apply (subset_offset_array (c, out->ligatureSet, this, coverage_idx))
|
||||
;
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
|
||||
|
|
@ -1116,11 +1155,11 @@ struct LigatureSubstFormat1
|
|||
struct LigatureSubst
|
||||
{
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID> first_glyphs,
|
||||
hb_sorted_array_t<const HBGlyphID16> first_glyphs,
|
||||
hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
|
||||
hb_array_t<const HBGlyphID> ligatures_list,
|
||||
hb_array_t<const HBGlyphID16> ligatures_list,
|
||||
hb_array_t<const unsigned int> component_count_list,
|
||||
hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */)
|
||||
hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (u.format))) return_trace (false);
|
||||
|
|
@ -1143,7 +1182,7 @@ struct LigatureSubst
|
|||
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 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -1199,7 +1238,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
if (!intersects (c->glyphs)) return;
|
||||
|
||||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
|
||||
|
||||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
|
|
@ -1225,7 +1264,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
for (unsigned int i = 0; i < count; i++)
|
||||
if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
|
||||
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
|
||||
count = substitute.len;
|
||||
c->output->add_array (substitute.arrayZ, substitute.len);
|
||||
}
|
||||
|
|
@ -1245,7 +1284,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
|
||||
|
||||
if (unlikely (index >= substitute.len)) return_trace (false);
|
||||
|
||||
|
|
@ -1308,7 +1347,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
|
||||
if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
|
||||
|
||||
auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID>> ();
|
||||
auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID16>> ();
|
||||
auto substitutes =
|
||||
+ coverage_subst_iter
|
||||
| hb_map (hb_second)
|
||||
|
|
@ -1333,13 +1372,13 @@ struct ReverseChainSingleSubstFormat1
|
|||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (glyphset, hb_second)
|
||||
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID &> p) -> hb_codepoint_pair_t
|
||||
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
|
||||
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
|
||||
;
|
||||
|
||||
|
|
@ -1354,7 +1393,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
|
||||
if (!lookahead.sanitize (c, this))
|
||||
return_trace (false);
|
||||
const Array16Of<HBGlyphID> &substitute = StructAfter<Array16Of<HBGlyphID>> (lookahead);
|
||||
const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
|
||||
return_trace (substitute.sanitize (c));
|
||||
}
|
||||
|
||||
|
|
@ -1371,7 +1410,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
lookaheadX; /* Array of coverage tables
|
||||
* in lookahead sequence, in glyph
|
||||
* sequence order */
|
||||
Array16Of<HBGlyphID>
|
||||
Array16Of<HBGlyphID16>
|
||||
substituteX; /* Array of substitute
|
||||
* GlyphIDs--ordered by Coverage Index */
|
||||
public:
|
||||
|
|
@ -1386,7 +1425,7 @@ struct ReverseChainSingleSubst
|
|||
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 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -1425,14 +1464,14 @@ struct SubstLookupSubTable
|
|||
{
|
||||
TRACE_DISPATCH (this, lookup_type);
|
||||
switch (lookup_type) {
|
||||
case Single: return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Multiple: return_trace (u.multiple.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Alternate: return_trace (u.alternate.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Ligature: return_trace (u.ligature.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Context: return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Extension: return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Multiple: return_trace (u.multiple.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Alternate: return_trace (u.alternate.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Ligature: return_trace (u.ligature.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, std::forward<Ts> (ds)...));
|
||||
default: return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -1552,8 +1591,8 @@ struct SubstLookup : Lookup
|
|||
|
||||
bool serialize_single (hb_serialize_context_t *c,
|
||||
uint32_t lookup_props,
|
||||
hb_sorted_array_t<const HBGlyphID> glyphs,
|
||||
hb_array_t<const HBGlyphID> substitutes)
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const HBGlyphID16> substitutes)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
|
||||
|
|
@ -1568,9 +1607,9 @@ struct SubstLookup : Lookup
|
|||
|
||||
bool serialize_multiple (hb_serialize_context_t *c,
|
||||
uint32_t lookup_props,
|
||||
hb_sorted_array_t<const HBGlyphID> glyphs,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> substitute_len_list,
|
||||
hb_array_t<const HBGlyphID> substitute_glyphs_list)
|
||||
hb_array_t<const HBGlyphID16> substitute_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
|
||||
|
|
@ -1589,9 +1628,9 @@ struct SubstLookup : Lookup
|
|||
|
||||
bool serialize_alternate (hb_serialize_context_t *c,
|
||||
uint32_t lookup_props,
|
||||
hb_sorted_array_t<const HBGlyphID> glyphs,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> alternate_len_list,
|
||||
hb_array_t<const HBGlyphID> alternate_glyphs_list)
|
||||
hb_array_t<const HBGlyphID16> alternate_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
|
||||
|
|
@ -1611,11 +1650,11 @@ struct SubstLookup : Lookup
|
|||
|
||||
bool serialize_ligature (hb_serialize_context_t *c,
|
||||
uint32_t lookup_props,
|
||||
hb_sorted_array_t<const HBGlyphID> first_glyphs,
|
||||
hb_sorted_array_t<const HBGlyphID16> first_glyphs,
|
||||
hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
|
||||
hb_array_t<const HBGlyphID> ligatures_list,
|
||||
hb_array_t<const HBGlyphID16> ligatures_list,
|
||||
hb_array_t<const unsigned int> component_count_list,
|
||||
hb_array_t<const HBGlyphID> component_list /* Starting from second for each ligature */)
|
||||
hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
|
||||
|
|
@ -1658,7 +1697,7 @@ struct SubstLookup : Lookup
|
|||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{ return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
|
||||
{ return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{ return Lookup::subset<SubTable> (c); }
|
||||
|
|
|
|||
|
|
@ -81,12 +81,15 @@ struct hb_closure_context_t :
|
|||
nesting_level_left++;
|
||||
}
|
||||
|
||||
void reset_lookup_visit_count ()
|
||||
{ lookup_count = 0; }
|
||||
|
||||
bool lookup_limit_exceeded ()
|
||||
{ return lookup_count > HB_MAX_LOOKUP_INDICES; }
|
||||
{ return lookup_count > HB_MAX_LOOKUP_VISIT_COUNT; }
|
||||
|
||||
bool should_visit_lookup (unsigned int lookup_index)
|
||||
{
|
||||
if (lookup_count++ > HB_MAX_LOOKUP_INDICES)
|
||||
if (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT)
|
||||
return false;
|
||||
|
||||
if (is_lookup_done (lookup_index))
|
||||
|
|
@ -163,7 +166,7 @@ struct hb_closure_context_t :
|
|||
hb_set_t *glyphs_,
|
||||
hb_set_t *cur_intersected_glyphs_,
|
||||
hb_map_t *done_lookups_glyph_count_,
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set_,
|
||||
hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set_,
|
||||
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
|
||||
face (face_),
|
||||
glyphs (glyphs_),
|
||||
|
|
@ -183,7 +186,7 @@ struct hb_closure_context_t :
|
|||
|
||||
void flush ()
|
||||
{
|
||||
hb_set_del_range (output, face->get_num_glyphs (), hb_set_get_max (output)); /* Remove invalid glyphs. */
|
||||
hb_set_del_range (output, face->get_num_glyphs (), HB_SET_VALUE_INVALID); /* Remove invalid glyphs. */
|
||||
hb_set_union (glyphs, output);
|
||||
hb_set_clear (output);
|
||||
active_glyphs_stack.pop ();
|
||||
|
|
@ -192,7 +195,7 @@ struct hb_closure_context_t :
|
|||
|
||||
private:
|
||||
hb_map_t *done_lookups_glyph_count;
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *done_lookups_glyph_set;
|
||||
hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set;
|
||||
unsigned int lookup_count;
|
||||
};
|
||||
|
||||
|
|
@ -211,7 +214,11 @@ struct hb_closure_lookups_context_t :
|
|||
return;
|
||||
|
||||
/* Return if new lookup was recursed to before. */
|
||||
if (is_lookup_visited (lookup_index))
|
||||
if (lookup_limit_exceeded ()
|
||||
|| visited_lookups->in_error ()
|
||||
|| visited_lookups->has (lookup_index))
|
||||
// Don't increment lookup count here, that will be done in the call to closure_lookups()
|
||||
// made by recurse_func.
|
||||
return;
|
||||
|
||||
nesting_level_left--;
|
||||
|
|
@ -226,12 +233,20 @@ struct hb_closure_lookups_context_t :
|
|||
{ inactive_lookups->add (lookup_index); }
|
||||
|
||||
bool lookup_limit_exceeded ()
|
||||
{ return lookup_count > HB_MAX_LOOKUP_INDICES; }
|
||||
{
|
||||
bool ret = lookup_count > HB_MAX_LOOKUP_VISIT_COUNT;
|
||||
if (ret)
|
||||
DEBUG_MSG (SUBSET, nullptr, "lookup visit count limit exceeded in lookup closure!");
|
||||
return ret; }
|
||||
|
||||
bool is_lookup_visited (unsigned lookup_index)
|
||||
{
|
||||
if (unlikely (lookup_count++ > HB_MAX_LOOKUP_INDICES))
|
||||
if (unlikely (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT))
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "total visited lookup count %u exceeds max limit, lookup %u is dropped.",
|
||||
lookup_count, lookup_index);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (unlikely (visited_lookups->in_error ()))
|
||||
return true;
|
||||
|
|
@ -1210,15 +1225,14 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
|
|||
|
||||
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 +1249,24 @@ struct LookupRecord
|
|||
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,
|
||||
|
|
@ -1286,8 +1318,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
|
|||
}
|
||||
|
||||
hb_set_add (covered_seq_indicies, seqIndex);
|
||||
if (pos_glyphs)
|
||||
c->push_cur_active_glyphs (pos_glyphs);
|
||||
c->push_cur_active_glyphs (pos_glyphs ? pos_glyphs : c->glyphs);
|
||||
|
||||
unsigned endIndex = inputCount;
|
||||
if (context_format == ContextFormat::CoverageBasedContext)
|
||||
|
|
@ -1295,10 +1326,9 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
|
|||
|
||||
c->recurse (lookupRecord[i].lookupListIndex, covered_seq_indicies, seqIndex, endIndex);
|
||||
|
||||
if (pos_glyphs) {
|
||||
c->pop_cur_done_glyphs ();
|
||||
c->pop_cur_done_glyphs ();
|
||||
if (pos_glyphs)
|
||||
hb_set_destroy (pos_glyphs);
|
||||
}
|
||||
}
|
||||
|
||||
hb_set_destroy (covered_seq_indicies);
|
||||
|
|
@ -1605,8 +1635,6 @@ struct Rule
|
|||
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,10 +1645,9 @@ struct Rule
|
|||
|
||||
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
|
||||
(inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
|
||||
for (unsigned i = 0; i < (unsigned) lookupCount; i++)
|
||||
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,
|
||||
|
|
@ -1628,9 +1655,8 @@ struct Rule
|
|||
const hb_map_t *klass_map = nullptr) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
const hb_array_t<const HBUINT16> input = inputZ.as_array ((inputCount ? inputCount - 1 : 0));
|
||||
if (!input.length) return_trace (false);
|
||||
if (unlikely (!inputCount)) return_trace (false);
|
||||
const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
|
||||
|
||||
const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map;
|
||||
if (!hb_all (input, mapping)) return_trace (false);
|
||||
|
|
@ -1745,10 +1771,10 @@ struct RuleSet
|
|||
for (const Offset16To<Rule>& _ : rule)
|
||||
{
|
||||
if (!_) continue;
|
||||
auto o_snap = c->serializer->snapshot ();
|
||||
auto *o = out->rule.serialize_append (c->serializer);
|
||||
if (unlikely (!o)) continue;
|
||||
|
||||
auto o_snap = c->serializer->snapshot ();
|
||||
if (!o->serialize_subset (c, _, this, lookup_map, klass_map))
|
||||
{
|
||||
out->rule.pop ();
|
||||
|
|
@ -1936,12 +1962,20 @@ struct ContextFormat2
|
|||
&class_def
|
||||
};
|
||||
|
||||
hb_set_t retained_coverage_glyphs;
|
||||
(this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
|
||||
|
||||
hb_set_t coverage_glyph_classes;
|
||||
class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
|
||||
|
||||
|
||||
return
|
||||
+ hb_iter (ruleSet)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_enumerate
|
||||
| hb_map ([&] (const hb_pair_t<unsigned, const RuleSet &> p)
|
||||
{ return class_def.intersects_class (glyphs, p.first) &&
|
||||
coverage_glyph_classes.has (p.first) &&
|
||||
p.second.intersects (glyphs, lookup_context); })
|
||||
| hb_any
|
||||
;
|
||||
|
|
@ -2062,9 +2096,16 @@ struct ContextFormat2
|
|||
hb_map_t klass_map;
|
||||
out->classDef.serialize_subset (c, classDef, this, &klass_map);
|
||||
|
||||
const hb_set_t* glyphset = c->plan->glyphset_gsub ();
|
||||
hb_set_t retained_coverage_glyphs;
|
||||
(this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
|
||||
|
||||
hb_set_t coverage_glyph_classes;
|
||||
(this+classDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
|
||||
|
||||
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
||||
bool ret = true;
|
||||
int non_zero_index = 0, index = 0;
|
||||
int non_zero_index = -1, index = 0;
|
||||
for (const auto& _ : + hb_enumerate (ruleSet)
|
||||
| hb_filter (klass_map, hb_first))
|
||||
{
|
||||
|
|
@ -2075,13 +2116,14 @@ struct ContextFormat2
|
|||
break;
|
||||
}
|
||||
|
||||
if (o->serialize_subset (c, _.second, this, lookup_map, &klass_map))
|
||||
if (coverage_glyph_classes.has (_.first) &&
|
||||
o->serialize_subset (c, _.second, this, lookup_map, &klass_map))
|
||||
non_zero_index = index;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!ret) return_trace (ret);
|
||||
if (!ret || non_zero_index == -1) return_trace (false);
|
||||
|
||||
//prune empty trailing ruleSets
|
||||
--index;
|
||||
|
|
@ -2219,7 +2261,6 @@ struct ContextFormat3
|
|||
|
||||
out->format = format;
|
||||
out->glyphCount = glyphCount;
|
||||
out->lookupCount = lookupCount;
|
||||
|
||||
auto coverages = coverageZ.as_array (glyphCount);
|
||||
|
||||
|
|
@ -2231,12 +2272,12 @@ struct ContextFormat3
|
|||
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++)
|
||||
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
|
||||
|
|
@ -2275,9 +2316,9 @@ struct Context
|
|||
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)...));
|
||||
case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...));
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -2525,15 +2566,15 @@ struct ChainRule
|
|||
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 ()
|
||||
|
|
@ -2552,19 +2593,10 @@ struct ChainRule
|
|||
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,
|
||||
|
|
@ -2586,7 +2618,7 @@ struct ChainRule
|
|||
!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
|
||||
{
|
||||
|
|
@ -2595,7 +2627,7 @@ struct ChainRule
|
|||
!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);
|
||||
|
|
@ -2710,10 +2742,10 @@ struct ChainRuleSet
|
|||
for (const Offset16To<ChainRule>& _ : rule)
|
||||
{
|
||||
if (!_) continue;
|
||||
auto o_snap = c->serializer->snapshot ();
|
||||
auto *o = out->rule.serialize_append (c->serializer);
|
||||
if (unlikely (!o)) continue;
|
||||
|
||||
auto o_snap = c->serializer->snapshot ();
|
||||
if (!o->serialize_subset (c, _, this,
|
||||
lookup_map,
|
||||
backtrack_klass_map,
|
||||
|
|
@ -2906,12 +2938,19 @@ struct ChainContextFormat2
|
|||
&lookahead_class_def}
|
||||
};
|
||||
|
||||
hb_set_t retained_coverage_glyphs;
|
||||
(this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
|
||||
|
||||
hb_set_t coverage_glyph_classes;
|
||||
input_class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
|
||||
|
||||
return
|
||||
+ hb_iter (ruleSet)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_enumerate
|
||||
| hb_map ([&] (const hb_pair_t<unsigned, const ChainRuleSet &> p)
|
||||
{ return input_class_def.intersects_class (glyphs, p.first) &&
|
||||
coverage_glyph_classes.has (p.first) &&
|
||||
p.second.intersects (glyphs, lookup_context); })
|
||||
| hb_any
|
||||
;
|
||||
|
|
@ -3066,13 +3105,19 @@ struct ChainContextFormat2
|
|||
lookahead_klass_map)))
|
||||
return_trace (false);
|
||||
|
||||
const hb_set_t* glyphset = c->plan->glyphset_gsub ();
|
||||
hb_set_t retained_coverage_glyphs;
|
||||
(this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
|
||||
|
||||
hb_set_t coverage_glyph_classes;
|
||||
(this+inputClassDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
|
||||
|
||||
int non_zero_index = -1, index = 0;
|
||||
bool ret = true;
|
||||
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
||||
auto last_non_zero = c->serializer->snapshot ();
|
||||
for (const Offset16To<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
|
||||
| hb_filter (input_klass_map, hb_first)
|
||||
| hb_map (hb_second))
|
||||
for (const auto& _ : + hb_enumerate (ruleSet)
|
||||
| hb_filter (input_klass_map, hb_first))
|
||||
{
|
||||
auto *o = out->ruleSet.serialize_append (c->serializer);
|
||||
if (unlikely (!o))
|
||||
|
|
@ -3080,7 +3125,8 @@ struct ChainContextFormat2
|
|||
ret = false;
|
||||
break;
|
||||
}
|
||||
if (o->serialize_subset (c, _, this,
|
||||
if (coverage_glyph_classes.has (_.first) &&
|
||||
o->serialize_subset (c, _.second, this,
|
||||
lookup_map,
|
||||
&backtrack_klass_map,
|
||||
&input_klass_map,
|
||||
|
|
@ -3093,7 +3139,7 @@ struct ChainContextFormat2
|
|||
index++;
|
||||
}
|
||||
|
||||
if (!ret) return_trace (ret);
|
||||
if (!ret || non_zero_index == -1) return_trace (false);
|
||||
|
||||
// prune empty trailing ruleSets
|
||||
if (index > non_zero_index) {
|
||||
|
|
@ -3303,15 +3349,13 @@ struct ChainContextFormat3
|
|||
return_trace (false);
|
||||
|
||||
const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
|
||||
HBUINT16 lookupCount;
|
||||
lookupCount = lookupRecord.len;
|
||||
if (!c->serializer->copy (lookupCount)) return_trace (false);
|
||||
|
||||
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 (!c->serializer->copy (lookupRecord[i], lookup_map)) return_trace (false);
|
||||
|
||||
return_trace (true);
|
||||
HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookupRecord.len);
|
||||
if (!lookupCount) return_trace (false);
|
||||
|
||||
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
|
||||
|
|
@ -3356,9 +3400,9 @@ struct ChainContext
|
|||
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)...));
|
||||
case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...));
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -3387,7 +3431,7 @@ struct ExtensionFormat1
|
|||
{
|
||||
TRACE_DISPATCH (this, format);
|
||||
if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
|
||||
return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), hb_forward<Ts> (ds)...));
|
||||
return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), std::forward<Ts> (ds)...));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
|
|
@ -3467,7 +3511,7 @@ struct Extension
|
|||
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 (u.format1.dispatch (c, hb_forward<Ts> (ds)...));
|
||||
case 1: return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
|
@ -3599,7 +3643,7 @@ struct GSUBGPOS
|
|||
}
|
||||
|
||||
void prune_langsys (const hb_map_t *duplicate_feature_map,
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> *script_langsys_map,
|
||||
hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map,
|
||||
hb_set_t *new_feature_indexes /* OUT */) const
|
||||
{
|
||||
hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
|
||||
|
|
@ -3656,57 +3700,72 @@ struct GSUBGPOS
|
|||
const hb_set_t *feature_indices,
|
||||
hb_map_t *duplicate_feature_map /* OUT */) const
|
||||
{
|
||||
if (feature_indices->is_empty ()) return;
|
||||
hb_hashmap_t<hb_tag_t, hb_set_t *> unique_features;
|
||||
//find out duplicate features after subset
|
||||
unsigned prev = 0xFFFFu;
|
||||
for (unsigned i : feature_indices->iter ())
|
||||
{
|
||||
if (prev == 0xFFFFu)
|
||||
{
|
||||
duplicate_feature_map->set (i, i);
|
||||
prev = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
hb_tag_t t = get_feature_tag (i);
|
||||
hb_tag_t prev_t = get_feature_tag (prev);
|
||||
if (t != prev_t)
|
||||
if (t == unique_features.INVALID_KEY) continue;
|
||||
if (!unique_features.has (t))
|
||||
{
|
||||
hb_set_t* indices = hb_set_create ();
|
||||
if (unlikely (indices == hb_set_get_empty () ||
|
||||
!unique_features.set (t, indices)))
|
||||
{
|
||||
hb_set_destroy (indices);
|
||||
for (auto _ : unique_features.iter ())
|
||||
hb_set_destroy (_.second);
|
||||
return;
|
||||
}
|
||||
if (unique_features.get (t))
|
||||
unique_features.get (t)->add (i);
|
||||
duplicate_feature_map->set (i, i);
|
||||
prev = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
const Feature& f = get_feature (i);
|
||||
const Feature& prev_f = get_feature (prev);
|
||||
bool found = false;
|
||||
|
||||
auto f_iter =
|
||||
+ hb_iter (f.lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
auto prev_iter =
|
||||
+ hb_iter (prev_f.lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
if (f_iter.len () != prev_iter.len ())
|
||||
hb_set_t* same_tag_features = unique_features.get (t);
|
||||
for (unsigned other_f_index : same_tag_features->iter ())
|
||||
{
|
||||
duplicate_feature_map->set (i, i);
|
||||
prev = i;
|
||||
continue;
|
||||
const Feature& f = get_feature (i);
|
||||
const Feature& other_f = get_feature (other_f_index);
|
||||
|
||||
auto f_iter =
|
||||
+ hb_iter (f.lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
auto other_f_iter =
|
||||
+ hb_iter (other_f.lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
bool is_equal = true;
|
||||
for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
|
||||
{
|
||||
unsigned a = *f_iter;
|
||||
unsigned b = *other_f_iter;
|
||||
if (a != b) { is_equal = false; break; }
|
||||
}
|
||||
|
||||
if (is_equal == false || f_iter || other_f_iter) continue;
|
||||
|
||||
found = true;
|
||||
duplicate_feature_map->set (i, other_f_index);
|
||||
break;
|
||||
}
|
||||
|
||||
bool is_equal = true;
|
||||
for (auto _ : + hb_zip (f_iter, prev_iter))
|
||||
if (_.first != _.second) { is_equal = false; break; }
|
||||
|
||||
if (is_equal == true) duplicate_feature_map->set (i, prev);
|
||||
else
|
||||
if (found == false)
|
||||
{
|
||||
same_tag_features->add (i);
|
||||
duplicate_feature_map->set (i, i);
|
||||
prev = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto _ : unique_features.iter ())
|
||||
hb_set_destroy (_.second);
|
||||
}
|
||||
|
||||
void prune_features (const hb_map_t *lookup_indices, /* IN */
|
||||
|
|
@ -3719,8 +3778,9 @@ struct GSUBGPOS
|
|||
hb_set_t alternate_feature_indices;
|
||||
if (version.to_int () >= 0x00010001u)
|
||||
(this+featureVars).closure_features (lookup_indices, &alternate_feature_indices);
|
||||
if (unlikely (alternate_feature_indices.in_error())) {
|
||||
feature_indices->successful = false;
|
||||
if (unlikely (alternate_feature_indices.in_error()))
|
||||
{
|
||||
feature_indices->err ();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -3736,8 +3796,12 @@ struct GSUBGPOS
|
|||
// http://lists.freedesktop.org/archives/harfbuzz/2012-November/002660.html
|
||||
continue;
|
||||
|
||||
if (f.featureParams.is_null ()
|
||||
&& !f.intersects_lookup_indexes (lookup_indices)
|
||||
|
||||
if (!f.featureParams.is_null () &&
|
||||
tag == HB_TAG ('s', 'i', 'z', 'e'))
|
||||
continue;
|
||||
|
||||
if (!f.intersects_lookup_indexes (lookup_indices)
|
||||
#ifndef HB_NO_VAR
|
||||
&& !alternate_feature_indices.has (i)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ struct JstfLangSys : List16OfOffset16To<JstfPriority>
|
|||
* ExtenderGlyphs -- Extender Glyph Table
|
||||
*/
|
||||
|
||||
typedef SortedArray16Of<HBGlyphID> ExtenderGlyphs;
|
||||
typedef SortedArray16Of<HBGlyphID16> ExtenderGlyphs;
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -613,7 +613,7 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
|
|||
* hb_ot_layout_table_find_feature:
|
||||
* @face: #hb_face_t to work upon
|
||||
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
|
||||
* @feature_tag: The #hb_tag_t og the requested feature tag
|
||||
* @feature_tag: The #hb_tag_t of the requested feature tag
|
||||
* @feature_index: (out): The index of the requested feature
|
||||
*
|
||||
* Fetches the index for a given feature tag in the specified face's GSUB table
|
||||
|
|
@ -688,8 +688,8 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
|
|||
*
|
||||
* Return value: %true if the language tag is found, %false otherwise
|
||||
*
|
||||
* Since: ??
|
||||
* Deprecated: ??
|
||||
* Since: 0.6.0
|
||||
* Deprecated: 2.0.0
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_ot_layout_script_find_language (hb_face_t *face,
|
||||
|
|
@ -717,10 +717,14 @@ hb_ot_layout_script_find_language (hb_face_t *face,
|
|||
* @language_tags: The array of language tags
|
||||
* @language_index: (out): The index of the requested language
|
||||
*
|
||||
* Fetches the index of a given language tag in the specified face's GSUB table
|
||||
* or GPOS table, underneath the specified script index.
|
||||
* Fetches the index of the first language tag fom @language_tags that is present
|
||||
* in the specified face's GSUB or GPOS table, underneath the specified script
|
||||
* index.
|
||||
*
|
||||
* Return value: %true if the language tag is found, %false otherwise
|
||||
* If none of the given language tags is found, %false is returned and
|
||||
* @language_index is set to the default language index.
|
||||
*
|
||||
* Return value: %true if one of the given language tags is found, %false otherwise
|
||||
*
|
||||
* Since: 2.0.0
|
||||
**/
|
||||
|
|
@ -746,7 +750,8 @@ hb_ot_layout_script_select_language (hb_face_t *face,
|
|||
if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
|
||||
return false;
|
||||
|
||||
if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
|
||||
if (language_index)
|
||||
*language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1013,24 +1018,15 @@ struct hb_collect_features_context_t
|
|||
}
|
||||
|
||||
has_feature_filter = true;
|
||||
hb_set_t features_set;
|
||||
for (; *features; features++)
|
||||
{
|
||||
hb_tag_t tag = *features;
|
||||
unsigned index;
|
||||
g.find_feature_index (tag, &index);
|
||||
if (index == OT::Index::NOT_FOUND_INDEX) continue;
|
||||
features_set.add (*features);
|
||||
|
||||
feature_indices_filter.add(index);
|
||||
for (int i = (int) index - 1; i >= 0; i--)
|
||||
{
|
||||
if (g.get_feature_tag (i) != tag) break;
|
||||
for (unsigned i = 0; i < g.get_feature_count (); i++)
|
||||
{
|
||||
hb_tag_t tag = g.get_feature_tag (i);
|
||||
if (features_set.has (tag))
|
||||
feature_indices_filter.add(i);
|
||||
}
|
||||
for (unsigned i = index + 1; i < g.get_feature_count (); i++)
|
||||
{
|
||||
if (g.get_feature_tag (i) != tag) break;
|
||||
feature_indices_filter.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1497,7 +1493,7 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
|
|||
{
|
||||
hb_set_t cur_intersected_glyphs;
|
||||
hb_map_t done_lookups_glyph_count;
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
|
||||
hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
|
||||
OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
|
||||
|
||||
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
|
||||
|
|
@ -1526,7 +1522,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
|
|||
{
|
||||
hb_set_t cur_intersected_glyphs;
|
||||
hb_map_t done_lookups_glyph_count;
|
||||
hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> done_lookups_glyph_set;
|
||||
hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
|
||||
OT::hb_closure_context_t c (face, glyphs, &cur_intersected_glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
|
||||
const OT::GSUB& gsub = *face->table.GSUB->table;
|
||||
|
||||
|
|
@ -1534,6 +1530,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
|
|||
unsigned int glyphs_length;
|
||||
do
|
||||
{
|
||||
c.reset_lookup_visit_count ();
|
||||
glyphs_length = glyphs->get_population ();
|
||||
if (lookups)
|
||||
{
|
||||
|
|
@ -1886,27 +1883,20 @@ apply_string (OT::hb_ot_apply_context_t *c,
|
|||
if (likely (!lookup.is_reverse ()))
|
||||
{
|
||||
/* in/out forward substitution/positioning */
|
||||
if (Proxy::table_index == 0u)
|
||||
if (!Proxy::inplace)
|
||||
buffer->clear_output ();
|
||||
buffer->idx = 0;
|
||||
|
||||
bool ret;
|
||||
ret = apply_forward (c, accel);
|
||||
if (ret)
|
||||
{
|
||||
if (!Proxy::inplace)
|
||||
buffer->swap_buffers ();
|
||||
else
|
||||
assert (!buffer->has_separate_output ());
|
||||
}
|
||||
buffer->idx = 0;
|
||||
apply_forward (c, accel);
|
||||
|
||||
if (!Proxy::inplace)
|
||||
buffer->swap_buffers ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* in-place backward substitution/positioning */
|
||||
if (Proxy::table_index == 0u)
|
||||
buffer->remove_output ();
|
||||
assert (!buffer->have_output);
|
||||
buffer->idx = buffer->len - 1;
|
||||
|
||||
apply_backward (c, accel);
|
||||
}
|
||||
}
|
||||
|
|
@ -1922,7 +1912,8 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
OT::hb_ot_apply_context_t c (table_index, font, buffer);
|
||||
c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
|
||||
|
||||
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) {
|
||||
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++)
|
||||
{
|
||||
const stage_map_t *stage = &stages[table_index][stage_index];
|
||||
for (; i < stage->last_lookup; i++)
|
||||
{
|
||||
|
|
@ -1932,11 +1923,8 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
c.set_lookup_mask (lookups[table_index][i].mask);
|
||||
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
|
||||
c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
|
||||
if (lookups[table_index][i].random)
|
||||
{
|
||||
c.set_random (true);
|
||||
buffer->unsafe_to_break_all ();
|
||||
}
|
||||
c.set_random (lookups[table_index][i].random);
|
||||
|
||||
apply_string<Proxy> (&c,
|
||||
proxy.table.get_lookup (lookup_index),
|
||||
proxy.accels[lookup_index]);
|
||||
|
|
@ -1944,10 +1932,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
}
|
||||
|
||||
if (stage->pause_func)
|
||||
{
|
||||
buffer->clear_output ();
|
||||
stage->pause_func (plan, font, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2023,14 +2008,14 @@ struct hb_get_glyph_alternates_dispatch_t :
|
|||
private:
|
||||
template <typename T, typename ...Ts> auto
|
||||
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
|
||||
( obj.get_glyph_alternates (hb_forward<Ts> (ds)...) )
|
||||
( obj.get_glyph_alternates (std::forward<Ts> (ds)...) )
|
||||
template <typename T, typename ...Ts> auto
|
||||
_dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
|
||||
( default_return_value () )
|
||||
public:
|
||||
template <typename T, typename ...Ts> auto
|
||||
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
|
||||
( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
|
||||
( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ _hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
* - 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 @@ _hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
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 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
|
|||
* 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;
|
||||
|
|
@ -350,24 +350,20 @@ _hb_glyph_info_is_continuation (const hb_glyph_info_t *info)
|
|||
{
|
||||
return info->unicode_props() & UPROPS_MASK_CONTINUATION;
|
||||
}
|
||||
/* Loop over grapheme. Based on foreach_cluster(). */
|
||||
|
||||
static inline bool
|
||||
_hb_grapheme_group_func (const hb_glyph_info_t& a HB_UNUSED,
|
||||
const hb_glyph_info_t& b)
|
||||
{ return _hb_glyph_info_is_continuation (&b); }
|
||||
|
||||
#define foreach_grapheme(buffer, start, end) \
|
||||
for (unsigned int \
|
||||
_count = buffer->len, \
|
||||
start = 0, end = _count ? _hb_next_grapheme (buffer, 0) : 0; \
|
||||
start < _count; \
|
||||
start = end, end = _hb_next_grapheme (buffer, start))
|
||||
foreach_group (buffer, start, end, _hb_grapheme_group_func)
|
||||
|
||||
static inline unsigned int
|
||||
_hb_next_grapheme (hb_buffer_t *buffer, unsigned int start)
|
||||
static inline void
|
||||
_hb_ot_layout_reverse_graphemes (hb_buffer_t *buffer)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
|
||||
while (++start < count && _hb_glyph_info_is_continuation (&info[start]))
|
||||
;
|
||||
|
||||
return start;
|
||||
buffer->reverse_groups (_hb_grapheme_group_func,
|
||||
buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
|
|||
face = face_;
|
||||
props = *props_;
|
||||
|
||||
|
||||
/* Fetch script/language indices for GSUB/GPOS. We need these later to skip
|
||||
* features not available in either table and not waste precious bits for them. */
|
||||
|
||||
|
|
@ -63,12 +62,28 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
|
|||
hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
|
||||
hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
|
||||
|
||||
hb_ot_tags_from_script_and_language (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
|
||||
hb_ot_tags_from_script_and_language (props.script,
|
||||
props.language,
|
||||
&script_count,
|
||||
script_tags,
|
||||
&language_count,
|
||||
language_tags);
|
||||
|
||||
for (unsigned int table_index = 0; table_index < 2; table_index++) {
|
||||
for (unsigned int table_index = 0; table_index < 2; table_index++)
|
||||
{
|
||||
hb_tag_t table_tag = table_tags[table_index];
|
||||
found_script[table_index] = (bool) hb_ot_layout_table_select_script (face, table_tag, script_count, script_tags, &script_index[table_index], &chosen_script[table_index]);
|
||||
hb_ot_layout_script_select_language (face, table_tag, script_index[table_index], language_count, language_tags, &language_index[table_index]);
|
||||
found_script[table_index] = (bool) hb_ot_layout_table_select_script (face,
|
||||
table_tag,
|
||||
script_count,
|
||||
script_tags,
|
||||
&script_index[table_index],
|
||||
&chosen_script[table_index]);
|
||||
hb_ot_layout_script_select_language (face,
|
||||
table_tag,
|
||||
script_index[table_index],
|
||||
language_count,
|
||||
language_tags,
|
||||
&language_index[table_index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -150,9 +165,8 @@ void
|
|||
hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
||||
const hb_ot_shape_plan_key_t &key)
|
||||
{
|
||||
static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
|
||||
unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1;
|
||||
unsigned int global_bit_shift = hb_popcount (HB_GLYPH_FLAG_DEFINED);
|
||||
unsigned int global_bit_shift = 8 * sizeof (hb_mask_t) - 1;
|
||||
unsigned int global_bit_mask = 1u << global_bit_shift;
|
||||
|
||||
m.global_mask = global_bit_mask;
|
||||
|
||||
|
|
@ -205,7 +219,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
|
||||
|
||||
/* Allocate bits now */
|
||||
unsigned int next_bit = global_bit_shift + 1;
|
||||
static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
|
||||
unsigned int next_bit = hb_popcount (HB_GLYPH_FLAG_DEFINED) + 1;
|
||||
|
||||
for (unsigned int i = 0; i < feature_infos.length; i++)
|
||||
{
|
||||
|
|
@ -220,7 +235,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
/* Limit bits per feature. */
|
||||
bits_needed = hb_min (HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
|
||||
|
||||
if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
|
||||
if (!info->max_value || next_bit + bits_needed >= global_bit_shift)
|
||||
continue; /* Feature disabled, or not enough bits. */
|
||||
|
||||
|
||||
|
|
@ -274,7 +289,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
}
|
||||
map->_1_mask = (1u << map->shift) & map->mask;
|
||||
map->needs_fallback = !found;
|
||||
|
||||
}
|
||||
feature_infos.shrink (0); /* Done with these */
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,16 @@ struct MathValueRecord
|
|||
hb_position_t get_y_value (hb_font_t *font, const void *base) const
|
||||
{ return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
|
||||
|
||||
MathValueRecord* copy (hb_serialize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->embed (this);
|
||||
if (unlikely (!out)) return_trace (nullptr);
|
||||
out->deviceTable.serialize_copy (c, deviceTable, base, 0, hb_serialize_context_t::Head);
|
||||
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -59,6 +69,29 @@ struct MathValueRecord
|
|||
|
||||
struct MathConstants
|
||||
{
|
||||
MathConstants* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->start_embed (this);
|
||||
if (unlikely (!out)) return_trace (nullptr);
|
||||
|
||||
HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2);
|
||||
if (unlikely (!p)) return_trace (nullptr);
|
||||
memcpy (p, percentScaleDown, HBINT16::static_size * 2);
|
||||
|
||||
HBUINT16 *m = c->allocate_size<HBUINT16> (HBUINT16::static_size * 2);
|
||||
if (unlikely (!m)) return_trace (nullptr);
|
||||
memcpy (m, minHeight, HBUINT16::static_size * 2);
|
||||
|
||||
unsigned count = ARRAY_LENGTH (mathValueRecords);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
if (!c->copy (mathValueRecords[i], this))
|
||||
return_trace (nullptr);
|
||||
|
||||
if (!c->embed (radicalDegreeBottomRaisePercent)) return_trace (nullptr);
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
bool sanitize_math_value_records (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -165,6 +198,28 @@ struct MathConstants
|
|||
|
||||
struct MathItalicsCorrectionInfo
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ hb_zip (this+coverage, italicsCorrection)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (serialize_math_record_array (c->serializer, out->italicsCorrection, this), hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -196,6 +251,28 @@ struct MathItalicsCorrectionInfo
|
|||
|
||||
struct MathTopAccentAttachment
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ hb_zip (this+topAccentCoverage, topAccentAttachment)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (serialize_math_record_array (c->serializer, out->topAccentAttachment, this), hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
out->topAccentCoverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -229,6 +306,22 @@ struct MathTopAccentAttachment
|
|||
|
||||
struct MathKern
|
||||
{
|
||||
MathKern* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->start_embed (this);
|
||||
if (unlikely (!out)) return_trace (nullptr);
|
||||
|
||||
if (unlikely (!c->embed (heightCount))) return_trace (nullptr);
|
||||
|
||||
unsigned count = 2 * heightCount + 1;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
if (!c->copy (mathValueRecordsZ.arrayZ[i], this))
|
||||
return_trace (nullptr);
|
||||
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
bool sanitize_math_value_records (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -295,6 +388,19 @@ struct MathKern
|
|||
|
||||
struct MathKernInfoRecord
|
||||
{
|
||||
MathKernInfoRecord* copy (hb_serialize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->embed (this);
|
||||
if (unlikely (!out)) return_trace (nullptr);
|
||||
|
||||
unsigned count = ARRAY_LENGTH (mathKern);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
out->mathKern[i].serialize_copy (c, mathKern[i], base, 0, hb_serialize_context_t::Head);
|
||||
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -328,6 +434,28 @@ struct MathKernInfoRecord
|
|||
|
||||
struct MathKernInfo
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ hb_zip (this+mathKernCoverage, mathKernInfoRecords)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (serialize_math_record_array (c->serializer, out->mathKernInfoRecords, this), hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
out->mathKernCoverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -365,6 +493,31 @@ struct MathKernInfo
|
|||
|
||||
struct MathGlyphInfo
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->mathItalicsCorrectionInfo.serialize_subset (c, mathItalicsCorrectionInfo, this);
|
||||
out->mathTopAccentAttachment.serialize_subset (c, mathTopAccentAttachment, this);
|
||||
|
||||
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto it =
|
||||
+ hb_iter (this+extendedShapeCoverage)
|
||||
| hb_filter (glyphset)
|
||||
| hb_map_retains_sorting (glyph_map)
|
||||
;
|
||||
|
||||
if (it) out->extendedShapeCoverage.serialize_serialize (c->serializer, it);
|
||||
else out->extendedShapeCoverage = 0;
|
||||
|
||||
out->mathKernInfo.serialize_subset (c, mathKernInfo, this);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -420,14 +573,27 @@ struct MathGlyphVariantRecord
|
|||
{
|
||||
friend struct MathGlyphConstruction;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
const hb_map_t& glyph_map = *c->plan->glyph_map;
|
||||
return_trace (c->serializer->check_assign (out->variantGlyph, glyph_map.get (variantGlyph), HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
void closure_glyphs (hb_set_t *variant_glyphs) const
|
||||
{ variant_glyphs->add (variantGlyph); }
|
||||
|
||||
protected:
|
||||
HBGlyphID variantGlyph; /* Glyph ID for the variant. */
|
||||
HBGlyphID16 variantGlyph; /* Glyph ID for the variant. */
|
||||
HBUINT16 advanceMeasurement; /* Advance width/height, in design units, of the
|
||||
* variant, in the direction of requested
|
||||
* glyph extension. */
|
||||
|
|
@ -450,6 +616,16 @@ struct PartFlags : HBUINT16
|
|||
|
||||
struct MathGlyphPartRecord
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
const hb_map_t& glyph_map = *c->plan->glyph_map;
|
||||
return_trace (c->serializer->check_assign (out->glyph, glyph_map.get (glyph), HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -474,8 +650,11 @@ struct MathGlyphPartRecord
|
|||
(partFlags & PartFlags::Defined);
|
||||
}
|
||||
|
||||
void closure_glyphs (hb_set_t *variant_glyphs) const
|
||||
{ variant_glyphs->add (glyph); }
|
||||
|
||||
protected:
|
||||
HBGlyphID glyph; /* Glyph ID for the part. */
|
||||
HBGlyphID16 glyph; /* Glyph ID for the part. */
|
||||
HBUINT16 startConnectorLength;
|
||||
/* Advance width/ height of the straight bar
|
||||
* connector material, in design units, is at
|
||||
|
|
@ -497,6 +676,20 @@ struct MathGlyphPartRecord
|
|||
|
||||
struct MathGlyphAssembly
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (!c->serializer->copy (italicsCorrection, this)) return_trace (false);
|
||||
if (!c->serializer->copy<HBUINT16> (partRecords.len)) return_trace (false);
|
||||
|
||||
for (const auto& record : partRecords.iter ())
|
||||
if (!record.subset (c)) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -526,6 +719,12 @@ struct MathGlyphAssembly
|
|||
return partRecords.len;
|
||||
}
|
||||
|
||||
void closure_glyphs (hb_set_t *variant_glyphs) const
|
||||
{
|
||||
for (const auto& _ : partRecords.iter ())
|
||||
_.closure_glyphs (variant_glyphs);
|
||||
}
|
||||
|
||||
protected:
|
||||
MathValueRecord
|
||||
italicsCorrection;
|
||||
|
|
@ -543,6 +742,22 @@ struct MathGlyphAssembly
|
|||
|
||||
struct MathGlyphConstruction
|
||||
{
|
||||
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);
|
||||
|
||||
out->glyphAssembly.serialize_subset (c, glyphAssembly, this);
|
||||
|
||||
if (!c->serializer->check_assign (out->mathGlyphVariantRecord.len, mathGlyphVariantRecord.len, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
for (const auto& record : mathGlyphVariantRecord.iter ())
|
||||
if (!record.subset (c)) return_trace (false);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -569,6 +784,14 @@ struct MathGlyphConstruction
|
|||
return mathGlyphVariantRecord.len;
|
||||
}
|
||||
|
||||
void closure_glyphs (hb_set_t *variant_glyphs) const
|
||||
{
|
||||
(this+glyphAssembly).closure_glyphs (variant_glyphs);
|
||||
|
||||
for (const auto& _ : mathGlyphVariantRecord.iter ())
|
||||
_.closure_glyphs (variant_glyphs);
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Offset to MathGlyphAssembly table for this shape - from the beginning of
|
||||
MathGlyphConstruction table. May be NULL. */
|
||||
|
|
@ -583,6 +806,94 @@ struct MathGlyphConstruction
|
|||
|
||||
struct MathVariants
|
||||
{
|
||||
void closure_glyphs (const hb_set_t *glyph_set,
|
||||
hb_set_t *variant_glyphs) const
|
||||
{
|
||||
const hb_array_t<const Offset16To<MathGlyphConstruction>> glyph_construction_offsets = glyphConstruction.as_array (vertGlyphCount + horizGlyphCount);
|
||||
|
||||
if (vertGlyphCoverage)
|
||||
{
|
||||
const auto vert_offsets = glyph_construction_offsets.sub_array (0, vertGlyphCount);
|
||||
+ hb_zip (this+vertGlyphCoverage, vert_offsets)
|
||||
| hb_filter (glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([=] (const MathGlyphConstruction &_) { _.closure_glyphs (variant_glyphs); })
|
||||
;
|
||||
}
|
||||
|
||||
if (horizGlyphCoverage)
|
||||
{
|
||||
const auto hori_offsets = glyph_construction_offsets.sub_array (vertGlyphCount, horizGlyphCount);
|
||||
+ hb_zip (this+horizGlyphCoverage, hori_offsets)
|
||||
| hb_filter (glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([=] (const MathGlyphConstruction &_) { _.closure_glyphs (variant_glyphs); })
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
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 (_);
|
||||
new_coverage.push (new_gid);
|
||||
indices.add (i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
if (!c->serializer->check_assign (out->minConnectorOverlap, minConnectorOverlap, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
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, 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);
|
||||
if (!c->serializer->check_assign (out->horizGlyphCount, new_hori_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
for (unsigned i : indices.iter ())
|
||||
{
|
||||
auto *o = c->serializer->embed (glyphConstruction[i]);
|
||||
if (!o) return_trace (false);
|
||||
o->serialize_subset (c, glyphConstruction[i], this);
|
||||
}
|
||||
|
||||
if (new_vert_coverage)
|
||||
out->vertGlyphCoverage.serialize_serialize (c->serializer, new_vert_coverage.iter ());
|
||||
|
||||
if (new_hori_coverage)
|
||||
out->horizGlyphCoverage.serialize_serialize (c->serializer, new_hori_coverage.iter ());
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize_offsets (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -690,6 +1001,28 @@ struct MATH
|
|||
|
||||
bool has_data () const { return version.to_int (); }
|
||||
|
||||
void closure_glyphs (hb_set_t *glyph_set) const
|
||||
{
|
||||
if (mathVariants)
|
||||
{
|
||||
hb_set_t variant_glyphs;
|
||||
(this+mathVariants).closure_glyphs (glyph_set, &variant_glyphs);
|
||||
hb_set_union (glyph_set, &variant_glyphs);
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->mathConstants.serialize_copy (c->serializer, mathConstants, this, 0, hb_serialize_context_t::Head);
|
||||
out->mathGlyphInfo.serialize_subset (c, mathGlyphInfo, this);
|
||||
out->mathVariants.serialize_subset (c, mathVariants, this);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ struct maxp
|
|||
maxpV1Tail *dest_v1 = c->serializer->embed<maxpV1Tail> (src_v1);
|
||||
if (unlikely (!dest_v1)) return_trace (false);
|
||||
|
||||
if (c->plan->drop_hints)
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
drop_hint_fields (dest_v1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ _hb_ot_metrics_get_position_common (hb_font_t *font,
|
|||
(face->table.TABLE->has_data () && \
|
||||
(position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
|
||||
face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
|
||||
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
|
||||
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) ||
|
||||
GET_METRIC_Y (hhea, ascender);
|
||||
|
|
@ -86,9 +87,13 @@ _hb_ot_metrics_get_position_common (hb_font_t *font,
|
|||
case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP:
|
||||
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoLineGap)) ||
|
||||
GET_METRIC_Y (hhea, lineGap);
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
case HB_OT_METRICS_TAG_VERTICAL_ASCENDER: return GET_METRIC_X (vhea, ascender);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_DESCENDER: return GET_METRIC_X (vhea, descender);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP: return GET_METRIC_X (vhea, lineGap);
|
||||
#endif
|
||||
|
||||
#undef GET_METRIC_Y
|
||||
#undef GET_METRIC_X
|
||||
#undef GET_VAR
|
||||
|
|
@ -158,9 +163,11 @@ hb_ot_metrics_get_position (hb_font_t *font,
|
|||
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: return GET_METRIC_Y (hhea, caretSlopeRise);
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: return GET_METRIC_X (hhea, caretSlopeRun);
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET: return GET_METRIC_X (hhea, caretOffset);
|
||||
#ifndef HB_NO_VERTICAL
|
||||
case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE: return GET_METRIC_X (vhea, caretSlopeRise);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN: return GET_METRIC_Y (vhea, caretSlopeRun);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET: return GET_METRIC_Y (vhea, caretOffset);
|
||||
#endif
|
||||
case HB_OT_METRICS_TAG_X_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sxHeight);
|
||||
case HB_OT_METRICS_TAG_CAP_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sCapHeight);
|
||||
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE: return GET_METRIC_X (OS2, ySubscriptXSize);
|
||||
|
|
|
|||
|
|
@ -249,7 +249,11 @@ struct name
|
|||
+ nameRecordZ.as_array (count)
|
||||
| hb_filter (c->plan->name_ids, &NameRecord::nameID)
|
||||
| hb_filter (c->plan->name_languages, &NameRecord::languageID)
|
||||
| hb_filter ([&] (const NameRecord& namerecord) { return c->plan->name_legacy || namerecord.isUnicode (); })
|
||||
| hb_filter ([&] (const NameRecord& namerecord) {
|
||||
return
|
||||
(c->plan->flags & HB_SUBSET_FLAGS_NAME_LEGACY)
|
||||
|| namerecord.isUnicode ();
|
||||
})
|
||||
;
|
||||
|
||||
name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset));
|
||||
|
|
|
|||
|
|
@ -156,7 +156,8 @@ hb_ot_name_get_utf (hb_face_t *face,
|
|||
*
|
||||
* Fetches a font name from the OpenType 'name' table.
|
||||
* If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
|
||||
* Returns string in UTF-8 encoding.
|
||||
* Returns string in UTF-8 encoding. A NUL terminator is always written
|
||||
* for convenience, and isn't included in the output @text_size.
|
||||
*
|
||||
* Returns: full length of the requested string, or 0 if not found.
|
||||
* Since: 2.1.0
|
||||
|
|
@ -183,7 +184,8 @@ hb_ot_name_get_utf8 (hb_face_t *face,
|
|||
*
|
||||
* Fetches a font name from the OpenType 'name' table.
|
||||
* If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
|
||||
* Returns string in UTF-16 encoding.
|
||||
* Returns string in UTF-16 encoding. A NUL terminator is always written
|
||||
* for convenience, and isn't included in the output @text_size.
|
||||
*
|
||||
* Returns: full length of the requested string, or 0 if not found.
|
||||
* Since: 2.1.0
|
||||
|
|
@ -209,7 +211,8 @@ hb_ot_name_get_utf16 (hb_face_t *face,
|
|||
*
|
||||
* Fetches a font name from the OpenType 'name' table.
|
||||
* If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
|
||||
* Returns string in UTF-32 encoding.
|
||||
* Returns string in UTF-32 encoding. A NUL terminator is always written
|
||||
* for convenience, and isn't included in the output @text_size.
|
||||
*
|
||||
* Returns: full length of the requested string, or 0 if not found.
|
||||
* Since: 2.1.0
|
||||
|
|
|
|||
|
|
@ -36,12 +36,42 @@ HB_BEGIN_DECLS
|
|||
|
||||
/**
|
||||
* hb_ot_name_id_t:
|
||||
* @HB_OT_NAME_ID_COPYRIGHT: Copyright notice
|
||||
* @HB_OT_NAME_ID_FONT_FAMILY: Font Family name
|
||||
* @HB_OT_NAME_ID_FONT_SUBFAMILY: Font Subfamily name
|
||||
* @HB_OT_NAME_ID_UNIQUE_ID: Unique font identifier
|
||||
* @HB_OT_NAME_ID_FULL_NAME: Full font name that reflects
|
||||
* all family and relevant subfamily descriptors
|
||||
* @HB_OT_NAME_ID_VERSION_STRING: Version string
|
||||
* @HB_OT_NAME_ID_POSTSCRIPT_NAME: PostScript name for the font
|
||||
* @HB_OT_NAME_ID_TRADEMARK: Trademark
|
||||
* @HB_OT_NAME_ID_MANUFACTURER: Manufacturer Name
|
||||
* @HB_OT_NAME_ID_DESIGNER: Designer
|
||||
* @HB_OT_NAME_ID_DESCRIPTION: Description
|
||||
* @HB_OT_NAME_ID_VENDOR_URL: URL of font vendor
|
||||
* @HB_OT_NAME_ID_DESIGNER_URL: URL of typeface designer
|
||||
* @HB_OT_NAME_ID_LICENSE: License Description
|
||||
* @HB_OT_NAME_ID_LICENSE_URL: URL where additional licensing
|
||||
* information can be found
|
||||
* @HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY: Typographic Family name
|
||||
* @HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY: Typographic Subfamily name
|
||||
* @HB_OT_NAME_ID_MAC_FULL_NAME: Compatible Full Name for MacOS
|
||||
* @HB_OT_NAME_ID_SAMPLE_TEXT: Sample text
|
||||
* @HB_OT_NAME_ID_CID_FINDFONT_NAME: PostScript CID findfont name
|
||||
* @HB_OT_NAME_ID_WWS_FAMILY: WWS Family Name
|
||||
* @HB_OT_NAME_ID_WWS_SUBFAMILY: WWS Subfamily Name
|
||||
* @HB_OT_NAME_ID_LIGHT_BACKGROUND: Light Background Palette
|
||||
* @HB_OT_NAME_ID_DARK_BACKGROUND: Dark Background Palette
|
||||
* @HB_OT_NAME_ID_VARIATIONS_PS_PREFIX: Variations PostScript Name Prefix
|
||||
* @HB_OT_NAME_ID_INVALID: Value to represent a nonexistent name ID.
|
||||
*
|
||||
* An integral type representing an OpenType 'name' table name identifier.
|
||||
* There are predefined name IDs, as well as name IDs return from other
|
||||
* API. These can be used to fetch name strings from a font face.
|
||||
*
|
||||
* For more information on these fields, see the
|
||||
* [OpenType spec](https://docs.microsoft.com/en-us/typography/opentype/spec/name#name-ids).
|
||||
*
|
||||
* Since: 2.0.0
|
||||
**/
|
||||
enum
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-os2-unicode-ranges.hh"
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
|
||||
#include "hb-set.hh"
|
||||
|
||||
|
|
@ -172,34 +171,17 @@ struct OS2
|
|||
TRACE_SUBSET (this);
|
||||
OS2 *os2_prime = c->serializer->embed (this);
|
||||
if (unlikely (!os2_prime)) return_trace (false);
|
||||
if (!c->plan->prune_unicode_ranges) return_trace (true);
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
|
||||
return_trace (true);
|
||||
|
||||
hb_set_t unicodes;
|
||||
if (!c->plan->glyphs_requested->is_empty ())
|
||||
{
|
||||
hb_map_t unicode_glyphid_map;
|
||||
|
||||
OT::cmap::accelerator_t cmap;
|
||||
cmap.init (c->plan->source);
|
||||
cmap.collect_mapping (&unicodes, &unicode_glyphid_map);
|
||||
cmap.fini ();
|
||||
|
||||
hb_set_set (&unicodes, c->plan->unicodes);
|
||||
|
||||
+ unicode_glyphid_map.iter ()
|
||||
| hb_filter (c->plan->glyphs_requested, hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_sink (unicodes)
|
||||
;
|
||||
}
|
||||
/* when --gids option is not used, no need to do collect_mapping that is
|
||||
* iterating all codepoints in each subtable, which is not efficient */
|
||||
uint16_t min_cp, max_cp;
|
||||
find_min_and_max_codepoint (unicodes.is_empty () ? c->plan->unicodes : &unicodes, &min_cp, &max_cp);
|
||||
find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
|
||||
os2_prime->usFirstCharIndex = min_cp;
|
||||
os2_prime->usLastCharIndex = max_cp;
|
||||
|
||||
_update_unicode_ranges (unicodes.is_empty () ? c->plan->unicodes : &unicodes, os2_prime->ulUnicodeRange);
|
||||
_update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
|||
137
gfx/harfbuzz/src/hb-ot-post-table-v2subset.hh
Normal file
137
gfx/harfbuzz/src/hb-ot-post-table-v2subset.hh
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* 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_POST_TABLE_V2SUBSET_HH
|
||||
#define HB_OT_POST_TABLE_V2SUBSET_HH
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-post-table.hh"
|
||||
|
||||
/*
|
||||
* post -- PostScript
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/post
|
||||
*/
|
||||
|
||||
namespace OT {
|
||||
template<typename Iterator>
|
||||
HB_INTERNAL bool postV2Tail::serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
const void* _post) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->start_embed (this);
|
||||
if (unlikely (!c->check_success (out))) return_trace (false);
|
||||
if (!out->glyphNameIndex.serialize (c, + it
|
||||
| hb_map (hb_second)))
|
||||
return_trace (false);
|
||||
|
||||
hb_set_t copied_indices;
|
||||
for (const auto& _ : + it )
|
||||
{
|
||||
unsigned glyph_id = _.first;
|
||||
unsigned new_index = _.second;
|
||||
|
||||
if (new_index < 258) continue;
|
||||
if (copied_indices.has (new_index)) continue;
|
||||
copied_indices.add (new_index);
|
||||
|
||||
hb_bytes_t s = reinterpret_cast<const post::accelerator_t*> (_post)->find_glyph_name (glyph_id);
|
||||
HBUINT8 *o = c->allocate_size<HBUINT8> (HBUINT8::static_size * (s.length + 1));
|
||||
if (unlikely (!o)) return_trace (false);
|
||||
if (!c->check_assign (o[0], s.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
|
||||
memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
|
||||
unsigned num_glyphs = c->plan->num_output_glyphs ();
|
||||
hb_map_t old_new_index_map, old_gid_new_index_map;
|
||||
unsigned i = 0;
|
||||
|
||||
post::accelerator_t _post;
|
||||
_post.init (c->plan->source);
|
||||
|
||||
hb_hashmap_t<hb_bytes_t, unsigned, std::nullptr_t, unsigned, nullptr, (unsigned)-1> glyph_name_to_new_index;
|
||||
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
|
||||
unsigned old_index = glyphNameIndex[old_gid];
|
||||
|
||||
unsigned new_index;
|
||||
if (old_index <= 257) new_index = old_index;
|
||||
else if (old_new_index_map.has (old_index)) new_index = old_new_index_map.get (old_index);
|
||||
else
|
||||
{
|
||||
hb_bytes_t s = _post.find_glyph_name (old_gid);
|
||||
new_index = glyph_name_to_new_index.get (s);
|
||||
if (new_index == (unsigned)-1)
|
||||
{
|
||||
int standard_glyph_index = -1;
|
||||
for (unsigned i = 0; i < format1_names_length; i++)
|
||||
{
|
||||
if (s == format1_names (i))
|
||||
{
|
||||
standard_glyph_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (standard_glyph_index == -1)
|
||||
{
|
||||
new_index = 258 + i;
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{ new_index = standard_glyph_index; }
|
||||
glyph_name_to_new_index.set (s, new_index);
|
||||
}
|
||||
old_new_index_map.set (old_index, new_index);
|
||||
}
|
||||
old_gid_new_index_map.set (old_gid, new_index);
|
||||
}
|
||||
|
||||
auto index_iter =
|
||||
+ hb_range (num_glyphs)
|
||||
| hb_map (reverse_glyph_map)
|
||||
| hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
|
||||
{
|
||||
unsigned new_index = old_gid_new_index_map.get (old_gid);
|
||||
return hb_pair_t<unsigned, unsigned> (old_gid, new_index);
|
||||
})
|
||||
;
|
||||
|
||||
bool ret = serialize (c->serializer, index_iter, &_post);
|
||||
_post.fini ();
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
} /* namespace OT */
|
||||
#endif /* HB_OT_POST_TABLE_V2SUBSET_HH */
|
||||
|
|
@ -55,6 +55,13 @@ struct postV2Tail
|
|||
return_trace (glyphNameIndex.sanitize (c));
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
const void* _post) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const;
|
||||
|
||||
protected:
|
||||
Array16Of<HBUINT16> glyphNameIndex; /* This is not an offset, but is the
|
||||
* ordinal number of the glyph in 'post'
|
||||
|
|
@ -71,13 +78,18 @@ struct post
|
|||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
|
||||
|
||||
void serialize (hb_serialize_context_t *c) const
|
||||
bool serialize (hb_serialize_context_t *c, bool glyph_names) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
post *post_prime = c->allocate_min<post> ();
|
||||
if (unlikely (!post_prime)) return;
|
||||
if (unlikely (!post_prime)) return_trace (false);
|
||||
|
||||
memcpy (post_prime, this, post::min_size);
|
||||
post_prime->version.major = 3; // Version 3 does not have any glyph names.
|
||||
if (!glyph_names)
|
||||
return_trace (c->check_assign (post_prime->version.major, 3,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW)); // Version 3 does not have any glyph names.
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
|
|
@ -86,13 +98,19 @@ struct post
|
|||
post *post_prime = c->serializer->start_embed<post> ();
|
||||
if (unlikely (!post_prime)) return_trace (false);
|
||||
|
||||
serialize (c->serializer);
|
||||
bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
|
||||
if (!serialize (c->serializer, glyph_names))
|
||||
return_trace (false);
|
||||
|
||||
if (glyph_names && version.major == 2)
|
||||
return_trace (v2X.subset (c));
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
friend struct postV2Tail;
|
||||
void init (hb_face_t *face)
|
||||
{
|
||||
index_to_offset.init ();
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
|
|||
hb_font_t *font,
|
||||
unsigned int feature_index)
|
||||
{
|
||||
OT::HBGlyphID glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
|
||||
OT::HBGlyphID substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
|
||||
OT::HBGlyphID16 glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
|
||||
OT::HBGlyphID16 substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
|
||||
unsigned int num_glyphs = 0;
|
||||
|
||||
/* Populate arrays */
|
||||
|
|
@ -78,7 +78,7 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
|
|||
/* Bubble-sort or something equally good!
|
||||
* May not be good-enough for presidential candidate interviews, but good-enough for us... */
|
||||
hb_stable_sort (&glyphs[0], num_glyphs,
|
||||
(int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID::cmp,
|
||||
(int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp,
|
||||
&substitutes[0]);
|
||||
|
||||
|
||||
|
|
@ -99,15 +99,15 @@ static OT::SubstLookup *
|
|||
arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font)
|
||||
{
|
||||
OT::HBGlyphID first_glyphs[ARRAY_LENGTH_CONST (ligature_table)];
|
||||
OT::HBGlyphID16 first_glyphs[ARRAY_LENGTH_CONST (ligature_table)];
|
||||
unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)];
|
||||
unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)];
|
||||
unsigned int num_first_glyphs = 0;
|
||||
|
||||
/* We know that all our ligatures are 2-component */
|
||||
OT::HBGlyphID ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)];
|
||||
OT::HBGlyphID16 ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)];
|
||||
unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)];
|
||||
OT::HBGlyphID component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */];
|
||||
OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */];
|
||||
unsigned int num_ligatures = 0;
|
||||
|
||||
/* Populate arrays */
|
||||
|
|
@ -125,7 +125,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
|
|||
num_first_glyphs++;
|
||||
}
|
||||
hb_stable_sort (&first_glyphs[0], num_first_glyphs,
|
||||
(int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID::cmp,
|
||||
(int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp,
|
||||
&first_glyphs_indirection[0]);
|
||||
|
||||
/* Now that the first-glyphs are sorted, walk again, populate ligatures. */
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
*
|
||||
* on files with these headers:
|
||||
*
|
||||
* # ArabicShaping-13.0.0.txt
|
||||
* # Date: 2020-01-31, 23:55:00 GMT [KW, RP]
|
||||
* # Scripts-13.0.0.txt
|
||||
* # Date: 2020-01-22, 00:07:43 GMT
|
||||
* # ArabicShaping-14.0.0.txt
|
||||
* # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
|
||||
* # Scripts-14.0.0.txt
|
||||
* # Date: 2021-07-10, 00:35:31 GMT
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
|
||||
|
|
@ -29,6 +29,7 @@ has_arabic_joining (hb_script_t script)
|
|||
case HB_SCRIPT_MANICHAEAN:
|
||||
case HB_SCRIPT_MONGOLIAN:
|
||||
case HB_SCRIPT_NKO:
|
||||
case HB_SCRIPT_OLD_UYGHUR:
|
||||
case HB_SCRIPT_PHAGS_PA:
|
||||
case HB_SCRIPT_PSALTER_PAHLAVI:
|
||||
case HB_SCRIPT_SOGDIAN:
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
*
|
||||
* on files with these headers:
|
||||
*
|
||||
* # ArabicShaping-13.0.0.txt
|
||||
* # Date: 2020-01-31, 23:55:00 GMT [KW, RP]
|
||||
* # Blocks-13.0.0.txt
|
||||
* # Date: 2019-07-10, 19:06:00 GMT [KW]
|
||||
* # ArabicShaping-14.0.0.txt
|
||||
* # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
|
||||
* # Blocks-14.0.0.txt
|
||||
* # Date: 2021-01-22, 23:29:00 GMT [KW]
|
||||
* UnicodeData.txt does not have a header.
|
||||
*/
|
||||
|
||||
|
|
@ -75,13 +75,17 @@ static const uint8_t joining_table[] =
|
|||
|
||||
/* Syriac Supplement */
|
||||
|
||||
/* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,
|
||||
|
||||
/* Arabic Extended-B */
|
||||
|
||||
/* 0860 */ R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,
|
||||
/* 0880 */ R,R,R,C,C,C,D,U,U,D,D,D,D,D,R,X,U,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
|
||||
/* Arabic Extended-A */
|
||||
|
||||
/* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,X,D,D,D,R,D,D,D,D,D,D,
|
||||
/* 08C0 */ D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,D,D,D,D,R,D,D,D,D,D,D,
|
||||
/* 08C0 */ D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 08E0 */ X,X,U,
|
||||
|
||||
#define joining_offset_0x1806u 739
|
||||
|
|
@ -137,23 +141,28 @@ static const uint8_t joining_table[] =
|
|||
/* Sogdian */
|
||||
|
||||
/* 10F20 */ D,D,D,R,D,D,D,D,D,D,D,D,D,D,D,D,
|
||||
/* 10F40 */ D,D,D,D,D,U,X,X,X,X,X,X,X,X,X,X,X,D,D,D,R,
|
||||
/* 10F40 */ D,D,D,D,D,U,X,X,X,X,X,X,X,X,X,X,X,D,D,D,R,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 10F60 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
|
||||
#define joining_offset_0x10fb0u 1219
|
||||
/* Old Uyghur */
|
||||
|
||||
/* 10F60 */ D,D,D,D,R,R,D,D,D,D,D,D,D,D,D,D,
|
||||
/* 10F80 */ D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
/* 10FA0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
|
||||
|
||||
/* Chorasmian */
|
||||
|
||||
/* 10FA0 */ D,U,D,D,R,R,R,U,D,R,R,D,D,R,D,D,
|
||||
/* 10FC0 */ U,D,R,R,D,U,U,U,U,R,D,L,
|
||||
|
||||
#define joining_offset_0x110bdu 1247
|
||||
#define joining_offset_0x110bdu 1338
|
||||
|
||||
/* Kaithi */
|
||||
|
||||
/* 110A0 */ U,X,X,
|
||||
/* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U,
|
||||
|
||||
#define joining_offset_0x1e900u 1264
|
||||
#define joining_offset_0x1e900u 1355
|
||||
|
||||
/* Adlam */
|
||||
|
||||
|
|
@ -161,7 +170,7 @@ static const uint8_t joining_table[] =
|
|||
/* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
|
||||
/* 1E940 */ D,D,D,D,X,X,X,X,X,X,X,T,
|
||||
|
||||
}; /* Table items: 1340; occupancy: 57% */
|
||||
}; /* Table items: 1431; occupancy: 57% */
|
||||
|
||||
|
||||
static unsigned int
|
||||
|
|
@ -189,8 +198,7 @@ joining_type (hb_codepoint_t u)
|
|||
if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10F54u)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10FB0u, 0x10FCBu)) return joining_table[u - 0x10FB0u + joining_offset_0x10fb0u];
|
||||
if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10FCBu)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
|
||||
break;
|
||||
|
||||
case 0x11u:
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ mongolian_variation_selectors (hb_buffer_t *buffer)
|
|||
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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
*
|
||||
* on files with these headers:
|
||||
*
|
||||
* # IndicSyllabicCategory-13.0.0.txt
|
||||
* # Date: 2019-07-22, 19:55:00 GMT [KW, RP]
|
||||
* # IndicPositionalCategory-13.0.0.txt
|
||||
* # Date: 2019-07-23, 00:01:00 GMT [KW, RP]
|
||||
* # Blocks-13.0.0.txt
|
||||
* # Date: 2019-07-10, 19:06:00 GMT [KW]
|
||||
* # IndicSyllabicCategory-14.0.0.txt
|
||||
* # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
|
||||
* # IndicPositionalCategory-14.0.0.txt
|
||||
* # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
|
||||
* # Blocks-14.0.0.txt
|
||||
* # Date: 2021-01-22, 23:29:00 GMT [KW]
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
|
@ -27,9 +27,9 @@
|
|||
#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 91 chars; Bindu */
|
||||
#define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */
|
||||
#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 59 chars; Cantillation_Mark */
|
||||
#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2195 chars; Consonant */
|
||||
#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 12 chars; Consonant_Dead */
|
||||
#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 67 chars; Consonant_Final */
|
||||
#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2206 chars; Consonant */
|
||||
#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 14 chars; Consonant_Dead */
|
||||
#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 70 chars; Consonant_Final */
|
||||
#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */
|
||||
#define ISC_CIP INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED /* 1 chars; Consonant_Initial_Postfixed */
|
||||
#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */
|
||||
|
|
@ -38,18 +38,18 @@
|
|||
#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 3 chars; Consonant_Preceding_Repha */
|
||||
#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 10 chars; Consonant_Prefixed */
|
||||
#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 94 chars; Consonant_Subjoined */
|
||||
#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */
|
||||
#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 1 chars; Consonant_Succeeding_Repha */
|
||||
#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 8 chars; Consonant_With_Stacker */
|
||||
#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 3 chars; Gemination_Mark */
|
||||
#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 12 chars; Invisible_Stacker */
|
||||
#define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */
|
||||
#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
|
||||
#define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */
|
||||
#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 31 chars; Nukta */
|
||||
#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 32 chars; Nukta */
|
||||
#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 491 chars; Number */
|
||||
#define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */
|
||||
#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
|
||||
#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 23 chars; Pure_Killer */
|
||||
#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 25 chars; Pure_Killer */
|
||||
#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */
|
||||
#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 25 chars; Syllable_Modifier */
|
||||
#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */
|
||||
|
|
@ -57,18 +57,18 @@
|
|||
#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 27 chars; Virama */
|
||||
#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 35 chars; Visarga */
|
||||
#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */
|
||||
#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 683 chars; Vowel_Dependent */
|
||||
#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 484 chars; Vowel_Independent */
|
||||
#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 686 chars; Vowel_Dependent */
|
||||
#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 486 chars; Vowel_Independent */
|
||||
|
||||
#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 351 chars; Bottom */
|
||||
#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 352 chars; Bottom */
|
||||
#define IMC_BL INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT /* 1 chars; Bottom_And_Left */
|
||||
#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 4 chars; Bottom_And_Right */
|
||||
#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 64 chars; Left */
|
||||
#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 22 chars; Left_And_Right */
|
||||
#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
|
||||
#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */
|
||||
#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 288 chars; Right */
|
||||
#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 415 chars; Top */
|
||||
#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 290 chars; Right */
|
||||
#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 418 chars; Top */
|
||||
#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */
|
||||
#define IMC_TBL INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT /* 2 chars; Top_And_Bottom_And_Left */
|
||||
#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
|
||||
|
|
@ -231,11 +231,11 @@ static const uint16_t indic_table[] = {
|
|||
/* 0C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
|
||||
/* 0C28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
|
||||
/* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
|
||||
/* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(A,x), _(M,T), _(M,T),
|
||||
/* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,T), _(M,T),
|
||||
/* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T),
|
||||
/* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x),
|
||||
/* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x),
|
||||
/* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
|
||||
/* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(CD,x), _(x,x), _(x,x),
|
||||
/* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
|
||||
/* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
|
||||
/* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
|
||||
|
|
@ -254,7 +254,7 @@ static const uint16_t indic_table[] = {
|
|||
/* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR),
|
||||
/* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x),
|
||||
/* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x),
|
||||
/* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(x,x),
|
||||
/* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(C,x), _(x,x),
|
||||
/* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
|
||||
/* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
|
||||
/* 0CF0 */ _(x,x),_(CWS,x),_(CWS,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
|
||||
|
|
@ -402,7 +402,7 @@ static const uint16_t indic_table[] = {
|
|||
/* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x),
|
||||
/* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x),
|
||||
|
||||
}; /* Table items: 1792; occupancy: 70% */
|
||||
}; /* Table items: 1792; occupancy: 71% */
|
||||
|
||||
uint16_t
|
||||
hb_indic_get_categories (hb_codepoint_t u)
|
||||
|
|
|
|||
|
|
@ -106,7 +106,8 @@ indic_features[] =
|
|||
{
|
||||
/*
|
||||
* Basic features.
|
||||
* These features are applied in order, one at a time, after initial_reordering.
|
||||
* These features are applied in order, one at a time, after initial_reordering,
|
||||
* constrained to the syllable.
|
||||
*/
|
||||
{HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
|
||||
{HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
|
||||
|
|
@ -121,8 +122,8 @@ indic_features[] =
|
|||
{HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
|
||||
/*
|
||||
* Other features.
|
||||
* These features are applied all at once, after final_reordering
|
||||
* but before clearing syllables.
|
||||
* These features are applied all at once, after final_reordering, constrained
|
||||
* to the syllable.
|
||||
* Default Bengali font in Windows for example has intermixed
|
||||
* lookups for init,pres,abvs,blws features.
|
||||
*/
|
||||
|
|
@ -201,9 +202,6 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +1,30 @@
|
|||
|
||||
#line 1 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
/*
|
||||
* Copyright © 2011,2012 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.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
* Copyright © 2011,2012 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.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
|
||||
#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
|
||||
|
|
@ -31,13 +32,13 @@
|
|||
#include "hb.hh"
|
||||
|
||||
enum khmer_syllable_type_t {
|
||||
khmer_consonant_syllable,
|
||||
khmer_broken_cluster,
|
||||
khmer_non_khmer_cluster,
|
||||
khmer_consonant_syllable,
|
||||
khmer_broken_cluster,
|
||||
khmer_non_khmer_cluster,
|
||||
};
|
||||
|
||||
|
||||
#line 41 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
#line 42 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
#define khmer_syllable_machine_ex_C 1u
|
||||
#define khmer_syllable_machine_ex_Coeng 14u
|
||||
#define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u
|
||||
|
|
@ -55,125 +56,180 @@ enum khmer_syllable_type_t {
|
|||
#define khmer_syllable_machine_ex_ZWNJ 5u
|
||||
|
||||
|
||||
#line 59 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
#line 60 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
static const unsigned char _khmer_syllable_machine_trans_keys[] = {
|
||||
2u, 8u, 2u, 6u, 2u, 8u, 2u, 6u,
|
||||
0u, 0u, 2u, 6u, 2u, 8u, 2u, 6u,
|
||||
2u, 8u, 2u, 6u, 2u, 6u, 2u, 8u,
|
||||
2u, 6u, 0u, 0u, 2u, 6u, 2u, 8u,
|
||||
2u, 6u, 2u, 8u, 2u, 6u, 2u, 8u,
|
||||
0u, 11u, 2u, 11u, 2u, 11u, 2u, 11u,
|
||||
7u, 7u, 2u, 7u, 2u, 11u, 2u, 11u,
|
||||
2u, 11u, 0u, 0u, 2u, 8u, 2u, 11u,
|
||||
2u, 11u, 7u, 7u, 2u, 7u, 2u, 11u,
|
||||
2u, 11u, 0u, 0u, 2u, 11u, 2u, 11u,
|
||||
0u
|
||||
5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u,
|
||||
5u, 26u, 5u, 21u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u,
|
||||
5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 29u, 5u, 29u, 5u, 29u, 5u, 29u,
|
||||
22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 26u, 5u, 29u,
|
||||
5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 5u, 29u,
|
||||
0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_char_class[] = {
|
||||
0, 0, 1, 1, 2, 2, 1, 1,
|
||||
1, 1, 3, 3, 1, 4, 1, 0,
|
||||
1, 1, 1, 5, 6, 7, 1, 1,
|
||||
1, 8, 9, 10, 11, 0
|
||||
static const char _khmer_syllable_machine_key_spans[] = {
|
||||
22, 17, 22, 17, 16, 17, 22, 17,
|
||||
22, 17, 17, 22, 17, 16, 17, 22,
|
||||
17, 22, 17, 22, 29, 25, 25, 25,
|
||||
1, 18, 25, 25, 25, 16, 22, 25,
|
||||
25, 1, 18, 25, 25, 16, 25, 25
|
||||
};
|
||||
|
||||
static const short _khmer_syllable_machine_index_offsets[] = {
|
||||
0, 7, 12, 19, 24, 25, 30, 37,
|
||||
42, 49, 54, 59, 66, 71, 72, 77,
|
||||
84, 89, 96, 101, 108, 120, 130, 140,
|
||||
150, 151, 157, 167, 177, 187, 188, 195,
|
||||
205, 215, 216, 222, 232, 242, 243, 253,
|
||||
0
|
||||
0, 23, 41, 64, 82, 99, 117, 140,
|
||||
158, 181, 199, 217, 240, 258, 275, 293,
|
||||
316, 334, 357, 375, 398, 428, 454, 480,
|
||||
506, 508, 527, 553, 579, 605, 622, 645,
|
||||
671, 697, 699, 718, 744, 770, 787, 813
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_indicies[] = {
|
||||
1, 0, 0, 2, 3, 0, 4, 1,
|
||||
0, 0, 0, 3, 1, 0, 0, 0,
|
||||
3, 0, 4, 5, 0, 0, 0, 4,
|
||||
6, 7, 0, 0, 0, 8, 9, 0,
|
||||
0, 0, 10, 0, 4, 9, 0, 0,
|
||||
0, 10, 11, 0, 0, 0, 12, 0,
|
||||
4, 11, 0, 0, 0, 12, 14, 13,
|
||||
13, 13, 15, 14, 16, 16, 16, 15,
|
||||
16, 17, 18, 16, 16, 16, 17, 19,
|
||||
20, 16, 16, 16, 21, 22, 16, 16,
|
||||
16, 23, 16, 17, 22, 16, 16, 16,
|
||||
23, 24, 16, 16, 16, 25, 16, 17,
|
||||
24, 16, 16, 16, 25, 14, 16, 16,
|
||||
26, 15, 16, 17, 29, 28, 30, 2,
|
||||
31, 28, 15, 19, 17, 23, 25, 21,
|
||||
33, 32, 34, 2, 3, 6, 4, 10,
|
||||
12, 8, 35, 32, 36, 32, 3, 6,
|
||||
4, 10, 12, 8, 5, 32, 36, 32,
|
||||
4, 6, 32, 32, 32, 8, 6, 7,
|
||||
32, 36, 32, 8, 6, 37, 32, 36,
|
||||
32, 10, 6, 4, 32, 32, 8, 38,
|
||||
32, 36, 32, 12, 6, 4, 10, 32,
|
||||
8, 35, 32, 34, 32, 3, 6, 4,
|
||||
10, 12, 8, 29, 14, 39, 39, 39,
|
||||
15, 39, 17, 41, 40, 42, 40, 15,
|
||||
19, 17, 23, 25, 21, 18, 40, 42,
|
||||
40, 17, 19, 40, 40, 40, 21, 19,
|
||||
20, 40, 42, 40, 21, 19, 43, 40,
|
||||
42, 40, 23, 19, 17, 40, 40, 21,
|
||||
44, 40, 42, 40, 25, 19, 17, 23,
|
||||
40, 21, 45, 46, 40, 31, 26, 15,
|
||||
19, 17, 23, 25, 21, 41, 40, 31,
|
||||
40, 15, 19, 17, 23, 25, 21, 0
|
||||
static const char _khmer_syllable_machine_indicies[] = {
|
||||
1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 2,
|
||||
3, 0, 0, 0, 0, 4, 0, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 3,
|
||||
0, 1, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 3, 0, 0, 0, 0, 4, 0,
|
||||
5, 5, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 0, 6, 6, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 6, 0, 7, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 8, 0, 9, 9, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 10, 0, 0,
|
||||
0, 0, 4, 0, 9, 9, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 10, 0, 11, 11,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 12, 0,
|
||||
0, 0, 0, 4, 0, 11, 11, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 12, 0, 14,
|
||||
14, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 15,
|
||||
13, 14, 14, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 15, 16, 16, 16, 16, 17, 16,
|
||||
18, 18, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
17, 16, 19, 19, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 19, 16, 20, 20, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 21, 16, 22, 22, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 23, 16, 16,
|
||||
16, 16, 17, 16, 22, 22, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 23, 16, 24, 24,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 25, 16,
|
||||
16, 16, 16, 17, 16, 24, 24, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 25, 16, 14,
|
||||
14, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 26, 15,
|
||||
16, 16, 16, 16, 17, 16, 28, 28,
|
||||
27, 27, 29, 29, 27, 27, 27, 27,
|
||||
2, 2, 27, 30, 27, 28, 27, 27,
|
||||
27, 27, 15, 19, 27, 27, 27, 17,
|
||||
23, 25, 21, 27, 32, 32, 31, 31,
|
||||
31, 31, 31, 31, 31, 33, 31, 31,
|
||||
31, 31, 31, 2, 3, 6, 31, 31,
|
||||
31, 4, 10, 12, 8, 31, 34, 34,
|
||||
31, 31, 31, 31, 31, 31, 31, 35,
|
||||
31, 31, 31, 31, 31, 31, 3, 6,
|
||||
31, 31, 31, 4, 10, 12, 8, 31,
|
||||
5, 5, 31, 31, 31, 31, 31, 31,
|
||||
31, 35, 31, 31, 31, 31, 31, 31,
|
||||
4, 6, 31, 31, 31, 31, 31, 31,
|
||||
8, 31, 6, 31, 7, 7, 31, 31,
|
||||
31, 31, 31, 31, 31, 35, 31, 31,
|
||||
31, 31, 31, 31, 8, 6, 31, 36,
|
||||
36, 31, 31, 31, 31, 31, 31, 31,
|
||||
35, 31, 31, 31, 31, 31, 31, 10,
|
||||
6, 31, 31, 31, 4, 31, 31, 8,
|
||||
31, 37, 37, 31, 31, 31, 31, 31,
|
||||
31, 31, 35, 31, 31, 31, 31, 31,
|
||||
31, 12, 6, 31, 31, 31, 4, 10,
|
||||
31, 8, 31, 34, 34, 31, 31, 31,
|
||||
31, 31, 31, 31, 33, 31, 31, 31,
|
||||
31, 31, 31, 3, 6, 31, 31, 31,
|
||||
4, 10, 12, 8, 31, 28, 28, 31,
|
||||
31, 31, 31, 31, 31, 31, 31, 31,
|
||||
31, 31, 31, 31, 28, 31, 14, 14,
|
||||
38, 38, 38, 38, 38, 38, 38, 38,
|
||||
38, 38, 38, 38, 38, 38, 15, 38,
|
||||
38, 38, 38, 17, 38, 40, 40, 39,
|
||||
39, 39, 39, 39, 39, 39, 41, 39,
|
||||
39, 39, 39, 39, 39, 15, 19, 39,
|
||||
39, 39, 17, 23, 25, 21, 39, 18,
|
||||
18, 39, 39, 39, 39, 39, 39, 39,
|
||||
41, 39, 39, 39, 39, 39, 39, 17,
|
||||
19, 39, 39, 39, 39, 39, 39, 21,
|
||||
39, 19, 39, 20, 20, 39, 39, 39,
|
||||
39, 39, 39, 39, 41, 39, 39, 39,
|
||||
39, 39, 39, 21, 19, 39, 42, 42,
|
||||
39, 39, 39, 39, 39, 39, 39, 41,
|
||||
39, 39, 39, 39, 39, 39, 23, 19,
|
||||
39, 39, 39, 17, 39, 39, 21, 39,
|
||||
43, 43, 39, 39, 39, 39, 39, 39,
|
||||
39, 41, 39, 39, 39, 39, 39, 39,
|
||||
25, 19, 39, 39, 39, 17, 23, 39,
|
||||
21, 39, 44, 44, 39, 39, 39, 39,
|
||||
39, 39, 39, 39, 39, 39, 39, 39,
|
||||
39, 44, 39, 45, 45, 39, 39, 39,
|
||||
39, 39, 39, 39, 30, 39, 39, 39,
|
||||
39, 39, 26, 15, 19, 39, 39, 39,
|
||||
17, 23, 25, 21, 39, 40, 40, 39,
|
||||
39, 39, 39, 39, 39, 39, 30, 39,
|
||||
39, 39, 39, 39, 39, 15, 19, 39,
|
||||
39, 39, 17, 23, 25, 21, 39, 0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_index_defaults[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 13, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 28, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 39, 40,
|
||||
40, 40, 40, 40, 40, 40, 40, 40,
|
||||
0
|
||||
static const char _khmer_syllable_machine_trans_targs[] = {
|
||||
20, 1, 28, 22, 23, 3, 24, 5,
|
||||
25, 7, 26, 9, 27, 20, 10, 31,
|
||||
20, 32, 12, 33, 14, 34, 16, 35,
|
||||
18, 36, 39, 20, 21, 30, 37, 20,
|
||||
0, 29, 2, 4, 6, 8, 20, 20,
|
||||
11, 13, 15, 17, 38, 19
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_cond_targs[] = {
|
||||
20, 1, 28, 22, 23, 3, 24, 5,
|
||||
25, 7, 26, 9, 27, 20, 10, 31,
|
||||
20, 32, 12, 33, 14, 34, 16, 35,
|
||||
18, 36, 39, 20, 20, 21, 30, 37,
|
||||
20, 0, 29, 2, 4, 6, 8, 20,
|
||||
20, 11, 13, 15, 17, 38, 19, 0
|
||||
static const char _khmer_syllable_machine_trans_actions[] = {
|
||||
1, 0, 2, 2, 2, 0, 0, 0,
|
||||
2, 0, 2, 0, 2, 3, 0, 4,
|
||||
5, 2, 0, 0, 0, 2, 0, 2,
|
||||
0, 2, 4, 8, 2, 9, 0, 10,
|
||||
0, 0, 0, 0, 0, 0, 11, 12,
|
||||
0, 0, 0, 0, 4, 0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_cond_actions[] = {
|
||||
1, 0, 2, 2, 2, 0, 0, 0,
|
||||
2, 0, 2, 0, 2, 3, 0, 4,
|
||||
5, 2, 0, 0, 0, 2, 0, 2,
|
||||
0, 2, 4, 0, 8, 2, 9, 0,
|
||||
10, 0, 0, 0, 0, 0, 0, 11,
|
||||
12, 0, 0, 0, 0, 4, 0, 0
|
||||
static const char _khmer_syllable_machine_to_state_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_to_state_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0
|
||||
static const char _khmer_syllable_machine_from_state_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_from_state_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0
|
||||
};
|
||||
|
||||
static const signed char _khmer_syllable_machine_eof_trans[] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 14, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 28, 33, 33, 33,
|
||||
33, 33, 33, 33, 33, 33, 40, 41,
|
||||
41, 41, 41, 41, 41, 41, 41, 41,
|
||||
0
|
||||
static const unsigned char _khmer_syllable_machine_eof_trans[] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 14, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 0, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 39, 40,
|
||||
40, 40, 40, 40, 40, 40, 40, 40
|
||||
};
|
||||
|
||||
static const int khmer_syllable_machine_start = 20;
|
||||
|
|
@ -191,263 +247,148 @@ static const int khmer_syllable_machine_en_main = 20;
|
|||
|
||||
|
||||
#define found_syllable(syllable_type) \
|
||||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables_khmer (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
|
||||
int cs;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
#line 210 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
|
||||
int cs;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
#line 266 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
{
|
||||
cs = (int)khmer_syllable_machine_start;
|
||||
ts = 0;
|
||||
te = 0;
|
||||
act = 0;
|
||||
cs = khmer_syllable_machine_start;
|
||||
ts = 0;
|
||||
te = 0;
|
||||
act = 0;
|
||||
}
|
||||
|
||||
|
||||
#line 106 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
|
||||
|
||||
p = 0;
|
||||
pe = eof = buffer->len;
|
||||
|
||||
unsigned int syllable_serial = 1;
|
||||
|
||||
#line 226 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
p = 0;
|
||||
pe = eof = buffer->len;
|
||||
|
||||
unsigned int syllable_serial = 1;
|
||||
|
||||
#line 282 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
{
|
||||
unsigned int _trans = 0;
|
||||
const unsigned char * _keys;
|
||||
const signed char * _inds;
|
||||
int _ic;
|
||||
_resume: {}
|
||||
if ( p == pe && p != eof )
|
||||
goto _out;
|
||||
switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
|
||||
case 7: {
|
||||
{
|
||||
int _slen;
|
||||
int _trans;
|
||||
const unsigned char *_keys;
|
||||
const char *_inds;
|
||||
if ( p == pe )
|
||||
goto _test_eof;
|
||||
_resume:
|
||||
switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
|
||||
case 7:
|
||||
#line 1 "NONE"
|
||||
{ts = p;}}
|
||||
|
||||
#line 241 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( p == eof ) {
|
||||
if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
|
||||
_trans = (unsigned int)_khmer_syllable_machine_eof_trans[cs] - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_keys = ( _khmer_syllable_machine_trans_keys + ((cs<<1)));
|
||||
_inds = ( _khmer_syllable_machine_indicies + (_khmer_syllable_machine_index_offsets[cs]));
|
||||
|
||||
if ( (info[p].khmer_category()) <= 29 && (info[p].khmer_category()) >= 1 ) {
|
||||
_ic = (int)_khmer_syllable_machine_char_class[(int)(info[p].khmer_category()) - 1];
|
||||
if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) )
|
||||
_trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) ));
|
||||
else
|
||||
_trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
|
||||
}
|
||||
else {
|
||||
_trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs];
|
||||
}
|
||||
|
||||
}
|
||||
cs = (int)_khmer_syllable_machine_cond_targs[_trans];
|
||||
|
||||
if ( _khmer_syllable_machine_cond_actions[_trans] != 0 ) {
|
||||
|
||||
switch ( _khmer_syllable_machine_cond_actions[_trans] ) {
|
||||
case 2: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}}
|
||||
|
||||
#line 279 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p+1;{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_non_khmer_cluster); }
|
||||
}}
|
||||
|
||||
#line 292 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
{
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p = p - 1;{
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_consonant_syllable); }
|
||||
}}
|
||||
|
||||
#line 305 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 12: {
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p = p - 1;{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_broken_cluster); }
|
||||
}}
|
||||
|
||||
#line 318 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 11: {
|
||||
{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p = p - 1;{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_non_khmer_cluster); }
|
||||
}}
|
||||
|
||||
#line 331 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
{
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{p = ((te))-1;
|
||||
{
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_consonant_syllable); }
|
||||
}}
|
||||
|
||||
#line 345 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{p = ((te))-1;
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_broken_cluster); }
|
||||
}}
|
||||
|
||||
#line 359 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{switch( act ) {
|
||||
case 2: {
|
||||
p = ((te))-1;
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_broken_cluster); }
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
p = ((te))-1;
|
||||
{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
found_syllable (khmer_non_khmer_cluster); }
|
||||
break;
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#line 385 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}}
|
||||
|
||||
#line 395 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
{
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{act = 2;}}
|
||||
|
||||
#line 401 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}}
|
||||
|
||||
#line 411 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
{
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{act = 3;}}
|
||||
|
||||
#line 417 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( p == eof ) {
|
||||
if ( cs >= 20 )
|
||||
goto _out;
|
||||
}
|
||||
else {
|
||||
switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
|
||||
case 6: {
|
||||
{
|
||||
#line 1 "NONE"
|
||||
{ts = 0;}}
|
||||
|
||||
#line 437 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p += 1;
|
||||
goto _resume;
|
||||
}
|
||||
_out: {}
|
||||
{ts = p;}
|
||||
break;
|
||||
#line 296 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
}
|
||||
|
||||
|
||||
_keys = _khmer_syllable_machine_trans_keys + (cs<<1);
|
||||
_inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
|
||||
|
||||
_slen = _khmer_syllable_machine_key_spans[cs];
|
||||
_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
|
||||
( info[p].khmer_category()) <= _keys[1] ?
|
||||
( info[p].khmer_category()) - _keys[0] : _slen ];
|
||||
|
||||
_eof_trans:
|
||||
cs = _khmer_syllable_machine_trans_targs[_trans];
|
||||
|
||||
if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
|
||||
goto _again;
|
||||
|
||||
switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
|
||||
case 2:
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}
|
||||
break;
|
||||
case 8:
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p+1;{ found_syllable (khmer_non_khmer_cluster); }}
|
||||
break;
|
||||
case 10:
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p--;{ found_syllable (khmer_consonant_syllable); }}
|
||||
break;
|
||||
case 12:
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p--;{ found_syllable (khmer_broken_cluster); }}
|
||||
break;
|
||||
case 11:
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{te = p;p--;{ found_syllable (khmer_non_khmer_cluster); }}
|
||||
break;
|
||||
case 1:
|
||||
#line 80 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{{p = ((te))-1;}{ found_syllable (khmer_consonant_syllable); }}
|
||||
break;
|
||||
case 5:
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{{p = ((te))-1;}{ found_syllable (khmer_broken_cluster); }}
|
||||
break;
|
||||
case 3:
|
||||
#line 1 "NONE"
|
||||
{ switch( act ) {
|
||||
case 2:
|
||||
{{p = ((te))-1;} found_syllable (khmer_broken_cluster); }
|
||||
break;
|
||||
case 3:
|
||||
{{p = ((te))-1;} found_syllable (khmer_non_khmer_cluster); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}
|
||||
#line 81 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{act = 2;}
|
||||
break;
|
||||
case 9:
|
||||
#line 1 "NONE"
|
||||
{te = p+1;}
|
||||
#line 82 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
{act = 3;}
|
||||
break;
|
||||
#line 366 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
}
|
||||
|
||||
_again:
|
||||
switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
|
||||
case 6:
|
||||
#line 1 "NONE"
|
||||
{ts = 0;}
|
||||
break;
|
||||
#line 375 "hb-ot-shape-complex-khmer-machine.hh"
|
||||
}
|
||||
|
||||
if ( ++p != pe )
|
||||
goto _resume;
|
||||
_test_eof: {}
|
||||
if ( p == eof )
|
||||
{
|
||||
if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
|
||||
_trans = _khmer_syllable_machine_eof_trans[cs] - 1;
|
||||
goto _eof_trans;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#line 114 "hb-ot-shape-complex-khmer-machine.rl"
|
||||
|
||||
|
||||
}
|
||||
|
||||
#undef found_syllable
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ khmer_features[] =
|
|||
{
|
||||
/*
|
||||
* Basic features.
|
||||
* These features are applied in order, one at a time, after reordering.
|
||||
* These features are applied all at once, before reordering, constrained
|
||||
* to the syllable.
|
||||
*/
|
||||
{HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
|
||||
{HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
|
||||
|
|
|
|||
|
|
@ -49,13 +49,15 @@ enum khmer_category_t
|
|||
//OT_VPst = 29,
|
||||
};
|
||||
|
||||
using khmer_position_t = indic_position_t;
|
||||
|
||||
static inline void
|
||||
set_khmer_properties (hb_glyph_info_t &info)
|
||||
{
|
||||
hb_codepoint_t u = info.codepoint;
|
||||
unsigned int type = hb_indic_get_categories (u);
|
||||
khmer_category_t cat = (khmer_category_t) (type & 0xFFu);
|
||||
indic_position_t pos = (indic_position_t) (type >> 8);
|
||||
khmer_position_t pos = (khmer_position_t) (type >> 8);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ enum myanmar_syllable_type_t {
|
|||
#define myanmar_syllable_machine_ex_H 4u
|
||||
#define myanmar_syllable_machine_ex_IV 2u
|
||||
#define myanmar_syllable_machine_ex_MH 21u
|
||||
#define myanmar_syllable_machine_ex_ML 33u
|
||||
#define myanmar_syllable_machine_ex_MR 22u
|
||||
#define myanmar_syllable_machine_ex_MW 23u
|
||||
#define myanmar_syllable_machine_ex_MY 24u
|
||||
|
|
@ -67,35 +68,36 @@ enum myanmar_syllable_type_t {
|
|||
#define myanmar_syllable_machine_ex_ZWNJ 5u
|
||||
|
||||
|
||||
#line 71 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
#line 72 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
|
||||
1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
|
||||
3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u,
|
||||
3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u,
|
||||
5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u,
|
||||
3u, 29u, 3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u,
|
||||
3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u,
|
||||
3u, 29u, 1u, 32u, 1u, 32u, 8u, 8u, 0
|
||||
1u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
|
||||
3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
|
||||
3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u, 3u, 33u,
|
||||
3u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
|
||||
3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
|
||||
3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u,
|
||||
3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 1u, 33u, 1u, 32u, 8u, 8u,
|
||||
0
|
||||
};
|
||||
|
||||
static const char _myanmar_syllable_machine_key_spans[] = {
|
||||
32, 28, 25, 4, 25, 23, 21, 21,
|
||||
27, 27, 27, 27, 16, 27, 27, 27,
|
||||
27, 27, 28, 27, 27, 27, 27, 27,
|
||||
25, 4, 25, 23, 21, 21, 27, 27,
|
||||
27, 27, 16, 28, 27, 27, 27, 27,
|
||||
27, 28, 27, 27, 27, 27, 27, 28,
|
||||
27, 32, 32, 1
|
||||
33, 31, 25, 4, 25, 23, 21, 21,
|
||||
31, 27, 27, 27, 31, 16, 31, 31,
|
||||
27, 27, 27, 28, 27, 31, 31, 31,
|
||||
31, 31, 25, 4, 25, 23, 21, 21,
|
||||
31, 27, 27, 27, 31, 16, 31, 31,
|
||||
31, 27, 27, 27, 28, 27, 31, 31,
|
||||
31, 31, 31, 31, 31, 33, 32, 1
|
||||
};
|
||||
|
||||
static const short _myanmar_syllable_machine_index_offsets[] = {
|
||||
0, 33, 62, 88, 93, 119, 143, 165,
|
||||
187, 215, 243, 271, 299, 316, 344, 372,
|
||||
400, 428, 456, 485, 513, 541, 569, 597,
|
||||
625, 651, 656, 682, 706, 728, 750, 778,
|
||||
806, 834, 862, 879, 908, 936, 964, 992,
|
||||
1020, 1048, 1077, 1105, 1133, 1161, 1189, 1217,
|
||||
1246, 1274, 1307, 1340
|
||||
0, 34, 66, 92, 97, 123, 147, 169,
|
||||
191, 223, 251, 279, 307, 339, 356, 388,
|
||||
420, 448, 476, 504, 533, 561, 593, 625,
|
||||
657, 689, 721, 747, 752, 778, 802, 824,
|
||||
846, 878, 906, 934, 962, 994, 1011, 1043,
|
||||
1075, 1107, 1135, 1163, 1191, 1220, 1248, 1280,
|
||||
1312, 1344, 1376, 1408, 1440, 1472, 1506, 1539
|
||||
};
|
||||
|
||||
static const char _myanmar_syllable_machine_indicies[] = {
|
||||
|
|
@ -103,192 +105,217 @@ static const char _myanmar_syllable_machine_indicies[] = {
|
|||
0, 6, 1, 0, 0, 0, 0, 7,
|
||||
0, 8, 9, 0, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 20, 1,
|
||||
0, 22, 23, 24, 24, 21, 25, 21,
|
||||
26, 21, 21, 21, 21, 21, 21, 21,
|
||||
27, 21, 21, 28, 29, 30, 31, 32,
|
||||
33, 34, 35, 36, 37, 21, 24, 24,
|
||||
21, 25, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 38, 21, 21, 21, 21,
|
||||
21, 21, 32, 21, 21, 21, 36, 21,
|
||||
24, 24, 21, 25, 21, 24, 24, 21,
|
||||
25, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 32, 21, 21, 21, 36, 21, 39,
|
||||
21, 24, 24, 21, 25, 21, 32, 21,
|
||||
21, 21, 21, 21, 21, 21, 40, 21,
|
||||
21, 21, 21, 21, 21, 32, 21, 24,
|
||||
24, 21, 25, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 40, 21, 21, 21,
|
||||
21, 21, 21, 32, 21, 24, 24, 21,
|
||||
25, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 32, 21, 22, 21, 24, 24, 21,
|
||||
25, 21, 26, 21, 21, 21, 21, 21,
|
||||
21, 21, 41, 21, 21, 41, 21, 21,
|
||||
21, 32, 42, 21, 21, 36, 21, 22,
|
||||
21, 24, 24, 21, 25, 21, 26, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 32, 21, 21,
|
||||
21, 36, 21, 22, 21, 24, 24, 21,
|
||||
25, 21, 26, 21, 21, 21, 21, 21,
|
||||
21, 21, 41, 21, 21, 21, 21, 21,
|
||||
21, 32, 42, 21, 21, 36, 21, 22,
|
||||
21, 24, 24, 21, 25, 21, 26, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 32, 42, 21,
|
||||
21, 36, 21, 1, 1, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 1, 21, 22, 21, 24, 24,
|
||||
21, 25, 21, 26, 21, 21, 21, 21,
|
||||
21, 21, 21, 27, 21, 21, 28, 29,
|
||||
30, 31, 32, 33, 34, 35, 36, 21,
|
||||
22, 21, 24, 24, 21, 25, 21, 26,
|
||||
21, 21, 21, 21, 21, 21, 21, 43,
|
||||
21, 21, 21, 21, 21, 21, 32, 33,
|
||||
34, 35, 36, 21, 22, 21, 24, 24,
|
||||
21, 25, 21, 26, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 32, 33, 34, 35, 36, 21,
|
||||
22, 21, 24, 24, 21, 25, 21, 26,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 32, 33,
|
||||
34, 21, 36, 21, 22, 21, 24, 24,
|
||||
21, 25, 21, 26, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 32, 21, 34, 21, 36, 21,
|
||||
22, 21, 24, 24, 21, 25, 21, 26,
|
||||
21, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 32, 33,
|
||||
34, 35, 36, 43, 21, 22, 21, 24,
|
||||
24, 21, 25, 21, 26, 21, 21, 21,
|
||||
21, 21, 21, 21, 21, 21, 21, 28,
|
||||
21, 30, 21, 32, 33, 34, 35, 36,
|
||||
21, 22, 21, 24, 24, 21, 25, 21,
|
||||
26, 21, 21, 21, 21, 21, 21, 21,
|
||||
43, 21, 21, 28, 21, 21, 21, 32,
|
||||
33, 34, 35, 36, 21, 22, 21, 24,
|
||||
24, 21, 25, 21, 26, 21, 21, 21,
|
||||
21, 21, 21, 21, 44, 21, 21, 28,
|
||||
29, 30, 21, 32, 33, 34, 35, 36,
|
||||
21, 22, 21, 24, 24, 21, 25, 21,
|
||||
26, 21, 21, 21, 21, 21, 21, 21,
|
||||
21, 21, 21, 28, 29, 30, 21, 32,
|
||||
33, 34, 35, 36, 21, 22, 23, 24,
|
||||
24, 21, 25, 21, 26, 21, 21, 21,
|
||||
21, 21, 21, 21, 27, 21, 21, 28,
|
||||
29, 30, 31, 32, 33, 34, 35, 36,
|
||||
21, 46, 46, 45, 5, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 47, 45,
|
||||
45, 45, 45, 45, 45, 14, 45, 45,
|
||||
45, 18, 45, 46, 46, 45, 5, 45,
|
||||
46, 46, 45, 5, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 14, 45, 45, 45,
|
||||
18, 45, 48, 45, 46, 46, 45, 5,
|
||||
45, 14, 45, 45, 45, 45, 45, 45,
|
||||
45, 49, 45, 45, 45, 45, 45, 45,
|
||||
14, 45, 46, 46, 45, 5, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 45, 49,
|
||||
45, 45, 45, 45, 45, 45, 14, 45,
|
||||
46, 46, 45, 5, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 14, 45, 2, 45,
|
||||
46, 46, 45, 5, 45, 6, 45, 45,
|
||||
45, 45, 45, 45, 45, 50, 45, 45,
|
||||
50, 45, 45, 45, 14, 51, 45, 45,
|
||||
18, 45, 2, 45, 46, 46, 45, 5,
|
||||
45, 6, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 45, 45,
|
||||
14, 45, 45, 45, 18, 45, 2, 45,
|
||||
46, 46, 45, 5, 45, 6, 45, 45,
|
||||
45, 45, 45, 45, 45, 50, 45, 45,
|
||||
45, 45, 45, 45, 14, 51, 45, 45,
|
||||
18, 45, 2, 45, 46, 46, 45, 5,
|
||||
45, 6, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 45, 45,
|
||||
14, 51, 45, 45, 18, 45, 52, 52,
|
||||
45, 45, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 52, 45, 2,
|
||||
3, 46, 46, 45, 5, 45, 6, 45,
|
||||
45, 45, 45, 45, 45, 45, 8, 45,
|
||||
45, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 45, 2, 45, 46, 46,
|
||||
45, 5, 45, 6, 45, 45, 45, 45,
|
||||
45, 45, 45, 8, 45, 45, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 45,
|
||||
2, 45, 46, 46, 45, 5, 45, 6,
|
||||
45, 45, 45, 45, 45, 45, 45, 53,
|
||||
45, 45, 45, 45, 45, 45, 14, 15,
|
||||
16, 17, 18, 45, 2, 45, 46, 46,
|
||||
45, 5, 45, 6, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 14, 15, 16, 17, 18, 45,
|
||||
2, 45, 46, 46, 45, 5, 45, 6,
|
||||
45, 45, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 14, 15,
|
||||
16, 45, 18, 45, 2, 45, 46, 46,
|
||||
45, 5, 45, 6, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 14, 45, 16, 45, 18, 45,
|
||||
2, 45, 46, 46, 45, 5, 45, 6,
|
||||
45, 45, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 14, 15,
|
||||
16, 17, 18, 53, 45, 2, 45, 46,
|
||||
46, 45, 5, 45, 6, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 45, 10,
|
||||
45, 12, 45, 14, 15, 16, 17, 18,
|
||||
45, 2, 45, 46, 46, 45, 5, 45,
|
||||
6, 45, 45, 45, 45, 45, 45, 45,
|
||||
53, 45, 45, 10, 45, 45, 45, 14,
|
||||
15, 16, 17, 18, 45, 2, 45, 46,
|
||||
46, 45, 5, 45, 6, 45, 45, 45,
|
||||
45, 45, 45, 45, 54, 45, 45, 10,
|
||||
11, 12, 45, 14, 15, 16, 17, 18,
|
||||
45, 2, 45, 46, 46, 45, 5, 45,
|
||||
6, 45, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 10, 11, 12, 45, 14,
|
||||
15, 16, 17, 18, 45, 2, 3, 46,
|
||||
46, 45, 5, 45, 6, 45, 45, 45,
|
||||
45, 45, 45, 45, 8, 45, 45, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18,
|
||||
45, 22, 23, 24, 24, 21, 25, 21,
|
||||
26, 21, 21, 21, 21, 21, 21, 21,
|
||||
55, 21, 21, 28, 29, 30, 31, 32,
|
||||
33, 34, 35, 36, 37, 21, 22, 56,
|
||||
24, 24, 21, 25, 21, 26, 21, 21,
|
||||
21, 21, 21, 21, 21, 27, 21, 21,
|
||||
28, 29, 30, 31, 32, 33, 34, 35,
|
||||
36, 21, 1, 1, 2, 3, 46, 46,
|
||||
45, 5, 45, 6, 1, 45, 45, 45,
|
||||
45, 1, 45, 8, 45, 45, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19,
|
||||
45, 1, 45, 1, 1, 57, 57, 57,
|
||||
57, 57, 57, 57, 57, 1, 57, 57,
|
||||
57, 57, 1, 57, 57, 57, 57, 57,
|
||||
57, 57, 57, 57, 57, 57, 57, 57,
|
||||
57, 57, 1, 57, 58, 57, 0
|
||||
21, 0, 23, 24, 25, 25, 22, 26,
|
||||
22, 27, 22, 22, 22, 22, 22, 22,
|
||||
22, 28, 22, 22, 29, 30, 31, 32,
|
||||
33, 34, 35, 36, 37, 38, 22, 22,
|
||||
39, 22, 25, 25, 22, 26, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 40,
|
||||
22, 22, 22, 22, 22, 22, 33, 22,
|
||||
22, 22, 37, 22, 25, 25, 22, 26,
|
||||
22, 25, 25, 22, 26, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 33, 22, 22,
|
||||
22, 37, 22, 41, 22, 25, 25, 22,
|
||||
26, 22, 33, 22, 22, 22, 22, 22,
|
||||
22, 22, 42, 22, 22, 22, 22, 22,
|
||||
22, 33, 22, 25, 25, 22, 26, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
42, 22, 22, 22, 22, 22, 22, 33,
|
||||
22, 25, 25, 22, 26, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 33, 22, 23,
|
||||
22, 25, 25, 22, 26, 22, 27, 22,
|
||||
22, 22, 22, 22, 22, 22, 43, 22,
|
||||
22, 44, 22, 22, 22, 33, 45, 22,
|
||||
22, 37, 22, 22, 22, 43, 22, 23,
|
||||
22, 25, 25, 22, 26, 22, 27, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 33, 22, 22,
|
||||
22, 37, 22, 23, 22, 25, 25, 22,
|
||||
26, 22, 27, 22, 22, 22, 22, 22,
|
||||
22, 22, 43, 22, 22, 22, 22, 22,
|
||||
22, 33, 45, 22, 22, 37, 22, 23,
|
||||
22, 25, 25, 22, 26, 22, 27, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 33, 45, 22,
|
||||
22, 37, 22, 23, 22, 25, 25, 22,
|
||||
26, 22, 27, 22, 22, 22, 22, 22,
|
||||
22, 22, 43, 22, 22, 22, 22, 22,
|
||||
22, 33, 45, 22, 22, 37, 22, 22,
|
||||
22, 43, 22, 1, 1, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 1, 22, 23, 22, 25, 25,
|
||||
22, 26, 22, 27, 22, 22, 22, 22,
|
||||
22, 22, 22, 28, 22, 22, 29, 30,
|
||||
31, 32, 33, 34, 35, 36, 37, 22,
|
||||
22, 22, 39, 22, 23, 22, 25, 25,
|
||||
22, 26, 22, 27, 22, 22, 22, 22,
|
||||
22, 22, 22, 46, 22, 22, 22, 22,
|
||||
22, 22, 33, 34, 35, 36, 37, 22,
|
||||
22, 22, 39, 22, 23, 22, 25, 25,
|
||||
22, 26, 22, 27, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 33, 34, 35, 36, 37, 22,
|
||||
23, 22, 25, 25, 22, 26, 22, 27,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 33, 34,
|
||||
35, 22, 37, 22, 23, 22, 25, 25,
|
||||
22, 26, 22, 27, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 33, 22, 35, 22, 37, 22,
|
||||
23, 22, 25, 25, 22, 26, 22, 27,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 33, 34,
|
||||
35, 36, 37, 46, 22, 23, 22, 25,
|
||||
25, 22, 26, 22, 27, 22, 22, 22,
|
||||
22, 22, 22, 22, 46, 22, 22, 22,
|
||||
22, 22, 22, 33, 34, 35, 36, 37,
|
||||
22, 23, 22, 25, 25, 22, 26, 22,
|
||||
27, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 29, 22, 31, 22, 33,
|
||||
34, 35, 36, 37, 22, 22, 22, 39,
|
||||
22, 23, 22, 25, 25, 22, 26, 22,
|
||||
27, 22, 22, 22, 22, 22, 22, 22,
|
||||
46, 22, 22, 29, 22, 22, 22, 33,
|
||||
34, 35, 36, 37, 22, 22, 22, 39,
|
||||
22, 23, 22, 25, 25, 22, 26, 22,
|
||||
27, 22, 22, 22, 22, 22, 22, 22,
|
||||
47, 22, 22, 29, 30, 31, 22, 33,
|
||||
34, 35, 36, 37, 22, 22, 22, 39,
|
||||
22, 23, 22, 25, 25, 22, 26, 22,
|
||||
27, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 29, 30, 31, 22, 33,
|
||||
34, 35, 36, 37, 22, 22, 22, 39,
|
||||
22, 23, 24, 25, 25, 22, 26, 22,
|
||||
27, 22, 22, 22, 22, 22, 22, 22,
|
||||
28, 22, 22, 29, 30, 31, 32, 33,
|
||||
34, 35, 36, 37, 22, 22, 22, 39,
|
||||
22, 49, 49, 48, 5, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 50, 48,
|
||||
48, 48, 48, 48, 48, 14, 48, 48,
|
||||
48, 18, 48, 49, 49, 48, 5, 48,
|
||||
49, 49, 48, 5, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 14, 48, 48, 48,
|
||||
18, 48, 51, 48, 49, 49, 48, 5,
|
||||
48, 14, 48, 48, 48, 48, 48, 48,
|
||||
48, 52, 48, 48, 48, 48, 48, 48,
|
||||
14, 48, 49, 49, 48, 5, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 52,
|
||||
48, 48, 48, 48, 48, 48, 14, 48,
|
||||
49, 49, 48, 5, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 14, 48, 2, 48,
|
||||
49, 49, 48, 5, 48, 6, 48, 48,
|
||||
48, 48, 48, 48, 48, 53, 48, 48,
|
||||
54, 48, 48, 48, 14, 55, 48, 48,
|
||||
18, 48, 48, 48, 53, 48, 2, 48,
|
||||
49, 49, 48, 5, 48, 6, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 14, 48, 48, 48,
|
||||
18, 48, 2, 48, 49, 49, 48, 5,
|
||||
48, 6, 48, 48, 48, 48, 48, 48,
|
||||
48, 53, 48, 48, 48, 48, 48, 48,
|
||||
14, 55, 48, 48, 18, 48, 2, 48,
|
||||
49, 49, 48, 5, 48, 6, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 14, 55, 48, 48,
|
||||
18, 48, 2, 48, 49, 49, 48, 5,
|
||||
48, 6, 48, 48, 48, 48, 48, 48,
|
||||
48, 53, 48, 48, 48, 48, 48, 48,
|
||||
14, 55, 48, 48, 18, 48, 48, 48,
|
||||
53, 48, 56, 56, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 56, 48, 2, 3, 49, 49, 48,
|
||||
5, 48, 6, 48, 48, 48, 48, 48,
|
||||
48, 48, 8, 48, 48, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19, 48,
|
||||
48, 21, 48, 2, 48, 49, 49, 48,
|
||||
5, 48, 6, 48, 48, 48, 48, 48,
|
||||
48, 48, 8, 48, 48, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 48, 48,
|
||||
48, 21, 48, 2, 48, 49, 49, 48,
|
||||
5, 48, 6, 48, 48, 48, 48, 48,
|
||||
48, 48, 57, 48, 48, 48, 48, 48,
|
||||
48, 14, 15, 16, 17, 18, 48, 48,
|
||||
48, 21, 48, 2, 48, 49, 49, 48,
|
||||
5, 48, 6, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 14, 15, 16, 17, 18, 48, 2,
|
||||
48, 49, 49, 48, 5, 48, 6, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 14, 15, 16,
|
||||
48, 18, 48, 2, 48, 49, 49, 48,
|
||||
5, 48, 6, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 14, 48, 16, 48, 18, 48, 2,
|
||||
48, 49, 49, 48, 5, 48, 6, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 14, 15, 16,
|
||||
17, 18, 57, 48, 2, 48, 49, 49,
|
||||
48, 5, 48, 6, 48, 48, 48, 48,
|
||||
48, 48, 48, 57, 48, 48, 48, 48,
|
||||
48, 48, 14, 15, 16, 17, 18, 48,
|
||||
2, 48, 49, 49, 48, 5, 48, 6,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 10, 48, 12, 48, 14, 15,
|
||||
16, 17, 18, 48, 48, 48, 21, 48,
|
||||
2, 48, 49, 49, 48, 5, 48, 6,
|
||||
48, 48, 48, 48, 48, 48, 48, 57,
|
||||
48, 48, 10, 48, 48, 48, 14, 15,
|
||||
16, 17, 18, 48, 48, 48, 21, 48,
|
||||
2, 48, 49, 49, 48, 5, 48, 6,
|
||||
48, 48, 48, 48, 48, 48, 48, 58,
|
||||
48, 48, 10, 11, 12, 48, 14, 15,
|
||||
16, 17, 18, 48, 48, 48, 21, 48,
|
||||
2, 48, 49, 49, 48, 5, 48, 6,
|
||||
48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 10, 11, 12, 48, 14, 15,
|
||||
16, 17, 18, 48, 48, 48, 21, 48,
|
||||
2, 3, 49, 49, 48, 5, 48, 6,
|
||||
48, 48, 48, 48, 48, 48, 48, 8,
|
||||
48, 48, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 48, 48, 48, 21, 48,
|
||||
23, 24, 25, 25, 22, 26, 22, 27,
|
||||
22, 22, 22, 22, 22, 22, 22, 59,
|
||||
22, 22, 29, 30, 31, 32, 33, 34,
|
||||
35, 36, 37, 38, 22, 22, 39, 22,
|
||||
23, 60, 25, 25, 22, 26, 22, 27,
|
||||
22, 22, 22, 22, 22, 22, 22, 28,
|
||||
22, 22, 29, 30, 31, 32, 33, 34,
|
||||
35, 36, 37, 22, 22, 22, 39, 22,
|
||||
1, 1, 2, 3, 49, 49, 48, 5,
|
||||
48, 6, 1, 48, 48, 48, 48, 1,
|
||||
48, 8, 48, 48, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 48, 1,
|
||||
21, 48, 1, 1, 61, 61, 61, 61,
|
||||
61, 61, 61, 61, 1, 61, 61, 61,
|
||||
61, 1, 61, 61, 61, 61, 61, 61,
|
||||
61, 61, 61, 61, 61, 61, 61, 61,
|
||||
61, 1, 61, 62, 61, 0
|
||||
};
|
||||
|
||||
static const char _myanmar_syllable_machine_trans_targs[] = {
|
||||
0, 1, 24, 34, 0, 25, 31, 47,
|
||||
36, 50, 37, 42, 43, 44, 27, 39,
|
||||
40, 41, 30, 46, 51, 0, 2, 12,
|
||||
0, 3, 9, 13, 14, 19, 20, 21,
|
||||
5, 16, 17, 18, 8, 23, 4, 6,
|
||||
7, 10, 11, 15, 22, 0, 0, 26,
|
||||
28, 29, 32, 33, 35, 38, 45, 48,
|
||||
49, 0, 0
|
||||
0, 1, 26, 37, 0, 27, 33, 51,
|
||||
39, 54, 40, 46, 47, 48, 29, 42,
|
||||
43, 44, 32, 50, 55, 45, 0, 2,
|
||||
13, 0, 3, 9, 14, 15, 21, 22,
|
||||
23, 5, 17, 18, 19, 8, 25, 20,
|
||||
4, 6, 7, 10, 12, 11, 16, 24,
|
||||
0, 0, 28, 30, 31, 34, 36, 35,
|
||||
38, 41, 49, 52, 53, 0, 0
|
||||
};
|
||||
|
||||
static const char _myanmar_syllable_machine_trans_actions[] = {
|
||||
3, 0, 0, 0, 4, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 5, 0, 0,
|
||||
6, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 5, 0,
|
||||
0, 6, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 7, 8, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 9, 10
|
||||
7, 8, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 9, 10
|
||||
};
|
||||
|
||||
static const char _myanmar_syllable_machine_to_state_actions[] = {
|
||||
|
|
@ -298,7 +325,7 @@ static const char _myanmar_syllable_machine_to_state_actions[] = {
|
|||
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 _myanmar_syllable_machine_from_state_actions[] = {
|
||||
|
|
@ -308,17 +335,17 @@ static const char _myanmar_syllable_machine_from_state_actions[] = {
|
|||
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 _myanmar_syllable_machine_eof_trans[] = {
|
||||
0, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
46, 46, 46, 46, 46, 46, 46, 46,
|
||||
46, 46, 46, 46, 46, 46, 46, 46,
|
||||
46, 46, 46, 46, 46, 46, 46, 22,
|
||||
22, 46, 58, 58
|
||||
0, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 49, 49, 49, 49, 49, 49,
|
||||
49, 49, 49, 49, 49, 49, 49, 49,
|
||||
49, 49, 49, 49, 49, 49, 49, 49,
|
||||
49, 49, 49, 23, 23, 49, 62, 62
|
||||
};
|
||||
|
||||
static const int myanmar_syllable_machine_start = 0;
|
||||
|
|
@ -332,7 +359,7 @@ static const int myanmar_syllable_machine_en_main = 0;
|
|||
|
||||
|
||||
|
||||
#line 101 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 102 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
|
||||
|
||||
#define found_syllable(syllable_type) \
|
||||
|
|
@ -351,7 +378,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
|
|||
int cs;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
#line 355 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
#line 382 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
{
|
||||
cs = myanmar_syllable_machine_start;
|
||||
ts = 0;
|
||||
|
|
@ -359,7 +386,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
|
|||
act = 0;
|
||||
}
|
||||
|
||||
#line 121 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
|
||||
|
||||
p = 0;
|
||||
|
|
@ -367,7 +394,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
|
|||
|
||||
unsigned int syllable_serial = 1;
|
||||
|
||||
#line 371 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
#line 398 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
{
|
||||
int _slen;
|
||||
int _trans;
|
||||
|
|
@ -381,7 +408,7 @@ _resume:
|
|||
#line 1 "NONE"
|
||||
{ts = p;}
|
||||
break;
|
||||
#line 385 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
#line 412 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
}
|
||||
|
||||
_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
|
||||
|
|
@ -400,38 +427,38 @@ _eof_trans:
|
|||
|
||||
switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
|
||||
case 6:
|
||||
#line 93 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
{te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
|
||||
break;
|
||||
case 4:
|
||||
#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 95 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
{te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
|
||||
break;
|
||||
case 10:
|
||||
#line 95 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
{te = p+1;{ found_syllable (myanmar_punctuation_cluster); }}
|
||||
break;
|
||||
case 8:
|
||||
#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
{te = p+1;{ found_syllable (myanmar_broken_cluster); }}
|
||||
break;
|
||||
case 3:
|
||||
#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
{te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
|
||||
break;
|
||||
case 5:
|
||||
#line 93 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
{te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
|
||||
break;
|
||||
case 7:
|
||||
#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
{te = p;p--;{ found_syllable (myanmar_broken_cluster); }}
|
||||
break;
|
||||
case 9:
|
||||
#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
{te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
|
||||
break;
|
||||
#line 435 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
#line 462 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
}
|
||||
|
||||
_again:
|
||||
|
|
@ -440,7 +467,7 @@ _again:
|
|||
#line 1 "NONE"
|
||||
{ts = 0;}
|
||||
break;
|
||||
#line 444 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
#line 471 "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
}
|
||||
|
||||
if ( ++p != pe )
|
||||
|
|
@ -456,7 +483,7 @@ _again:
|
|||
|
||||
}
|
||||
|
||||
#line 129 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
#line 130 "hb-ot-shape-complex-myanmar-machine.rl"
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue