diff -uN gfx/harfbuzz/src_old/check-defs.sh gfx/harfbuzz/src/check-defs.sh --- gfx/harfbuzz/src_old/check-defs.sh 1970-01-01 01:00:00.000000000 +0100 +++ gfx/harfbuzz/src/check-defs.sh 2016-06-05 23:47:59.650463392 +0200 @@ -0,0 +1,44 @@ +#!/bin/sh + +LC_ALL=C +export LC_ALL + +test -z "$srcdir" && srcdir=. +test -z "$MAKE" && MAKE=make +stat=0 + +if which nm 2>/dev/null >/dev/null; then + : +else + echo "check-defs.sh: 'nm' not found; skipping test" + exit 77 +fi + +defs="harfbuzz.def" +$MAKE $defs > /dev/null +tested=false +for def in $defs; do + lib=`echo "$def" | sed 's/[.]def$//;s@.*/@@'` + so=.libs/lib${lib}.so + + EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`" + + if test -f "$so"; then + + echo "Checking that $so has the same symbol list as $def" + { + echo EXPORTS + echo "$EXPORTED_SYMBOLS" + # cheat: copy the last line from the def file! + tail -n1 "$def" + } | diff "$def" - >&2 || stat=1 + + tested=true + fi +done +if ! $tested; then + echo "check-defs.sh: libharfbuzz shared library not found; skipping test" + exit 77 +fi + +exit $stat diff -uN gfx/harfbuzz/src_old/check-header-guards.sh gfx/harfbuzz/src/check-header-guards.sh --- gfx/harfbuzz/src_old/check-header-guards.sh 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/check-header-guards.sh 2016-06-05 23:48:00.885456341 +0200 @@ -9,13 +9,12 @@ test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'` test "x$HBSOURCES" = x && HBSOURCES=`cd "$srcdir"; find . -maxdepth 1 -name 'hb-*.cc' -or -name 'hb-*.hh'` - for x in $HBHEADERS $HBSOURCES; do test -f "$srcdir/$x" && x="$srcdir/$x" - echo "$x" | grep '[^h]$' -q && continue; + echo "$x" | grep -q '[^h]$' && continue; xx=`echo "$x" | sed 's@.*/@@'` tag=`echo "$xx" | tr 'a-z.-' 'A-Z_'` - lines=`grep "\<$tag\>" "$x" | wc -l | sed 's/[ ]*//g'` + lines=`grep -w "$tag" "$x" | wc -l | sed 's/[ ]*//g'` if test "x$lines" != x3; then echo "Ouch, header file $x does not have correct preprocessor guards" stat=1 diff -uN gfx/harfbuzz/src_old/check-libstdc++.sh gfx/harfbuzz/src/check-libstdc++.sh --- gfx/harfbuzz/src_old/check-libstdc++.sh 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/check-libstdc++.sh 2016-06-05 23:48:03.413441951 +0200 @@ -19,9 +19,9 @@ so=.libs/libharfbuzz.$suffix if ! test -f "$so"; then continue; fi - echo "Checking that we are not linking to libstdc++" - if ldd $so | grep 'libstdc[+][+]'; then - echo "Ouch, linked to libstdc++" + echo "Checking that we are not linking to libstdc++ or libc++" + if ldd $so | grep 'libstdc[+][+]\|libc[+][+]'; then + echo "Ouch, linked to libstdc++ or libc++" stat=1 fi tested=true diff -uN gfx/harfbuzz/src_old/gen-indic-table.py gfx/harfbuzz/src/gen-indic-table.py --- gfx/harfbuzz/src_old/gen-indic-table.py 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/gen-indic-table.py 2016-06-05 23:48:08.239414549 +0200 @@ -91,6 +91,7 @@ "Visarga": 'Vs', "Vowel": 'Vo', "Vowel_Dependent": 'M', + "Consonant_Prefixed": 'CPrf', "Other": 'x', },{ "Not_Applicable": 'x', @@ -209,7 +210,7 @@ for (start,end) in zip (starts, ends): if p not in [start>>page_bits, end>>page_bits]: continue offset = "indic_offset_0x%04xu" % start - print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end, start, offset) + print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset) for u,d in singles.items (): if p != u>>page_bits: continue print " if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]]) diff -uN gfx/harfbuzz/src_old/gen-use-table.py gfx/harfbuzz/src/gen-use-table.py --- gfx/harfbuzz/src_old/gen-use-table.py 1970-01-01 01:00:00.000000000 +0100 +++ gfx/harfbuzz/src/gen-use-table.py 2016-06-05 23:48:09.467407592 +0200 @@ -0,0 +1,476 @@ +#!/usr/bin/python + +import sys + +if len (sys.argv) != 5: + print >>sys.stderr, "usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt" + sys.exit (1) + +BLACKLISTED_BLOCKS = ["Thai", "Lao", "Tibetan"] + +files = [file (x) for x in sys.argv[1:]] + +headers = [[f.readline () for i in range (2)] for j,f in enumerate(files) if j != 2] +headers.append (["UnicodeData.txt does not have a header."]) + +data = [{} for f in files] +values = [{} for f in files] +for i, f in enumerate (files): + for line in f: + + j = line.find ('#') + if j >= 0: + line = line[:j] + + fields = [x.strip () for x in line.split (';')] + if len (fields) == 1: + continue + + uu = fields[0].split ('..') + start = int (uu[0], 16) + if len (uu) == 1: + end = start + else: + end = int (uu[1], 16) + + t = fields[1 if i != 2 else 2] + + for u in range (start, end + 1): + data[i][u] = t + values[i][t] = values[i].get (t, 0) + end - start + 1 + +defaults = ('Other', 'Not_Applicable', 'Cn', 'No_Block') + +# TODO Characters that are not in Unicode Indic files, but used in USE +data[0][0x034F] = defaults[0] +data[0][0x2060] = defaults[0] +for u in range (0xFE00, 0xFE0F + 1): + data[0][u] = defaults[0] + +# Merge data into one dict: +for i,v in enumerate (defaults): + values[i][v] = values[i].get (v, 0) + 1 +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: + combined[u] = list (defaults) + combined[u][i] = v +combined = {k:v for k,v in combined.items() if v[3] not in BLACKLISTED_BLOCKS} +data = combined +del combined +num = len (data) + + +property_names = [ + # General_Category + 'Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu', 'Mc', + 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf', 'Pi', 'Po', + 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs', + # Indic_Syllabic_Category + 'Other', + 'Bindu', + 'Visarga', + 'Avagraha', + 'Nukta', + 'Virama', + 'Pure_Killer', + 'Invisible_Stacker', + 'Vowel_Independent', + 'Vowel_Dependent', + 'Vowel', + 'Consonant_Placeholder', + 'Consonant', + 'Consonant_Dead', + 'Consonant_With_Stacker', + 'Consonant_Prefixed', + 'Consonant_Preceding_Repha', + 'Consonant_Succeeding_Repha', + 'Consonant_Subjoined', + 'Consonant_Medial', + 'Consonant_Final', + 'Consonant_Head_Letter', + 'Modifying_Letter', + 'Tone_Letter', + 'Tone_Mark', + 'Gemination_Mark', + 'Cantillation_Mark', + 'Register_Shifter', + 'Syllable_Modifier', + 'Consonant_Killer', + 'Non_Joiner', + 'Joiner', + 'Number_Joiner', + 'Number', + 'Brahmi_Joining_Number', + # Indic_Positional_Category + 'Not_Applicable', + 'Right', + 'Left', + 'Visual_Order_Left', + 'Left_And_Right', + 'Top', + 'Bottom', + 'Top_And_Bottom', + 'Top_And_Right', + 'Top_And_Left', + 'Top_And_Left_And_Right', + 'Bottom_And_Right', + 'Top_And_Bottom_And_Right', + 'Overstruck', +] + +class PropertyValue(object): + def __init__(self, name_): + self.name = name_ + def __str__(self): + return self.name + def __eq__(self, other): + return self.name == (other if isinstance(other, basestring) else other.name) + def __ne__(self, other): + return not (self == other) + +property_values = {} + +for name in property_names: + value = PropertyValue(name) + assert value not in property_values + assert value not in globals() + property_values[name] = value +globals().update(property_values) + + +def is_BASE(U, UISC, UGC): + return (UISC in [Number, Consonant, Consonant_Head_Letter, + #SPEC-OUTDATED Consonant_Placeholder, + Tone_Letter] or + (UGC == Lo and UISC in [Avagraha, Bindu, Consonant_Final, Consonant_Medial, + Consonant_Subjoined, Vowel, Vowel_Dependent])) +def is_BASE_VOWEL(U, UISC, UGC): + return UISC == Vowel_Independent +def is_BASE_IND(U, UISC, UGC): + #SPEC-BROKEN return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po) + return (UISC in [Consonant_Dead, Modifying_Letter] or + (UGC == Po and not is_BASE_OTHER(U, UISC, UGC))) # for 104E +def is_BASE_NUM(U, UISC, UGC): + return UISC == Brahmi_Joining_Number +def is_BASE_OTHER(U, UISC, UGC): + if UISC == Consonant_Placeholder: return True #SPEC-OUTDATED + return U in [0x00A0, 0x00D7, 0x2015, 0x2022, 0x25CC, + 0x25FB, 0x25FC, 0x25FD, 0x25FE] +def is_CGJ(U, UISC, UGC): + return U == 0x034F +def is_CONS_FINAL(U, UISC, UGC): + return ((UISC == Consonant_Final and UGC != Lo) or + UISC == Consonant_Succeeding_Repha) +def is_CONS_FINAL_MOD(U, UISC, UGC): + #SPEC-OUTDATED return UISC in [Consonant_Final_Modifier, Syllable_Modifier] + return UISC == Syllable_Modifier +def is_CONS_MED(U, UISC, UGC): + return UISC == Consonant_Medial and UGC != Lo +def is_CONS_MOD(U, UISC, UGC): + return UISC in [Nukta, Gemination_Mark, Consonant_Killer] +def is_CONS_SUB(U, UISC, UGC): + #SPEC-OUTDATED return UISC == Consonant_Subjoined + return UISC == Consonant_Subjoined and UGC != Lo +def is_HALANT(U, UISC, UGC): + return UISC in [Virama, Invisible_Stacker] +def is_HALANT_NUM(U, UISC, UGC): + return UISC == Number_Joiner +def is_ZWNJ(U, UISC, UGC): + return UISC == Non_Joiner +def is_ZWJ(U, UISC, UGC): + return UISC == Joiner +def is_Word_Joiner(U, UISC, UGC): + return U == 0x2060 +def is_OTHER(U, UISC, UGC): + #SPEC-OUTDATED return UGC == Zs # or any other SCRIPT_COMMON characters + return (UISC == Other + and not is_SYM_MOD(U, UISC, UGC) + and not is_CGJ(U, UISC, UGC) + and not is_Word_Joiner(U, UISC, UGC) + and not is_VARIATION_SELECTOR(U, UISC, UGC) + ) +def is_Reserved(U, UISC, UGC): + return UGC == 'Cn' +def is_REPHA(U, UISC, UGC): + #return UISC == Consonant_Preceding_Repha + #SPEC-OUTDATED hack to categorize Consonant_With_Stacker and Consonant_Prefixed + return UISC in [Consonant_Preceding_Repha, Consonant_With_Stacker, Consonant_Prefixed] +def is_SYM(U, UISC, UGC): + if U == 0x25CC: return False #SPEC-OUTDATED + #SPEC-OUTDATED return UGC in [So, Sc] or UISC == Symbol_Letter + return UGC in [So, Sc] +def is_SYM_MOD(U, UISC, UGC): + return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73] +def is_VARIATION_SELECTOR(U, UISC, UGC): + return 0xFE00 <= U <= 0xFE0F +def is_VOWEL(U, UISC, UGC): + return (UISC == Pure_Killer or + (UGC != Lo and UISC in [Vowel, Vowel_Dependent])) +def is_VOWEL_MOD(U, UISC, UGC): + return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or + (UGC != Lo and UISC == Bindu)) + +use_mapping = { + 'B': is_BASE, + 'IV': is_BASE_VOWEL, + 'IND': is_BASE_IND, + 'N': is_BASE_NUM, + 'GB': is_BASE_OTHER, + 'CGJ': is_CGJ, + 'F': is_CONS_FINAL, + 'FM': is_CONS_FINAL_MOD, + 'M': is_CONS_MED, + 'CM': is_CONS_MOD, + 'SUB': is_CONS_SUB, + 'H': is_HALANT, + 'HN': is_HALANT_NUM, + 'ZWNJ': is_ZWNJ, + 'ZWJ': is_ZWJ, + 'WJ': is_Word_Joiner, + 'O': is_OTHER, + 'Rsv': is_Reserved, + 'R': is_REPHA, + 'S': is_SYM, + 'SM': is_SYM_MOD, + 'VS': is_VARIATION_SELECTOR, + 'V': is_VOWEL, + 'VM': is_VOWEL_MOD, +} + +use_positions = { + 'F': { + 'Abv': [Top], + 'Blw': [Bottom], + 'Pst': [Right], + }, + 'M': { + 'Abv': [Top], + 'Blw': [Bottom], + 'Pst': [Right], + 'Pre': [Left], + }, + 'CM': { + 'Abv': [Top], + 'Blw': [Bottom], + }, + 'V': { + 'Abv': [Top, Top_And_Bottom, Top_And_Bottom_And_Right, Top_And_Right], + 'Blw': [Bottom, Overstruck, Bottom_And_Right], + 'Pst': [Right], + 'Pre': [Left, Top_And_Left, Top_And_Left_And_Right, Left_And_Right], + }, + 'VM': { + 'Abv': [Top], + 'Blw': [Bottom, Overstruck], + 'Pst': [Right], + 'Pre': [Left], + }, + 'SM': { + 'Abv': [Top], + 'Blw': [Bottom], + }, + 'H': None, + 'B': None, + 'FM': None, + 'SUB': None, +} + +def map_to_use(data): + out = {} + items = use_mapping.items() + for U,(UISC,UIPC,UGC,UBlock) in data.items(): + + # Resolve Indic_Syllabic_Category + + # TODO: These don't have UISC assigned in Unicode 8.0, but + # have UIPC + if U == 0x17DD: UISC = Vowel_Dependent + if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark + + # TODO: U+1CED should only be allowed after some of + # the nasalization marks, maybe only for U+1CE9..U+1CF1. + if U == 0x1CED: UISC = Tone_Mark + + evals = [(k, v(U,UISC,UGC)) for k,v in items] + values = [k for k,v in evals if v] + assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values) + USE = values[0] + + # Resolve Indic_Positional_Category + + # TODO: Not in Unicode 8.0 yet, but in spec. + if U == 0x1B6C: UIPC = Bottom + + # TODO: These should die, but have UIPC in Unicode 8.0 + if U in [0x953, 0x954]: UIPC = Not_Applicable + + # TODO: In USE's override list but not in Unicode 8.0 + if U == 0x103C: UIPC = Left + + # TODO: These are not in USE's override list that we have, nor are they in Unicode 8.0 + if 0xA926 <= U <= 0xA92A: UIPC = Top + if U == 0x111CA: UIPC = Bottom + if U == 0x11300: UIPC = Top + if U == 0x1133C: UIPC = Bottom + if U == 0x1171E: UIPC = Left # Correct?! + if 0x1CF2 <= U <= 0x1CF3: UIPC = Right + if 0x1CF8 <= U <= 0x1CF9: UIPC = Top + + assert (UIPC in [Not_Applicable, Visual_Order_Left] or + USE in use_positions), "%s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC) + + 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" % (hex(U), UIPC, USE, UISC, UGC, values) + USE = USE + values[0] + + out[U] = (USE, UBlock) + return out + +defaults = ('O', 'No_Block') +data = map_to_use(data) + +# Remove the outliers +singles = {} +for u in [0x034F, 0x25CC, 0x1107F]: + singles[u] = data[u] + del data[u] + +print "/* == Start of generated table == */" +print "/*" +print " * The following table is generated by running:" +print " *" +print " * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt" +print " *" +print " * on files with these headers:" +print " *" +for h in headers: + for l in h: + print " * %s" % (l.strip()) +print " */" +print +print '#include "hb-ot-shape-complex-use-private.hh"' +print + +total = 0 +used = 0 +last_block = None +def print_block (block, start, end, data): + global total, used, last_block + if block and block != last_block: + print + print + print " /* %s */" % block + if start % 16: + print ' ' * (20 + (start % 16 * 6)), + num = 0 + assert start % 8 == 0 + assert (end+1) % 8 == 0 + for u in range (start, end+1): + if u % 16 == 0: + print + print " /* %04X */" % u, + if u in data: + num += 1 + d = data.get (u, defaults) + sys.stdout.write ("%6s," % d[0]) + + total += end - start + 1 + used += num + if block: + last_block = block + +uu = data.keys () +uu.sort () + +last = -100000 +num = 0 +offset = 0 +starts = [] +ends = [] +for k,v in sorted(use_mapping.items()): + if k in use_positions and use_positions[k]: continue + print "#define %s USE_%s /* %s */" % (k, k, v.__name__[3:]) +for k,v in sorted(use_positions.items()): + if not v: continue + for suf in v.keys(): + tag = k + suf + print "#define %s USE_%s" % (tag, tag) +print "" +print "static const USE_TABLE_ELEMENT_TYPE use_table[] = {" +for u in uu: + if u <= last: + continue + block = data[u][1] + + start = u//8*8 + end = start+1 + while end in uu and block == data[end][1]: + end += 1 + end = (end-1)//8*8 + 7 + + if start != last + 1: + if start - last <= 1+16*3: + print_block (None, last+1, start-1, data) + last = start-1 + else: + if last >= 0: + ends.append (last + 1) + offset += ends[-1] - starts[-1] + print + print + print "#define use_offset_0x%04xu %d" % (start, offset) + starts.append (start) + + print_block (block, start, end, data) + last = end +ends.append (last + 1) +offset += ends[-1] - starts[-1] +print +print +occupancy = used * 100. / total +page_bits = 12 +print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy) +print +print "USE_TABLE_ELEMENT_TYPE" +print "hb_use_get_categories (hb_codepoint_t u)" +print "{" +print " switch (u >> %d)" % page_bits +print " {" +pages = set([u>>page_bits for u in starts+ends+singles.keys()]) +for p in sorted(pages): + print " case 0x%0Xu:" % p + for (start,end) in zip (starts, ends): + if p not in [start>>page_bits, end>>page_bits]: continue + offset = "use_offset_0x%04xu" % start + print " if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset) + for u,d in singles.items (): + if p != u>>page_bits: continue + print " if (unlikely (u == 0x%04Xu)) return %s;" % (u, d[0]) + print " break;" + print "" +print " default:" +print " break;" +print " }" +print " return USE_O;" +print "}" +print +for k in sorted(use_mapping.keys()): + if k in use_positions and use_positions[k]: continue + print "#undef %s" % k +for k,v in sorted(use_positions.items()): + if not v: continue + for suf in v.keys(): + tag = k + suf + print "#undef %s" % tag +print +print "/* == End of generated table == */" + +# Maintain at least 50% occupancy in the table */ +if occupancy < 50: + raise Exception ("Table too sparse, please investigate: ", occupancy) diff -uN gfx/harfbuzz/src_old/harfbuzz-icu.pc gfx/harfbuzz/src/harfbuzz-icu.pc --- gfx/harfbuzz/src_old/harfbuzz-icu.pc 1970-01-01 01:00:00.000000000 +0100 +++ gfx/harfbuzz/src/harfbuzz-icu.pc 2016-06-05 23:48:12.049392976 +0200 @@ -0,0 +1,13 @@ +prefix=/usr/local +exec_prefix=/usr/local +libdir=/usr/local/lib +includedir=/usr/local/include + +Name: harfbuzz +Description: HarfBuzz text shaping library ICU integration +Version: 1.0.1 + +Requires: harfbuzz +Requires.private: icu-uc +Libs: -L${libdir} -lharfbuzz-icu +Cflags: -I${includedir}/harfbuzz diff -uN gfx/harfbuzz/src_old/harfbuzz.pc gfx/harfbuzz/src/harfbuzz.pc --- gfx/harfbuzz/src_old/harfbuzz.pc 1970-01-01 01:00:00.000000000 +0100 +++ gfx/harfbuzz/src/harfbuzz.pc 2016-06-05 23:48:14.499379160 +0200 @@ -0,0 +1,11 @@ +prefix=/usr/local +exec_prefix=/usr/local +libdir=/usr/local/lib +includedir=/usr/local/include + +Name: harfbuzz +Description: HarfBuzz text shaping library +Version: 1.0.1 + +Libs: -L${libdir} -lharfbuzz +Cflags: -I${includedir}/harfbuzz diff -uN gfx/harfbuzz/src_old/harfbuzz.pc.in gfx/harfbuzz/src/harfbuzz.pc.in --- gfx/harfbuzz/src_old/harfbuzz.pc.in 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/harfbuzz.pc.in 2016-06-05 23:48:15.731372204 +0200 @@ -8,4 +8,6 @@ Version: %VERSION% Libs: -L${libdir} -lharfbuzz +Libs.private: %libs_private% +Requires.private: %requires_private% Cflags: -I${includedir}/harfbuzz diff -uN gfx/harfbuzz/src_old/hb-atomic-private.hh gfx/harfbuzz/src/hb-atomic-private.hh --- gfx/harfbuzz/src_old/hb-atomic-private.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-atomic-private.hh 2016-06-05 23:48:16.918365513 +0200 @@ -39,7 +39,11 @@ /* We need external help for these */ -#if 0 +#if defined(hb_atomic_int_impl_add) \ + && defined(hb_atomic_ptr_impl_get) \ + && defined(hb_atomic_ptr_impl_cmpexch) + +/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */ #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) @@ -58,11 +62,12 @@ #endif } -typedef LONG hb_atomic_int_t; -#define hb_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V)) +typedef LONG hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd (&(AI), (V)) -#define hb_atomic_ptr_get(P) (_HBMemoryBarrier (), (void *) *(P)) -#define hb_atomic_ptr_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) +#define hb_atomic_ptr_impl_get(P) (_HBMemoryBarrier (), (void *) *(P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O)) #elif !defined(HB_NO_MT) && defined(__APPLE__) @@ -74,28 +79,31 @@ #include #endif -typedef int32_t hb_atomic_int_t; -#define hb_atomic_int_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V)) -#define hb_atomic_ptr_get(P) (OSMemoryBarrier (), (void *) *(P)) +typedef int32_t hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V)) + +#define hb_atomic_ptr_impl_get(P) (OSMemoryBarrier (), (void *) *(P)) #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100) -#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) #else #if __ppc64__ || __x86_64__ || __aarch64__ -#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) #else -#define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) #endif #endif #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) -typedef int hb_atomic_int_t; -#define hb_atomic_int_add(AI, V) __sync_fetch_and_add (&(AI), (V)) +typedef int hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add (&(AI), (V)) -#define hb_atomic_ptr_get(P) (void *) (__sync_synchronize (), *(P)) -#define hb_atomic_ptr_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) +#define hb_atomic_ptr_impl_get(P) (void *) (__sync_synchronize (), *(P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) #elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS) @@ -103,33 +111,79 @@ #include #include -typedef unsigned int hb_atomic_int_t; -#define hb_atomic_int_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V)) +typedef unsigned int hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V)) + +#define hb_atomic_ptr_impl_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false) + + +#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__) + +#include + + +static inline int hb_fetch_and_add(volatile int* AI, unsigned int V) { + __lwsync(); + int result = __fetch_and_add(AI, V); + __isync(); + return result; +} +static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) { + __sync(); + int result = __compare_and_swaplp (P, &O, N); + __sync(); + return result; +} -#define hb_atomic_ptr_get(P) ( ({__machine_rw_barrier ();}), (void *) *(P)) -#define hb_atomic_ptr_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false) +typedef int hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) hb_fetch_and_add (&(AI), (V)) +#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N)) #elif !defined(HB_NO_MT) #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ -typedef volatile int hb_atomic_int_t; -#define hb_atomic_int_add(AI, V) (((AI) += (V)) - (V)) -#define hb_atomic_ptr_get(P) ((void *) *(P)) -#define hb_atomic_ptr_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false) +typedef volatile int hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V)) + +#define hb_atomic_ptr_impl_get(P) ((void *) *(P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false) #else /* HB_NO_MT */ -typedef int hb_atomic_int_t; -#define hb_atomic_int_add(AI, V) (((AI) += (V)) - (V)) +typedef int hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) (((AI) += (V)) - (V)) + +#define hb_atomic_ptr_impl_get(P) ((void *) *(P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) -#define hb_atomic_ptr_get(P) ((void *) *(P)) -#define hb_atomic_ptr_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) #endif -/* TODO Add tracing. */ + +#define HB_ATOMIC_INT_INIT(V) {HB_ATOMIC_INT_IMPL_INIT(V)} + +struct hb_atomic_int_t +{ + hb_atomic_int_impl_t v; + + inline void set_unsafe (int v_) { v = v_; } + inline int get_unsafe (void) const { return v; } + inline int inc (void) { return hb_atomic_int_impl_add (const_cast (v), 1); } + inline int dec (void) { return hb_atomic_int_impl_add (const_cast (v), -1); } +}; + + +#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P) +#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N)) + #endif /* HB_ATOMIC_PRIVATE_HH */ diff -uN gfx/harfbuzz/src_old/hb-blob.cc gfx/harfbuzz/src/hb-blob.cc --- gfx/harfbuzz/src_old/hb-blob.cc 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-blob.cc 2016-06-05 23:48:18.064359059 +0200 @@ -78,8 +78,8 @@ } /** - * hb_blob_create: (Xconstructor) - * @data: (array length=length) (closure user_data) (destroy destroy) (scope notified) (transfer none): Pointer to blob data. + * hb_blob_create: (skip) + * @data: Pointer to blob data. * @length: Length of @data in bytes. * @mode: Memory mode for @data. * @user_data: Data parameter to pass to @destroy. @@ -91,7 +91,7 @@ * Return value: New blob, or the empty blob if something failed or if @length is * zero. Destroy with hb_blob_destroy(). * - * Since: 1.0 + * Since: 0.9.2 **/ hb_blob_t * hb_blob_create (const char *data, @@ -147,7 +147,7 @@ * @length is zero or @offset is beyond the end of @parent's data. Destroy * with hb_blob_destroy(). * - * Since: 1.0 + * Since: 0.9.2 **/ hb_blob_t * hb_blob_create_sub_blob (hb_blob_t *parent, @@ -179,7 +179,7 @@ * * Return value: (transfer full): the empty blob. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_blob_t * hb_blob_get_empty (void) @@ -210,7 +210,7 @@ * * Return value: @blob. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_blob_t * hb_blob_reference (hb_blob_t *blob) @@ -228,7 +228,7 @@ * * See TODO:link object types for more information. * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_blob_destroy (hb_blob_t *blob) @@ -250,7 +250,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_blob_set_user_data (hb_blob_t *blob, @@ -271,7 +271,7 @@ * * Return value: (transfer none): * - * Since: 1.0 + * Since: 0.9.2 **/ void * hb_blob_get_user_data (hb_blob_t *blob, @@ -287,7 +287,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_blob_make_immutable (hb_blob_t *blob) @@ -306,7 +306,7 @@ * * Return value: TODO * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_blob_is_immutable (hb_blob_t *blob) @@ -323,7 +323,7 @@ * * Return value: the length of blob data in bytes. * - * Since: 1.0 + * Since: 0.9.2 **/ unsigned int hb_blob_get_length (hb_blob_t *blob) @@ -340,7 +340,7 @@ * * Returns: (transfer none) (array length=length): * - * Since: 1.0 + * Since: 0.9.2 **/ const char * hb_blob_get_data (hb_blob_t *blob, unsigned int *length) @@ -365,7 +365,7 @@ * Returns: (transfer none) (array length=length): Writable blob data, * or %NULL if failed. * - * Since: 1.0 + * Since: 0.9.2 **/ char * hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) diff -uN gfx/harfbuzz/src_old/hb-blob.h gfx/harfbuzz/src/hb-blob.h --- gfx/harfbuzz/src_old/hb-blob.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-blob.h 2016-06-05 23:48:19.231352500 +0200 @@ -64,7 +64,7 @@ typedef struct hb_blob_t hb_blob_t; -hb_blob_t * +HB_EXTERN hb_blob_t * hb_blob_create (const char *data, unsigned int length, hb_memory_mode_t mode, @@ -77,21 +77,21 @@ * modify the parent data as that data may be * shared among multiple sub-blobs. */ -hb_blob_t * +HB_EXTERN hb_blob_t * hb_blob_create_sub_blob (hb_blob_t *parent, unsigned int offset, unsigned int length); -hb_blob_t * +HB_EXTERN hb_blob_t * hb_blob_get_empty (void); -hb_blob_t * +HB_EXTERN hb_blob_t * hb_blob_reference (hb_blob_t *blob); -void +HB_EXTERN void hb_blob_destroy (hb_blob_t *blob); -hb_bool_t +HB_EXTERN hb_bool_t hb_blob_set_user_data (hb_blob_t *blob, hb_user_data_key_t *key, void * data, @@ -99,25 +99,25 @@ hb_bool_t replace); -void * +HB_EXTERN void * hb_blob_get_user_data (hb_blob_t *blob, hb_user_data_key_t *key); -void +HB_EXTERN void hb_blob_make_immutable (hb_blob_t *blob); -hb_bool_t +HB_EXTERN hb_bool_t hb_blob_is_immutable (hb_blob_t *blob); -unsigned int +HB_EXTERN unsigned int hb_blob_get_length (hb_blob_t *blob); -const char * +HB_EXTERN const char * hb_blob_get_data (hb_blob_t *blob, unsigned int *length); -char * +HB_EXTERN char * hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length); diff -uN gfx/harfbuzz/src_old/hb-buffer.cc gfx/harfbuzz/src/hb-buffer.cc --- gfx/harfbuzz/src_old/hb-buffer.cc 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-buffer.cc 2016-06-05 23:48:28.261301901 +0200 @@ -35,7 +35,28 @@ #define HB_DEBUG_BUFFER (HB_DEBUG+0) #endif +/** + * SECTION: hb-buffer + * @title: Buffers + * @short_description: Input and output buffers + * @include: hb.h + * + * Buffers serve dual role in HarfBuzz; they hold the input characters that are + * passed hb_shape(), and after shaping they hold the output glyphs. + **/ +/** + * hb_segment_properties_equal: + * @a: first #hb_segment_properties_t to compare. + * @b: second #hb_segment_properties_t to compare. + * + * Checks the equality of two #hb_segment_properties_t's. + * + * Return value: (transfer full): + * %true if all properties of @a equal those of @b, false otherwise. + * + * Since: 0.9.7 + **/ hb_bool_t hb_segment_properties_equal (const hb_segment_properties_t *a, const hb_segment_properties_t *b) @@ -48,6 +69,17 @@ } +/** + * hb_segment_properties_hash: + * @p: #hb_segment_properties_t to hash. + * + * Creates a hash representing @p. + * + * Return value: + * A hash of @p. + * + * Since: 0.9.7 + **/ unsigned int hb_segment_properties_hash (const hb_segment_properties_t *p) { @@ -85,6 +117,11 @@ { if (unlikely (in_error)) return false; + if (unlikely (size > max_len)) + { + in_error = true; + return false; + } unsigned int new_allocated = allocated; hb_glyph_position_t *new_pos = NULL; @@ -192,6 +229,7 @@ hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; props = default_props; + scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; content_type = HB_BUFFER_CONTENT_TYPE_INVALID; in_error = false; @@ -443,7 +481,7 @@ { unsigned int i, j; - if (start == end - 1) + if (end - start < 2) return; for (i = start, j = end - 1; i < j; i++, j--) { @@ -454,7 +492,7 @@ info[j] = t; } - if (pos) { + if (have_positions) { for (i = start, j = end - 1; i < j; i++, j--) { hb_glyph_position_t t; @@ -498,14 +536,10 @@ } void -hb_buffer_t::merge_clusters (unsigned int start, - unsigned int end) +hb_buffer_t::merge_clusters_impl (unsigned int start, + unsigned int end) { -#ifdef HB_NO_MERGE_CLUSTERS - return; -#endif - - if (unlikely (end - start < 2)) + if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) return; unsigned int cluster = info[start].cluster; @@ -523,7 +557,7 @@ /* If we hit the start of buffer, continue in out-buffer. */ if (idx == start) - for (unsigned i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) + for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) out_info[i - 1].cluster = cluster; for (unsigned int i = start; i < end; i++) @@ -533,9 +567,8 @@ hb_buffer_t::merge_out_clusters (unsigned int start, unsigned int end) { -#ifdef HB_NO_MERGE_CLUSTERS - return; -#endif + if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) + return; if (unlikely (end - start < 2)) return; @@ -555,12 +588,44 @@ /* If we hit the end of out-buffer, continue in buffer. */ if (end == out_len) - for (unsigned i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++) + for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++) info[i].cluster = cluster; for (unsigned int i = start; i < end; i++) out_info[i].cluster = cluster; } +void +hb_buffer_t::delete_glyph () +{ + unsigned int cluster = info[idx].cluster; + if (idx + 1 < len && cluster == info[idx + 1].cluster) + { + /* Cluster survives; do nothing. */ + goto done; + } + + if (out_len) + { + /* Merge cluster backward. */ + if (cluster < out_info[out_len - 1].cluster) + { + unsigned int old_cluster = out_info[out_len - 1].cluster; + for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--) + out_info[i - 1].cluster = cluster; + } + goto done; + } + + if (idx + 1 < len) + { + /* Merge cluster forward. */ + merge_clusters (idx, idx + 2); + goto done; + } + +done: + skip_glyph (); +} void hb_buffer_t::guess_segment_properties (void) @@ -667,11 +732,16 @@ /** * hb_buffer_create: (Xconstructor) * - * + * Creates a new #hb_buffer_t with all properties to defaults. * - * Return value: (transfer full) + * Return value: (transfer full): + * A newly allocated #hb_buffer_t with a reference count of 1. The initial + * reference count should be released with hb_buffer_destroy() when you are done + * using the #hb_buffer_t. This function never returns %NULL. If memory cannot + * be allocated, a special #hb_buffer_t object will be returned on which + * hb_buffer_allocation_successful() returns %false. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_buffer_t * hb_buffer_create (void) @@ -681,6 +751,8 @@ if (!(buffer = hb_object_create ())) return hb_buffer_get_empty (); + buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT; + buffer->reset (); return buffer; @@ -693,7 +765,7 @@ * * Return value: (transfer full): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_buffer_t * hb_buffer_get_empty (void) @@ -703,7 +775,10 @@ const_cast (&_hb_unicode_funcs_nil), HB_BUFFER_FLAG_DEFAULT, + HB_BUFFER_CLUSTER_LEVEL_DEFAULT, HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, + HB_BUFFER_SCRATCH_FLAG_DEFAULT, + HB_BUFFER_MAX_LEN_DEFAULT, HB_BUFFER_CONTENT_TYPE_INVALID, HB_SEGMENT_PROPERTIES_DEFAULT, @@ -719,13 +794,15 @@ /** * hb_buffer_reference: (skip) - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Increases the reference count on @buffer by one. This prevents @buffer from + * being destroyed until a matching call to hb_buffer_destroy() is made. * * Return value: (transfer full): + * The referenced #hb_buffer_t. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_buffer_t * hb_buffer_reference (hb_buffer_t *buffer) @@ -735,11 +812,13 @@ /** * hb_buffer_destroy: (skip) - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Deallocate the @buffer. + * Decreases the reference count on @buffer by one. If the result is zero, then + * @buffer and all associated resources are freed. See hb_buffer_reference(). * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_buffer_destroy (hb_buffer_t *buffer) @@ -750,13 +829,15 @@ free (buffer->info); free (buffer->pos); + if (buffer->message_destroy) + buffer->message_destroy (buffer->message_data); free (buffer); } /** * hb_buffer_set_user_data: (skip) - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @key: * @data: * @destroy: @@ -766,7 +847,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_buffer_set_user_data (hb_buffer_t *buffer, @@ -780,14 +861,14 @@ /** * hb_buffer_get_user_data: (skip) - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @key: * * * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ void * hb_buffer_get_user_data (hb_buffer_t *buffer, @@ -799,12 +880,13 @@ /** * hb_buffer_set_content_type: - * @buffer: a buffer. - * @content_type: + * @buffer: an #hb_buffer_t. + * @content_type: the type of buffer contents to set * - * + * Sets the type of @buffer contents, buffers are either empty, contain + * characters (before shaping) or glyphs (the result of shaping). * - * Since: 1.0 + * Since: 0.9.5 **/ void hb_buffer_set_content_type (hb_buffer_t *buffer, @@ -815,13 +897,14 @@ /** * hb_buffer_get_content_type: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * see hb_buffer_set_content_type(). * - * Return value: + * Return value: + * The type of @buffer contents. * - * Since: 1.0 + * Since: 0.9.5 **/ hb_buffer_content_type_t hb_buffer_get_content_type (hb_buffer_t *buffer) @@ -832,12 +915,12 @@ /** * hb_buffer_set_unicode_funcs: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @unicode_funcs: * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, @@ -857,13 +940,13 @@ /** * hb_buffer_get_unicode_funcs: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_unicode_funcs_t * hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) @@ -873,12 +956,18 @@ /** * hb_buffer_set_direction: - * @buffer: a buffer. - * @direction: + * @buffer: an #hb_buffer_t. + * @direction: the #hb_direction_t of the @buffer * - * + * Set the text flow direction of the buffer. No shaping can happen without + * setting @buffer direction, and it controls the visual direction for the + * output glyphs; for RTL direction the glyphs will be reversed. Many layout + * features depend on the proper setting of the direction, for example, + * reversing RTL text before shaping, then shaping with LTR direction is not + * the same as keeping the text in logical order and shaping with RTL + * direction. * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_buffer_set_direction (hb_buffer_t *buffer, @@ -893,13 +982,14 @@ /** * hb_buffer_get_direction: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_direction() * - * Return value: + * Return value: + * The direction of the @buffer. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_direction_t hb_buffer_get_direction (hb_buffer_t *buffer) @@ -909,12 +999,20 @@ /** * hb_buffer_set_script: - * @buffer: a buffer. - * @script: + * @buffer: an #hb_buffer_t. + * @script: an #hb_script_t to set. * - * + * Sets the script of @buffer to @script. * - * Since: 1.0 + * Script is crucial for choosing the proper shaping behaviour for scripts that + * require it (e.g. Arabic) and the which OpenType features defined in the font + * to be applied. + * + * You can pass one of the predefined #hb_script_t values, or use + * hb_script_from_string() or hb_script_from_iso15924_tag() to get the + * corresponding script from an ISO 15924 script tag. + * + * Since: 0.9.2 **/ void hb_buffer_set_script (hb_buffer_t *buffer, @@ -928,13 +1026,14 @@ /** * hb_buffer_get_script: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_script(). * - * Return value: + * Return value: + * The #hb_script_t of the @buffer. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_script_t hb_buffer_get_script (hb_buffer_t *buffer) @@ -944,12 +1043,20 @@ /** * hb_buffer_set_language: - * @buffer: a buffer. - * @language: + * @buffer: an #hb_buffer_t. + * @language: an hb_language_t to set. * - * + * Sets the language of @buffer to @language. + * + * Languages are crucial for selecting which OpenType feature to apply to the + * buffer which can result in applying language-specific behaviour. Languages + * are orthogonal to the scripts, and though they are related, they are + * different concepts and should not be confused with each other. + * + * Use hb_language_from_string() to convert from ISO 639 language codes to + * #hb_language_t. * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_buffer_set_language (hb_buffer_t *buffer, @@ -963,13 +1070,14 @@ /** * hb_buffer_get_language: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_language(). * - * Return value: + * Return value: (transfer none): + * The #hb_language_t of the buffer. Must not be freed by the caller. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_language_t hb_buffer_get_language (hb_buffer_t *buffer) @@ -979,12 +1087,14 @@ /** * hb_buffer_set_segment_properties: - * @buffer: a buffer. - * @props: + * @buffer: an #hb_buffer_t. + * @props: an #hb_segment_properties_t to use. * - * + * Sets the segment properties of the buffer, a shortcut for calling + * hb_buffer_set_direction(), hb_buffer_set_script() and + * hb_buffer_set_language() individually. * - * Since: 1.0 + * Since: 0.9.7 **/ void hb_buffer_set_segment_properties (hb_buffer_t *buffer, @@ -998,12 +1108,12 @@ /** * hb_buffer_get_segment_properties: - * @buffer: a buffer. - * @props: + * @buffer: an #hb_buffer_t. + * @props: (out): the output #hb_segment_properties_t. * - * + * Sets @props to the #hb_segment_properties_t of @buffer. * - * Since: 1.0 + * Since: 0.9.7 **/ void hb_buffer_get_segment_properties (hb_buffer_t *buffer, @@ -1015,12 +1125,12 @@ /** * hb_buffer_set_flags: - * @buffer: a buffer. - * @flags: + * @buffer: an #hb_buffer_t. + * @flags: the buffer flags to set. * - * + * Sets @buffer flags to @flags. See #hb_buffer_flags_t. * - * Since: 1.0 + * Since: 0.9.7 **/ void hb_buffer_set_flags (hb_buffer_t *buffer, @@ -1034,13 +1144,14 @@ /** * hb_buffer_get_flags: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_flags(). * * Return value: + * The @buffer flags. * - * Since: 1.0 + * Since: 0.9.7 **/ hb_buffer_flags_t hb_buffer_get_flags (hb_buffer_t *buffer) @@ -1048,15 +1159,53 @@ return buffer->flags; } +/** + * hb_buffer_set_cluster_level: + * @buffer: an #hb_buffer_t. + * @cluster_level: + * + * + * + * Since: 0.9.42 + **/ +void +hb_buffer_set_cluster_level (hb_buffer_t *buffer, + hb_buffer_cluster_level_t cluster_level) +{ + if (unlikely (hb_object_is_inert (buffer))) + return; + + buffer->cluster_level = cluster_level; +} + +/** + * hb_buffer_get_cluster_level: + * @buffer: an #hb_buffer_t. + * + * + * + * Return value: + * + * Since: 0.9.42 + **/ +hb_buffer_cluster_level_t +hb_buffer_get_cluster_level (hb_buffer_t *buffer) +{ + return buffer->cluster_level; +} + /** * hb_buffer_set_replacement_codepoint: - * @buffer: a buffer. - * @replacement: + * @buffer: an #hb_buffer_t. + * @replacement: the replacement #hb_codepoint_t * - * + * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding + * when adding text to @buffer. * - * Since: 1.0 + * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT. + * + * Since: 0.9.31 **/ void hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, @@ -1070,13 +1219,14 @@ /** * hb_buffer_get_replacement_codepoint: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * See hb_buffer_set_replacement_codepoint(). * * Return value: + * The @buffer replacement #hb_codepoint_t. * - * Since: 1.0 + * Since: 0.9.31 **/ hb_codepoint_t hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) @@ -1087,11 +1237,12 @@ /** * hb_buffer_reset: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Resets the buffer to its initial status, as if it was just newly created + * with hb_buffer_create(). * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_buffer_reset (hb_buffer_t *buffer) @@ -1101,11 +1252,12 @@ /** * hb_buffer_clear_contents: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Similar to hb_buffer_reset(), but does not clear the Unicode functions and + * the replacement code point. * - * Since: 1.0 + * Since: 0.9.11 **/ void hb_buffer_clear_contents (hb_buffer_t *buffer) @@ -1115,14 +1267,15 @@ /** * hb_buffer_pre_allocate: - * @buffer: a buffer. - * @size: + * @buffer: an #hb_buffer_t. + * @size: number of items to pre allocate. * - * + * Pre allocates memory for @buffer to fit at least @size number of items. * - * Return value: + * Return value: + * %true if @buffer memory allocation succeeded, %false otherwise. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) @@ -1132,13 +1285,14 @@ /** * hb_buffer_allocation_successful: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Check if allocating memory for the buffer succeeded. * - * Return value: + * Return value: + * %true if @buffer memory allocation succeeded, %false otherwise. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_buffer_allocation_successful (hb_buffer_t *buffer) @@ -1148,13 +1302,20 @@ /** * hb_buffer_add: - * @buffer: a buffer. - * @codepoint: - * @cluster: + * @buffer: an #hb_buffer_t. + * @codepoint: a Unicode code point. + * @cluster: the cluster value of @codepoint. + * + * Appends a character with the Unicode value of @codepoint to @buffer, and + * gives it the initial cluster value of @cluster. Clusters can be any thing + * the client wants, they are usually used to refer to the index of the + * character in the input text stream and are output in + * #hb_glyph_info_t.cluster field. * - * + * This function does not check the validity of @codepoint, it is up to the + * caller to ensure it is a valid Unicode code point. * - * Since: 1.0 + * Since: 0.9.7 **/ void hb_buffer_add (hb_buffer_t *buffer, @@ -1167,14 +1328,16 @@ /** * hb_buffer_set_length: - * @buffer: a buffer. - * @length: + * @buffer: an #hb_buffer_t. + * @length: the new length of @buffer. * - * + * Similar to hb_buffer_pre_allocate(), but clears any new items added at the + * end. * * Return value: + * %true if @buffer memory allocation succeeded, %false otherwise. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_buffer_set_length (hb_buffer_t *buffer, @@ -1207,13 +1370,15 @@ /** * hb_buffer_get_length: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * Returns the number of items in the buffer. * - * Return value: buffer length. + * Return value: + * The @buffer length. + * The value valid as long as buffer has not been modified. * - * Since: 1.0 + * Since: 0.9.2 **/ unsigned int hb_buffer_get_length (hb_buffer_t *buffer) @@ -1223,15 +1388,17 @@ /** * hb_buffer_get_glyph_infos: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @length: (out): output array length. * - * Returns buffer glyph information array. Returned pointer - * is valid as long as buffer contents are not modified. + * Returns @buffer glyph information array. Returned pointer + * is valid as long as @buffer contents are not modified. * - * Return value: (transfer none) (array length=length): buffer glyph information array. + * Return value: (transfer none) (array length=length): + * The @buffer glyph information array. + * The value valid as long as buffer has not been modified. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_glyph_info_t * hb_buffer_get_glyph_infos (hb_buffer_t *buffer, @@ -1245,15 +1412,17 @@ /** * hb_buffer_get_glyph_positions: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * @length: (out): output length. * - * Returns buffer glyph position array. Returned pointer - * is valid as long as buffer contents are not modified. + * Returns @buffer glyph position array. Returned pointer + * is valid as long as @buffer contents are not modified. * - * Return value: (transfer none) (array length=length): buffer glyph position array. + * Return value: (transfer none) (array length=length): + * The @buffer glyph position array. + * The value valid as long as buffer has not been modified. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_glyph_position_t * hb_buffer_get_glyph_positions (hb_buffer_t *buffer, @@ -1270,11 +1439,11 @@ /** * hb_buffer_reverse: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * Reverses buffer contents. * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_buffer_reverse (hb_buffer_t *buffer) @@ -1283,14 +1452,31 @@ } /** + * hb_buffer_reverse_range: + * @buffer: an #hb_buffer_t. + * @start: start index. + * @end: end index. + * + * Reverses buffer contents between start to end. + * + * Since: 0.9.41 + **/ +void +hb_buffer_reverse_range (hb_buffer_t *buffer, + unsigned int start, unsigned int end) +{ + buffer->reverse_range (start, end); +} + +/** * hb_buffer_reverse_clusters: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * Reverses buffer clusters. That is, the buffer contents are * reversed, then each cluster (consecutive items having the * same cluster number) are reversed again. * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_buffer_reverse_clusters (hb_buffer_t *buffer) @@ -1300,7 +1486,7 @@ /** * hb_buffer_guess_segment_properties: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * * Sets unset buffer segment properties based on buffer Unicode * contents. If buffer is not empty, it must have content type @@ -1320,7 +1506,7 @@ * hb_language_get_default(). This may change in the future by * taking buffer script into consideration when choosing a language. * - * Since: 1.0 + * Since: 0.9.7 **/ void hb_buffer_guess_segment_properties (hb_buffer_t *buffer) @@ -1328,15 +1514,15 @@ buffer->guess_segment_properties (); } -template +template static inline void hb_buffer_add_utf (hb_buffer_t *buffer, - const T *text, + const typename utf_t::codepoint_t *text, int text_length, unsigned int item_offset, int item_length) { - typedef hb_utf_t utf_t; + typedef typename utf_t::codepoint_t T; const hb_codepoint_t replacement = buffer->replacement; assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || @@ -1399,15 +1585,20 @@ /** * hb_buffer_add_utf8: - * @buffer: a buffer. - * @text: (array length=text_length): - * @text_length: - * @item_offset: - * @item_length: + * @buffer: an #hb_buffer_t. + * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 + * characters to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first character to add to the @buffer. + * @item_length: the number of characters to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). * - * + * See hb_buffer_add_codepoints(). * - * Since: 1.0 + * Replaces invalid UTF-8 characters with the @buffer replacement code point, + * see hb_buffer_set_replacement_codepoint(). + * + * Since: 0.9.2 **/ void hb_buffer_add_utf8 (hb_buffer_t *buffer, @@ -1416,20 +1607,24 @@ unsigned int item_offset, int item_length) { - hb_buffer_add_utf (buffer, (const uint8_t *) text, text_length, item_offset, item_length); + hb_buffer_add_utf (buffer, (const uint8_t *) text, text_length, item_offset, item_length); } /** * hb_buffer_add_utf16: - * @buffer: a buffer. - * @text: (array length=text_length): - * @text_length: - * @item_offset: - * @item_length: + * @buffer: an #hb_buffer_t. + * @text: (array length=text_length): an array of UTF-16 characters to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first character to add to the @buffer. + * @item_length: the number of characters to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). * - * + * See hb_buffer_add_codepoints(). * - * Since: 1.0 + * Replaces invalid UTF-16 characters with the @buffer replacement code point, + * see hb_buffer_set_replacement_codepoint(). + * + * Since: 0.9.2 **/ void hb_buffer_add_utf16 (hb_buffer_t *buffer, @@ -1438,20 +1633,24 @@ unsigned int item_offset, int item_length) { - hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); + hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); } /** * hb_buffer_add_utf32: - * @buffer: a buffer. - * @text: (array length=text_length): - * @text_length: - * @item_offset: - * @item_length: + * @buffer: an #hb_buffer_t. + * @text: (array length=text_length): an array of UTF-32 characters to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first character to add to the @buffer. + * @item_length: the number of characters to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). * - * + * See hb_buffer_add_codepoints(). * - * Since: 1.0 + * Replaces invalid UTF-32 characters with the @buffer replacement code point, + * see hb_buffer_set_replacement_codepoint(). + * + * Since: 0.9.2 **/ void hb_buffer_add_utf32 (hb_buffer_t *buffer, @@ -1460,20 +1659,59 @@ unsigned int item_offset, int item_length) { - hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); + hb_buffer_add_utf > (buffer, text, text_length, item_offset, item_length); +} + +/** + * hb_buffer_add_latin1: + * @buffer: an #hb_buffer_t. + * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8 + * characters to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first character to add to the @buffer. + * @item_length: the number of characters to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). + * + * Similar to hb_buffer_add_codepoints(), but allows only access to first 256 + * Unicode code points that can fit in 8-bit strings. + * + * Has nothing to do with non-Unicode Latin-1 encoding. + * + * Since: 0.9.39 + **/ +void +hb_buffer_add_latin1 (hb_buffer_t *buffer, + const uint8_t *text, + int text_length, + unsigned int item_offset, + int item_length) +{ + hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); } /** * hb_buffer_add_codepoints: - * @buffer: a buffer. - * @text: (array length=text_length): - * @text_length: - * @item_offset: - * @item_length: + * @buffer: a #hb_buffer_t to append characters to. + * @text: (array length=text_length): an array of Unicode code points to append. + * @text_length: the length of the @text, or -1 if it is %NULL terminated. + * @item_offset: the offset of the first code point to add to the @buffer. + * @item_length: the number of code points to add to the @buffer, or -1 for the + * end of @text (assuming it is %NULL terminated). + * + * Appends characters from @text array to @buffer. The @item_offset is the + * position of the first character from @text that will be appended, and + * @item_length is the number of character. When shaping part of a larger text + * (e.g. a run of text from a paragraph), instead of passing just the substring + * corresponding to the run, it is preferable to pass the whole + * paragraph and specify the run start and length as @item_offset and + * @item_length, respectively, to give HarfBuzz the full context to be able, + * for example, to do cross-run Arabic shaping or properly handle combining + * marks at stat of run. * - * + * This function does not check the validity of @text, it is up to the caller + * to ensure it contains a valid Unicode code points. * - * Since: 1.0 + * Since: 0.9.31 **/ void hb_buffer_add_codepoints (hb_buffer_t *buffer, @@ -1482,7 +1720,7 @@ unsigned int item_offset, int item_length) { - hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); + hb_buffer_add_utf > (buffer, text, text_length, item_offset, item_length); } @@ -1528,7 +1766,7 @@ pos[end - 1].x_advance = total_x_advance; pos[end - 1].y_advance = total_y_advance; - hb_bubble_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start); + hb_stable_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start); } else { /* Transfer all cluster advance to the first glyph. */ pos[start].x_advance += total_x_advance; @@ -1537,17 +1775,20 @@ pos[i].x_offset -= total_x_advance; pos[i].y_offset -= total_y_advance; } - hb_bubble_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1); + hb_stable_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1); } } /** * hb_buffer_normalize_glyphs: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t. * - * + * Reorders a glyph buffer to have canonical in-cluster glyph order / position. + * The resulting clusters should behave identical to pre-reordering clusters. * - * Since: 1.0 + * This has nothing to do with Unicode normalization. + * + * Since: 0.9.2 **/ void hb_buffer_normalize_glyphs (hb_buffer_t *buffer) @@ -1570,3 +1811,66 @@ } normalize_glyphs_cluster (buffer, start, end, backward); } + +void +hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *)) +{ + assert (!have_positions); + for (unsigned int i = start + 1; i < end; i++) + { + unsigned int j = i; + while (j > start && compar (&info[j - 1], &info[i]) > 0) + j--; + if (i == j) + continue; + /* Move item i to occupy place for item j, shift what's in between. */ + merge_clusters (j, i + 1); + { + hb_glyph_info_t t = info[i]; + memmove (&info[j + 1], &info[j], (i - j) * sizeof (hb_glyph_info_t)); + info[j] = t; + } + } +} + +/* + * Debugging. + */ + +/** + * hb_buffer_set_message_func: + * @buffer: an #hb_buffer_t. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.1.3 + **/ +void +hb_buffer_set_message_func (hb_buffer_t *buffer, + hb_buffer_message_func_t func, + void *user_data, hb_destroy_func_t destroy) +{ + if (buffer->message_destroy) + buffer->message_destroy (buffer->message_data); + + if (func) { + buffer->message_func = func; + buffer->message_data = user_data; + buffer->message_destroy = destroy; + } else { + buffer->message_func = NULL; + buffer->message_data = NULL; + buffer->message_destroy = NULL; + } +} + +bool +hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap) +{ + char buf[100]; + vsnprintf (buf, sizeof (buf), fmt, ap); + return (bool) this->message_func (this, font, buf, this->message_data); +} diff -uN gfx/harfbuzz/src_old/hb-buffer-deserialize-json.hh gfx/harfbuzz/src/hb-buffer-deserialize-json.hh --- gfx/harfbuzz/src_old/hb-buffer-deserialize-json.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-buffer-deserialize-json.hh 2016-06-05 23:48:20.553345078 +0200 @@ -1,5 +1,5 @@ -#line 1 "../../src/hb-buffer-deserialize-json.rl" +#line 1 "hb-buffer-deserialize-json.rl" /* * Copyright © 2013 Google, Inc. * @@ -32,7 +32,7 @@ #include "hb-private.hh" -#line 36 "hb-buffer-deserialize-json.hh.tmp" +#line 36 "hb-buffer-deserialize-json.hh" static const unsigned char _deserialize_json_trans_keys[] = { 0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, @@ -435,7 +435,7 @@ static const int deserialize_json_en_main = 1; -#line 97 "../../src/hb-buffer-deserialize-json.rl" +#line 97 "hb-buffer-deserialize-json.rl" static hb_bool_t @@ -459,15 +459,15 @@ const char *tok = NULL; int cs; - hb_glyph_info_t info; - hb_glyph_position_t pos; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; -#line 466 "hb-buffer-deserialize-json.hh.tmp" +#line 466 "hb-buffer-deserialize-json.hh" { cs = deserialize_json_start; } -#line 471 "hb-buffer-deserialize-json.hh.tmp" +#line 471 "hb-buffer-deserialize-json.hh" { int _slen; int _trans; @@ -493,14 +493,14 @@ switch ( _deserialize_json_trans_actions[_trans] ) { case 1: -#line 38 "../../src/hb-buffer-deserialize-json.rl" +#line 38 "hb-buffer-deserialize-json.rl" { memset (&info, 0, sizeof (info)); memset (&pos , 0, sizeof (pos )); } break; case 5: -#line 43 "../../src/hb-buffer-deserialize-json.rl" +#line 43 "hb-buffer-deserialize-json.rl" { buffer->add_info (info); if (buffer->in_error) @@ -510,13 +510,13 @@ } break; case 2: -#line 51 "../../src/hb-buffer-deserialize-json.rl" +#line 51 "hb-buffer-deserialize-json.rl" { tok = p; } break; case 14: -#line 55 "../../src/hb-buffer-deserialize-json.rl" +#line 55 "hb-buffer-deserialize-json.rl" { if (!hb_font_glyph_from_string (font, tok, p - tok, @@ -525,33 +525,33 @@ } break; case 15: -#line 62 "../../src/hb-buffer-deserialize-json.rl" +#line 62 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.codepoint)) return false; } break; case 8: -#line 63 "../../src/hb-buffer-deserialize-json.rl" +#line 63 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } break; case 10: -#line 64 "../../src/hb-buffer-deserialize-json.rl" +#line 64 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } break; case 12: -#line 65 "../../src/hb-buffer-deserialize-json.rl" +#line 65 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } break; case 3: -#line 66 "../../src/hb-buffer-deserialize-json.rl" +#line 66 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } break; case 6: -#line 67 "../../src/hb-buffer-deserialize-json.rl" +#line 67 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } break; case 16: -#line 62 "../../src/hb-buffer-deserialize-json.rl" +#line 62 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.codepoint)) return false; } -#line 43 "../../src/hb-buffer-deserialize-json.rl" +#line 43 "hb-buffer-deserialize-json.rl" { buffer->add_info (info); if (buffer->in_error) @@ -561,9 +561,9 @@ } break; case 9: -#line 63 "../../src/hb-buffer-deserialize-json.rl" +#line 63 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } -#line 43 "../../src/hb-buffer-deserialize-json.rl" +#line 43 "hb-buffer-deserialize-json.rl" { buffer->add_info (info); if (buffer->in_error) @@ -573,9 +573,9 @@ } break; case 11: -#line 64 "../../src/hb-buffer-deserialize-json.rl" +#line 64 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } -#line 43 "../../src/hb-buffer-deserialize-json.rl" +#line 43 "hb-buffer-deserialize-json.rl" { buffer->add_info (info); if (buffer->in_error) @@ -585,9 +585,9 @@ } break; case 13: -#line 65 "../../src/hb-buffer-deserialize-json.rl" +#line 65 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } -#line 43 "../../src/hb-buffer-deserialize-json.rl" +#line 43 "hb-buffer-deserialize-json.rl" { buffer->add_info (info); if (buffer->in_error) @@ -597,9 +597,9 @@ } break; case 4: -#line 66 "../../src/hb-buffer-deserialize-json.rl" +#line 66 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } -#line 43 "../../src/hb-buffer-deserialize-json.rl" +#line 43 "hb-buffer-deserialize-json.rl" { buffer->add_info (info); if (buffer->in_error) @@ -609,9 +609,9 @@ } break; case 7: -#line 67 "../../src/hb-buffer-deserialize-json.rl" +#line 67 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } -#line 43 "../../src/hb-buffer-deserialize-json.rl" +#line 43 "hb-buffer-deserialize-json.rl" { buffer->add_info (info); if (buffer->in_error) @@ -620,7 +620,7 @@ *end_ptr = p; } break; -#line 624 "hb-buffer-deserialize-json.hh.tmp" +#line 624 "hb-buffer-deserialize-json.hh" } _again: @@ -632,7 +632,7 @@ _out: {} } -#line 125 "../../src/hb-buffer-deserialize-json.rl" +#line 125 "hb-buffer-deserialize-json.rl" *end_ptr = p; diff -uN gfx/harfbuzz/src_old/hb-buffer-deserialize-text.hh gfx/harfbuzz/src/hb-buffer-deserialize-text.hh --- gfx/harfbuzz/src_old/hb-buffer-deserialize-text.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-buffer-deserialize-text.hh 2016-06-05 23:48:23.120330665 +0200 @@ -1,5 +1,5 @@ -#line 1 "../../src/hb-buffer-deserialize-text.rl" +#line 1 "hb-buffer-deserialize-text.rl" /* * Copyright © 2013 Google, Inc. * @@ -32,7 +32,7 @@ #include "hb-private.hh" -#line 36 "hb-buffer-deserialize-text.hh.tmp" +#line 36 "hb-buffer-deserialize-text.hh" static const unsigned char _deserialize_text_trans_keys[] = { 0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, @@ -312,7 +312,7 @@ static const int deserialize_text_en_main = 1; -#line 91 "../../src/hb-buffer-deserialize-text.rl" +#line 91 "hb-buffer-deserialize-text.rl" static hb_bool_t @@ -336,15 +336,15 @@ const char *eof = pe, *tok = NULL; int cs; - hb_glyph_info_t info; - hb_glyph_position_t pos; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; -#line 343 "hb-buffer-deserialize-text.hh.tmp" +#line 343 "hb-buffer-deserialize-text.hh" { cs = deserialize_text_start; } -#line 348 "hb-buffer-deserialize-text.hh.tmp" +#line 348 "hb-buffer-deserialize-text.hh" { int _slen; int _trans; @@ -370,13 +370,13 @@ switch ( _deserialize_text_trans_actions[_trans] ) { case 2: -#line 51 "../../src/hb-buffer-deserialize-text.rl" +#line 51 "hb-buffer-deserialize-text.rl" { tok = p; } break; case 5: -#line 55 "../../src/hb-buffer-deserialize-text.rl" +#line 55 "hb-buffer-deserialize-text.rl" { if (!hb_font_glyph_from_string (font, tok, p - tok, @@ -385,41 +385,41 @@ } break; case 10: -#line 62 "../../src/hb-buffer-deserialize-text.rl" +#line 62 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } break; case 3: -#line 63 "../../src/hb-buffer-deserialize-text.rl" +#line 63 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } break; case 12: -#line 64 "../../src/hb-buffer-deserialize-text.rl" +#line 64 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } break; case 7: -#line 65 "../../src/hb-buffer-deserialize-text.rl" +#line 65 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } break; case 1: -#line 38 "../../src/hb-buffer-deserialize-text.rl" +#line 38 "hb-buffer-deserialize-text.rl" { memset (&info, 0, sizeof (info)); memset (&pos , 0, sizeof (pos )); } -#line 51 "../../src/hb-buffer-deserialize-text.rl" +#line 51 "hb-buffer-deserialize-text.rl" { tok = p; } break; case 4: -#line 55 "../../src/hb-buffer-deserialize-text.rl" +#line 55 "hb-buffer-deserialize-text.rl" { if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -429,9 +429,9 @@ } break; case 9: -#line 62 "../../src/hb-buffer-deserialize-text.rl" +#line 62 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -441,9 +441,9 @@ } break; case 11: -#line 64 "../../src/hb-buffer-deserialize-text.rl" +#line 64 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -453,9 +453,9 @@ } break; case 6: -#line 65 "../../src/hb-buffer-deserialize-text.rl" +#line 65 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -465,9 +465,9 @@ } break; case 8: -#line 66 "../../src/hb-buffer-deserialize-text.rl" +#line 66 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -476,7 +476,7 @@ *end_ptr = p; } break; -#line 480 "hb-buffer-deserialize-text.hh.tmp" +#line 480 "hb-buffer-deserialize-text.hh" } _again: @@ -489,14 +489,14 @@ { switch ( _deserialize_text_eof_actions[cs] ) { case 4: -#line 55 "../../src/hb-buffer-deserialize-text.rl" +#line 55 "hb-buffer-deserialize-text.rl" { if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -506,9 +506,9 @@ } break; case 9: -#line 62 "../../src/hb-buffer-deserialize-text.rl" +#line 62 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -518,9 +518,9 @@ } break; case 11: -#line 64 "../../src/hb-buffer-deserialize-text.rl" +#line 64 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -530,9 +530,9 @@ } break; case 6: -#line 65 "../../src/hb-buffer-deserialize-text.rl" +#line 65 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -542,9 +542,9 @@ } break; case 8: -#line 66 "../../src/hb-buffer-deserialize-text.rl" +#line 66 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } -#line 43 "../../src/hb-buffer-deserialize-text.rl" +#line 43 "hb-buffer-deserialize-text.rl" { buffer->add_info (info); if (buffer->in_error) @@ -553,14 +553,14 @@ *end_ptr = p; } break; -#line 557 "hb-buffer-deserialize-text.hh.tmp" +#line 557 "hb-buffer-deserialize-text.hh" } } _out: {} } -#line 119 "../../src/hb-buffer-deserialize-text.rl" +#line 119 "hb-buffer-deserialize-text.rl" *end_ptr = p; diff -uN gfx/harfbuzz/src_old/hb-buffer-deserialize-text.rl gfx/harfbuzz/src/hb-buffer-deserialize-text.rl --- gfx/harfbuzz/src_old/hb-buffer-deserialize-text.rl 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-buffer-deserialize-text.rl 2016-06-05 23:48:24.307324017 +0200 @@ -111,8 +111,8 @@ const char *eof = pe, *tok = NULL; int cs; - hb_glyph_info_t info; - hb_glyph_position_t pos; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; %%{ write init; write exec; diff -uN gfx/harfbuzz/src_old/hb-buffer.h gfx/harfbuzz/src/hb-buffer.h --- gfx/harfbuzz/src_old/hb-buffer.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-buffer.h 2016-06-05 23:48:29.670294025 +0200 @@ -40,7 +40,27 @@ HB_BEGIN_DECLS - +/** + * hb_glyph_info_t: + * @codepoint: either a Unicode code point (before shaping) or a glyph index + * (after shaping). + * @mask: + * @cluster: the index of the character in the original text that corresponds + * to this #hb_glyph_info_t, or whatever the client passes to + * hb_buffer_add(). More than one #hb_glyph_info_t can have the same + * @cluster value, if they resulted from the same character (e.g. one + * to many glyph substitution), and when more than one character gets + * merged in the same glyph (e.g. many to one glyph substitution) the + * #hb_glyph_info_t will have the smallest cluster value of them. + * By default some characters are merged into the same cluster + * (e.g. combining marks have the same cluster as their bases) + * even if they are separate glyphs, hb_buffer_set_cluster_level() + * allow selecting more fine-grained cluster handling. + * + * The #hb_glyph_info_t is the structure that holds information about the + * glyphs and their relation to input text. + * + */ typedef struct hb_glyph_info_t { hb_codepoint_t codepoint; hb_mask_t mask; @@ -51,6 +71,22 @@ hb_var_int_t var2; } hb_glyph_info_t; +/** + * hb_glyph_position_t: + * @x_advance: how much the line advances after drawing this glyph when setting + * text in horizontal direction. + * @y_advance: how much the line advances after drawing this glyph when setting + * text in vertical direction. + * @x_offset: how much the glyph moves on the X-axis before drawing it, this + * should not affect how much the line advances. + * @y_offset: how much the glyph moves on the Y-axis before drawing it, this + * should not affect how much the line advances. + * + * The #hb_glyph_position_t is the structure that holds the positions of the + * glyph in both horizontal and vertical directions. All positions in + * #hb_glyph_position_t are relative to the current point. + * + */ typedef struct hb_glyph_position_t { hb_position_t x_advance; hb_position_t y_advance; @@ -61,7 +97,16 @@ hb_var_int_t var; } hb_glyph_position_t; - +/** + * hb_segment_properties_t: + * @direction: the #hb_direction_t of the buffer, see hb_buffer_set_direction(). + * @script: the #hb_script_t of the buffer, see hb_buffer_set_script(). + * @language: the #hb_language_t of the buffer, see hb_buffer_set_language(). + * + * The structure that holds various text properties of an #hb_buffer_t. Can be + * set and retrieved using hb_buffer_set_segment_properties() and + * hb_buffer_get_segment_properties(), respectively. + */ typedef struct hb_segment_properties_t { hb_direction_t direction; hb_script_t script; @@ -77,100 +122,127 @@ NULL, \ NULL} -hb_bool_t +HB_EXTERN hb_bool_t hb_segment_properties_equal (const hb_segment_properties_t *a, const hb_segment_properties_t *b); -unsigned int +HB_EXTERN unsigned int hb_segment_properties_hash (const hb_segment_properties_t *p); -/* - * hb_buffer_t +/** + * hb_buffer_t: + * + * The main structure holding the input text and its properties before shaping, + * and output glyphs and their information after shaping. */ typedef struct hb_buffer_t hb_buffer_t; -hb_buffer_t * +HB_EXTERN hb_buffer_t * hb_buffer_create (void); -hb_buffer_t * +HB_EXTERN hb_buffer_t * hb_buffer_get_empty (void); -hb_buffer_t * +HB_EXTERN hb_buffer_t * hb_buffer_reference (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_destroy (hb_buffer_t *buffer); -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_set_user_data (hb_buffer_t *buffer, hb_user_data_key_t *key, void * data, hb_destroy_func_t destroy, hb_bool_t replace); -void * +HB_EXTERN void * hb_buffer_get_user_data (hb_buffer_t *buffer, hb_user_data_key_t *key); - +/** + * hb_buffer_content_type_t: + * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer. + * @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping). + * @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping). + */ typedef enum { HB_BUFFER_CONTENT_TYPE_INVALID = 0, HB_BUFFER_CONTENT_TYPE_UNICODE, HB_BUFFER_CONTENT_TYPE_GLYPHS } hb_buffer_content_type_t; -void +HB_EXTERN void hb_buffer_set_content_type (hb_buffer_t *buffer, hb_buffer_content_type_t content_type); -hb_buffer_content_type_t +HB_EXTERN hb_buffer_content_type_t hb_buffer_get_content_type (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, hb_unicode_funcs_t *unicode_funcs); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_buffer_get_unicode_funcs (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_direction (hb_buffer_t *buffer, hb_direction_t direction); -hb_direction_t +HB_EXTERN hb_direction_t hb_buffer_get_direction (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_script (hb_buffer_t *buffer, hb_script_t script); -hb_script_t +HB_EXTERN hb_script_t hb_buffer_get_script (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_language (hb_buffer_t *buffer, hb_language_t language); -hb_language_t +HB_EXTERN hb_language_t hb_buffer_get_language (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_set_segment_properties (hb_buffer_t *buffer, const hb_segment_properties_t *props); -void +HB_EXTERN void hb_buffer_get_segment_properties (hb_buffer_t *buffer, hb_segment_properties_t *props); -void +HB_EXTERN void hb_buffer_guess_segment_properties (hb_buffer_t *buffer); +/** + * hb_buffer_flags_t: + * @HB_BUFFER_FLAG_DEFAULT: the default buffer flag. + * @HB_BUFFER_FLAG_BOT: flag indicating that special handling of the beginning + * of text paragraph can be applied to this buffer. Should usually + * be set, unless you are passing to the buffer only part + * of the text without the full context. + * @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text + * paragraph can be applied to this buffer, similar to + * @HB_BUFFER_FLAG_EOT. + * @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES: + * flag indication that character with Default_Ignorable + * Unicode property should use the corresponding glyph + * from the font, instead of hiding them (currently done + * by replacing them with the space glyph and zeroing the + * advance width.) + * + * Since: 0.9.20 + */ typedef enum { /*< flags >*/ HB_BUFFER_FLAG_DEFAULT = 0x00000000u, HB_BUFFER_FLAG_BOT = 0x00000001u, /* Beginning-of-text */ @@ -178,83 +250,109 @@ HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u } hb_buffer_flags_t; -void +HB_EXTERN void hb_buffer_set_flags (hb_buffer_t *buffer, hb_buffer_flags_t flags); -hb_buffer_flags_t +HB_EXTERN hb_buffer_flags_t hb_buffer_get_flags (hb_buffer_t *buffer); - - +/* + * Since: 0.9.42 + */ +typedef enum { + HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0, + HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1, + HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2, + HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES +} hb_buffer_cluster_level_t; + +HB_EXTERN void +hb_buffer_set_cluster_level (hb_buffer_t *buffer, + hb_buffer_cluster_level_t cluster_level); + +HB_EXTERN hb_buffer_cluster_level_t +hb_buffer_get_cluster_level (hb_buffer_t *buffer); + +/** + * HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT: + * + * The default code point for replacing invalid characters in a given encoding. + * Set to U+FFFD REPLACEMENT CHARACTER. + * + * Since: 0.9.31 + */ #define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu -/* Sets codepoint used to replace invalid UTF-8/16/32 entries. - * Default is 0xFFFDu. */ -void +HB_EXTERN void hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, hb_codepoint_t replacement); -hb_codepoint_t +HB_EXTERN hb_codepoint_t hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer); -/* Resets the buffer. Afterwards it's as if it was just created, - * except that it has a larger buffer allocated perhaps... */ -void +HB_EXTERN void hb_buffer_reset (hb_buffer_t *buffer); -/* Like reset, but does NOT clear unicode_funcs and replacement_codepoint. */ -void +HB_EXTERN void hb_buffer_clear_contents (hb_buffer_t *buffer); -/* Returns false if allocation failed */ -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size); -/* Returns false if allocation has failed before */ -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_allocation_successful (hb_buffer_t *buffer); -void +HB_EXTERN void hb_buffer_reverse (hb_buffer_t *buffer); -void +HB_EXTERN void +hb_buffer_reverse_range (hb_buffer_t *buffer, + unsigned int start, unsigned int end); + +HB_EXTERN void hb_buffer_reverse_clusters (hb_buffer_t *buffer); /* Filling the buffer in */ -void +HB_EXTERN void hb_buffer_add (hb_buffer_t *buffer, hb_codepoint_t codepoint, unsigned int cluster); -void +HB_EXTERN void hb_buffer_add_utf8 (hb_buffer_t *buffer, const char *text, int text_length, unsigned int item_offset, int item_length); -void +HB_EXTERN void hb_buffer_add_utf16 (hb_buffer_t *buffer, const uint16_t *text, int text_length, unsigned int item_offset, int item_length); -void +HB_EXTERN void hb_buffer_add_utf32 (hb_buffer_t *buffer, const uint32_t *text, int text_length, unsigned int item_offset, int item_length); -/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */ -void +HB_EXTERN void +hb_buffer_add_latin1 (hb_buffer_t *buffer, + const uint8_t *text, + int text_length, + unsigned int item_offset, + int item_length); + +HB_EXTERN void hb_buffer_add_codepoints (hb_buffer_t *buffer, const hb_codepoint_t *text, int text_length, @@ -262,32 +360,25 @@ int item_length); -/* Clears any new items added at the end */ -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_set_length (hb_buffer_t *buffer, unsigned int length); -/* Return value valid as long as buffer not modified */ -unsigned int +HB_EXTERN unsigned int hb_buffer_get_length (hb_buffer_t *buffer); /* Getting glyphs out of the buffer */ -/* Return value valid as long as buffer not modified */ -hb_glyph_info_t * +HB_EXTERN hb_glyph_info_t * hb_buffer_get_glyph_infos (hb_buffer_t *buffer, unsigned int *length); -/* Return value valid as long as buffer not modified */ -hb_glyph_position_t * +HB_EXTERN hb_glyph_position_t * hb_buffer_get_glyph_positions (hb_buffer_t *buffer, unsigned int *length); -/* Reorders a glyph buffer to have canonical in-cluster glyph order / position. - * The resulting clusters should behave identical to pre-reordering clusters. - * NOTE: This has nothing to do with Unicode normalization. */ -void +HB_EXTERN void hb_buffer_normalize_glyphs (hb_buffer_t *buffer); @@ -295,50 +386,87 @@ * Serialize */ +/** + * hb_buffer_serialize_flags_t: + * @HB_BUFFER_SERIALIZE_FLAG_DEFAULT: serialize glyph names, clusters and positions. + * @HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS: do not serialize glyph cluster. + * @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information. + * @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name. + * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents. + * + * Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs(). + * + * Since: 0.9.20 + */ typedef enum { /*< flags >*/ HB_BUFFER_SERIALIZE_FLAG_DEFAULT = 0x00000000u, HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u, HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u, - HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u + HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u, + HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u } hb_buffer_serialize_flags_t; +/** + * hb_buffer_serialize_format_t: + * @HB_BUFFER_SERIALIZE_FORMAT_TEXT: a human-readable, plain text format. + * @HB_BUFFER_SERIALIZE_FORMAT_JSON: a machine-readable JSON format. + * @HB_BUFFER_SERIALIZE_FORMAT_INVALID: invalid format. + * + * The buffer serialization and de-serialization format used in + * hb_buffer_serialize_glyphs() and hb_buffer_deserialize_glyphs(). + * + * Since: 0.9.2 + */ typedef enum { HB_BUFFER_SERIALIZE_FORMAT_TEXT = HB_TAG('T','E','X','T'), HB_BUFFER_SERIALIZE_FORMAT_JSON = HB_TAG('J','S','O','N'), HB_BUFFER_SERIALIZE_FORMAT_INVALID = HB_TAG_NONE } hb_buffer_serialize_format_t; -/* len=-1 means str is NUL-terminated. */ -hb_buffer_serialize_format_t +HB_EXTERN hb_buffer_serialize_format_t hb_buffer_serialize_format_from_string (const char *str, int len); -const char * +HB_EXTERN const char * hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format); -const char ** +HB_EXTERN const char ** hb_buffer_serialize_list_formats (void); -/* Returns number of items, starting at start, that were serialized. */ -unsigned int +HB_EXTERN unsigned int hb_buffer_serialize_glyphs (hb_buffer_t *buffer, unsigned int start, unsigned int end, char *buf, unsigned int buf_size, - unsigned int *buf_consumed, /* May be NULL */ - hb_font_t *font, /* May be NULL */ + unsigned int *buf_consumed, + hb_font_t *font, hb_buffer_serialize_format_t format, hb_buffer_serialize_flags_t flags); -hb_bool_t +HB_EXTERN hb_bool_t hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, const char *buf, - int buf_len, /* -1 means nul-terminated */ - const char **end_ptr, /* May be NULL */ - hb_font_t *font, /* May be NULL */ + int buf_len, + const char **end_ptr, + hb_font_t *font, hb_buffer_serialize_format_t format); +/* + * Debugging. + */ + +typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer, + hb_font_t *font, + const char *message, + void *user_data); + +HB_EXTERN void +hb_buffer_set_message_func (hb_buffer_t *buffer, + hb_buffer_message_func_t func, + void *user_data, hb_destroy_func_t destroy); + + HB_END_DECLS #endif /* HB_BUFFER_H */ diff -uN gfx/harfbuzz/src_old/hb-buffer-private.hh gfx/harfbuzz/src/hb-buffer-private.hh --- gfx/harfbuzz/src_old/hb-buffer-private.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-buffer-private.hh 2016-06-05 23:48:25.604316742 +0200 @@ -35,9 +35,37 @@ #include "hb-unicode-private.hh" +#ifndef HB_BUFFER_MAX_EXPANSION_FACTOR +#define HB_BUFFER_MAX_EXPANSION_FACTOR 32 +#endif +#ifndef HB_BUFFER_MAX_LEN_MIN +#define HB_BUFFER_MAX_LEN_MIN 8192 +#endif +#ifndef HB_BUFFER_MAX_LEN_DEFAULT +#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */ +#endif + ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20); ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)); +HB_MARK_AS_FLAG_T (hb_buffer_flags_t); +HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t); + +enum hb_buffer_scratch_flags_t { + HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u, + HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII = 0x00000001u, + HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, + HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, + HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_CURSIVE = 0x00000008u, + HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000010u, + /* Reserved for complex shapers' internal use. */ + HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u, + HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u, + HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u, + HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u, +}; +HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t); + /* * hb_buffer_t @@ -50,7 +78,10 @@ /* Information about how the text in the buffer should be treated */ hb_unicode_funcs_t *unicode; /* Unicode functions */ hb_buffer_flags_t flags; /* BOT / EOT / etc. */ + hb_buffer_cluster_level_t cluster_level; hb_codepoint_t replacement; /* U+FFFD or something else. */ + hb_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */ + unsigned int max_len; /* Maximum allowed len. */ /* Buffer contents */ hb_buffer_content_type_t content_type; @@ -75,8 +106,8 @@ inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; } inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; } - inline hb_glyph_info_t &prev (void) { return out_info[out_len - 1]; } - inline hb_glyph_info_t prev (void) const { return info[out_len - 1]; } + inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; } + inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; } inline bool has_separate_output (void) const { return info != out_info; } @@ -93,6 +124,11 @@ hb_codepoint_t context[2][CONTEXT_LENGTH]; unsigned int context_len[2]; + /* Debugging */ + hb_buffer_message_func_t message_func; + void *message_data; + hb_destroy_func_t message_destroy; + /* Methods */ @@ -171,9 +207,18 @@ unsigned int cluster_end); HB_INTERNAL void merge_clusters (unsigned int start, - unsigned int end); + unsigned int end) + { + if (end - start < 2) + return; + merge_clusters_impl (start, end); + } + HB_INTERNAL void merge_clusters_impl (unsigned int start, + unsigned int end); HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end); + /* Merge clusters for deleting current glyph, and skip it. */ + HB_INTERNAL void delete_glyph (void); /* Internal methods */ HB_INTERNAL bool enlarge (unsigned int size); @@ -191,6 +236,21 @@ HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size); inline void clear_context (unsigned int side) { context_len[side] = 0; } + + HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *)); + + inline bool messaging (void) { return unlikely (message_func); } + inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4) + { + if (!messaging ()) + return true; + va_list ap; + va_start (ap, fmt); + bool ret = message_impl (font, fmt, ap); + va_end (ap); + return ret; + } + HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0); }; diff -uN gfx/harfbuzz/src_old/hb-buffer-serialize.cc gfx/harfbuzz/src/hb-buffer-serialize.cc --- gfx/harfbuzz/src_old/hb-buffer-serialize.cc 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-buffer-serialize.cc 2016-06-05 23:48:26.782310166 +0200 @@ -36,11 +36,12 @@ /** * hb_buffer_serialize_list_formats: * - * + * Returns a list of supported buffer serialization formats. * * Return value: (transfer none): + * A string array of buffer serialization formats. Should not be freed. * - * Since: 1.0 + * Since: 0.9.7 **/ const char ** hb_buffer_serialize_list_formats (void) @@ -50,14 +51,17 @@ /** * hb_buffer_serialize_format_from_string: - * @str: - * @len: + * @str: (array length=len) (element-type uint8_t): a string to parse + * @len: length of @str, or -1 if string is %NULL terminated * - * + * Parses a string into an #hb_buffer_serialize_format_t. Does not check if + * @str is a valid buffer serialization format, use + * hb_buffer_serialize_list_formats() to get the list of supported formats. * * Return value: + * The parsed #hb_buffer_serialize_format_t. * - * Since: 1.0 + * Since: 0.9.7 **/ hb_buffer_serialize_format_t hb_buffer_serialize_format_from_string (const char *str, int len) @@ -68,13 +72,15 @@ /** * hb_buffer_serialize_format_to_string: - * @format: + * @format: an #hb_buffer_serialize_format_t to convert. * - * + * Converts @format to the string corresponding it, or %NULL if it is not a valid + * #hb_buffer_serialize_format_t. * - * Return value: + * Return value: (transfer none): + * A %NULL terminated string corresponding to @format. Should not be freed. * - * Since: 1.0 + * Since: 0.9.7 **/ const char * hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) @@ -99,7 +105,8 @@ hb_buffer_serialize_flags_t flags) { hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); - hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); + hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? + NULL : hb_buffer_get_glyph_positions (buffer, NULL); *buf_consumed = 0; for (unsigned int i = start; i < end; i++) @@ -144,6 +151,16 @@ pos[i].x_advance, pos[i].y_advance); } + if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) + { + hb_glyph_extents_t extents; + hb_font_get_glyph_extents(font, info[i].codepoint, &extents); + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", + extents.x_bearing, extents.y_bearing)); + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", + extents.width, extents.height)); + } + *p++ = '}'; unsigned int l = p - b; @@ -172,7 +189,8 @@ hb_buffer_serialize_flags_t flags) { hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); - hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); + hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? + NULL : hb_buffer_get_glyph_positions (buffer, NULL); *buf_consumed = 0; for (unsigned int i = start; i < end; i++) @@ -208,6 +226,13 @@ p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); } + if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) + { + hb_glyph_extents_t extents; + hb_font_get_glyph_extents(font, info[i].codepoint, &extents); + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)); + } + unsigned int l = p - b; if (buf_size > l) { @@ -223,24 +248,51 @@ return end - start; } -/* Returns number of items, starting at start, that were serialized. */ /** * hb_buffer_serialize_glyphs: - * @buffer: a buffer. - * @start: - * @end: - * @buf: (array length=buf_size): - * @buf_size: - * @buf_consumed: (out): - * @font: - * @format: - * @flags: + * @buffer: an #hb_buffer_t buffer. + * @start: the first item in @buffer to serialize. + * @end: the last item in @buffer to serialize. + * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to + * write serialized buffer into. + * @buf_size: the size of @buf. + * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. + * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to + * read glyph names and extents. If %NULL, and empty font will be used. + * @format: the #hb_buffer_serialize_format_t to use for formatting the output. + * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties + * to serialize. + * + * Serializes @buffer into a textual representation of its glyph content, + * useful for showing the contents of the buffer, for example during debugging. + * There are currently two supported serialization formats: + * + * ## text + * A human-readable, plain text format. + * The serialized glyphs will look something like: + * + * ``` + * [uni0651=0@518,0+0|uni0628=0+1897] + * ``` + * - The serialized glyphs are delimited with `[` and `]`. + * - Glyphs are separated with `|` + * - Each glyph starts with glyph name, or glyph index if + * #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then, + * - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster. + * - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format: + * - If both #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not 0, `@x_offset,y_offset`. Then, + * - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then, + * - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the + * #hb_glyph_extents_t in the format + * `<x_bearing,y_bearing,width,height>` * - * + * ## json + * TODO. * * Return value: + * The number of serialized items. * - * Since: 1.0 + * Since: 0.9.7 **/ unsigned int hb_buffer_serialize_glyphs (hb_buffer_t *buffer, @@ -248,8 +300,8 @@ unsigned int end, char *buf, unsigned int buf_size, - unsigned int *buf_consumed, /* May be NULL */ - hb_font_t *font, /* May be NULL */ + unsigned int *buf_consumed, + hb_font_t *font, hb_buffer_serialize_format_t format, hb_buffer_serialize_flags_t flags) { @@ -263,6 +315,9 @@ assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + if (!buffer->have_positions) + flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS; + if (unlikely (start == end)) return 0; @@ -336,7 +391,7 @@ /** * hb_buffer_deserialize_glyphs: - * @buffer: a buffer. + * @buffer: an #hb_buffer_t buffer. * @buf: (array length=buf_len): * @buf_len: * @end_ptr: (out): @@ -347,7 +402,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.7 **/ hb_bool_t hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, diff -uN gfx/harfbuzz/src_old/hb-common.cc gfx/harfbuzz/src/hb-common.cc --- gfx/harfbuzz/src_old/hb-common.cc 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-common.cc 2016-06-05 23:48:32.151280204 +0200 @@ -57,14 +57,14 @@ /** * hb_tag_from_string: - * @str: (array length=len): + * @str: (array length=len) (element-type uint8_t): * @len: * * * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_tag_t hb_tag_from_string (const char *str, int len) @@ -92,7 +92,7 @@ * * * - * Since: 1.0 + * Since: 0.9.5 **/ void hb_tag_to_string (hb_tag_t tag, char *buf) @@ -115,14 +115,14 @@ /** * hb_direction_from_string: - * @str: (array length=len): + * @str: (array length=len) (element-type uint8_t): * @len: * * * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_direction_t hb_direction_from_string (const char *str, int len) @@ -149,7 +149,7 @@ * * Return value: (transfer none): * - * Since: 1.0 + * Since: 0.9.2 **/ const char * hb_direction_to_string (hb_direction_t direction) @@ -179,7 +179,7 @@ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0 }; -static hb_bool_t +static bool lang_equal (hb_language_t v1, const void *v2) { @@ -235,7 +235,7 @@ static hb_language_item_t *langs; #ifdef HB_USE_ATEXIT -static inline +static void free_langs (void) { while (langs) { @@ -265,6 +265,7 @@ *lang = key; if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) { + lang->finish (); free (lang); goto retry; } @@ -280,46 +281,51 @@ /** * hb_language_from_string: - * @str: (array length=len): - * @len: + * @str: (array length=len) (element-type uint8_t): a string representing + * ISO 639 language code + * @len: length of the @str, or -1 if it is %NULL-terminated. * - * + * Converts @str representing an ISO 639 language code to the corresponding + * #hb_language_t. * - * Return value: + * Return value: (transfer none): + * The #hb_language_t corresponding to the ISO 639 language code. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_language_t hb_language_from_string (const char *str, int len) { - char strbuf[64]; - if (!str || !len || !*str) return HB_LANGUAGE_INVALID; + hb_language_item_t *item = NULL; if (len >= 0) { /* NUL-terminate it. */ + char strbuf[64]; len = MIN (len, (int) sizeof (strbuf) - 1); memcpy (strbuf, str, len); strbuf[len] = '\0'; - str = strbuf; + item = lang_find_or_insert (strbuf); } - - hb_language_item_t *item = lang_find_or_insert (str); + else + item = lang_find_or_insert (str); return likely (item) ? item->lang : HB_LANGUAGE_INVALID; } /** * hb_language_to_string: - * @language: + * @language: an #hb_language_t to convert. * - * + * See hb_language_from_string(). * - * Return value: (transfer none): + * Return value: (transfer none): + * A %NULL-terminated string representing the @language. Must not be freed by + * the caller. * - * Since: 1.0 + * Since: 0.9.2 **/ const char * hb_language_to_string (hb_language_t language) @@ -333,9 +339,9 @@ * * * - * Return value: + * Return value: (transfer none): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_language_t hb_language_get_default (void) @@ -345,7 +351,7 @@ hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language); if (unlikely (language == HB_LANGUAGE_INVALID)) { language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1); - hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language); + (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language); } return default_language; @@ -356,13 +362,14 @@ /** * hb_script_from_iso15924_tag: - * @tag: + * @tag: an #hb_tag_t representing an ISO 15924 tag. * - * + * Converts an ISO 15924 script tag to a corresponding #hb_script_t. * * Return value: + * An #hb_script_t corresponding to the ISO 15924 tag. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_script_t hb_script_from_iso15924_tag (hb_tag_t tag) @@ -400,30 +407,35 @@ /** * hb_script_from_string: - * @s: (array length=len): - * @len: - * - * + * @str: (array length=len) (element-type uint8_t): a string representing an + * ISO 15924 tag. + * @len: length of the @str, or -1 if it is %NULL-terminated. + * + * Converts a string @str representing an ISO 15924 script tag to a + * corresponding #hb_script_t. Shorthand for hb_tag_from_string() then + * hb_script_from_iso15924_tag(). * * Return value: + * An #hb_script_t corresponding to the ISO 15924 tag. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_script_t -hb_script_from_string (const char *s, int len) +hb_script_from_string (const char *str, int len) { - return hb_script_from_iso15924_tag (hb_tag_from_string (s, len)); + return hb_script_from_iso15924_tag (hb_tag_from_string (str, len)); } /** * hb_script_to_iso15924_tag: - * @script: + * @script: an #hb_script_ to convert. * - * + * See hb_script_from_iso15924_tag(). * - * Return value: + * Return value: + * An #hb_tag_t representing an ISO 15924 script tag. * - * Since: 1.0 + * Since: 0.9.2 **/ hb_tag_t hb_script_to_iso15924_tag (hb_script_t script) @@ -439,7 +451,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_direction_t hb_script_get_horizontal_direction (hb_script_t script) @@ -492,6 +504,9 @@ case HB_SCRIPT_PALMYRENE: case HB_SCRIPT_PSALTER_PAHLAVI: + /* Unicode-8.0 additions */ + case HB_SCRIPT_OLD_HUNGARIAN: + return HB_DIRECTION_RTL; } @@ -517,7 +532,7 @@ } } hb_user_data_item_t item = {key, data, destroy}; - bool ret = !!items.replace_or_insert (item, lock, replace); + bool ret = !!items.replace_or_insert (item, lock, (bool) replace); return ret; } @@ -541,7 +556,7 @@ * * Returns library version as three integer components. * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_version (unsigned int *major, @@ -560,7 +575,7 @@ * * Return value: library version string. * - * Since: 1.0 + * Since: 0.9.2 **/ const char * hb_version_string (void) @@ -578,7 +593,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.30 **/ hb_bool_t hb_version_atleast (unsigned int major, diff -uN gfx/harfbuzz/src_old/hb-common.h gfx/harfbuzz/src/hb-common.h --- gfx/harfbuzz/src_old/hb-common.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-common.h 2016-06-05 23:48:33.399273253 +0200 @@ -98,16 +98,22 @@ #define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff) /* len=-1 means str is NUL-terminated. */ -hb_tag_t +HB_EXTERN hb_tag_t hb_tag_from_string (const char *str, int len); /* buf should have 4 bytes. */ -void +HB_EXTERN void hb_tag_to_string (hb_tag_t tag, char *buf); -/* hb_direction_t */ - +/** + * hb_direction_t: + * @HB_DIRECTION_INVALID: Initial, unset direction. + * @HB_DIRECTION_LTR: Text is set horizontally from left to right. + * @HB_DIRECTION_RTL: Text is set horizontally from right to left. + * @HB_DIRECTION_TTB: Text is set vertically from top to bottom. + * @HB_DIRECTION_BTT: Text is set vertically from bottom to top. + */ typedef enum { HB_DIRECTION_INVALID = 0, HB_DIRECTION_LTR = 4, @@ -117,10 +123,10 @@ } hb_direction_t; /* len=-1 means str is NUL-terminated */ -hb_direction_t +HB_EXTERN hb_direction_t hb_direction_from_string (const char *str, int len); -const char * +HB_EXTERN const char * hb_direction_to_string (hb_direction_t direction); #define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4) @@ -136,16 +142,15 @@ typedef const struct hb_language_impl_t *hb_language_t; -/* len=-1 means str is NUL-terminated */ -hb_language_t +HB_EXTERN hb_language_t hb_language_from_string (const char *str, int len); -const char * +HB_EXTERN const char * hb_language_to_string (hb_language_t language); #define HB_LANGUAGE_INVALID ((hb_language_t) NULL) -hb_language_t +HB_EXTERN hb_language_t hb_language_get_default (void); @@ -272,6 +277,9 @@ /*6.1*/ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), + /* + * Since: 0.9.30 + */ /*7.0*/ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), @@ -296,6 +304,13 @@ /*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), + /*8.0*/ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), + /*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), + /*8.0*/ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), + /*8.0*/ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), + /*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), + /*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), + /* No script set. */ HB_SCRIPT_INVALID = HB_TAG_NONE, @@ -314,18 +329,16 @@ /* Script functions */ -hb_script_t +HB_EXTERN hb_script_t hb_script_from_iso15924_tag (hb_tag_t tag); -/* sugar for tag_from_string() then script_from_iso15924_tag */ -/* len=-1 means s is NUL-terminated */ -hb_script_t -hb_script_from_string (const char *s, int len); +HB_EXTERN hb_script_t +hb_script_from_string (const char *str, int len); -hb_tag_t +HB_EXTERN hb_tag_t hb_script_to_iso15924_tag (hb_script_t script); -hb_direction_t +HB_EXTERN hb_direction_t hb_script_get_horizontal_direction (hb_script_t script); diff -uN gfx/harfbuzz/src_old/hb-coretext.cc gfx/harfbuzz/src/hb-coretext.cc --- gfx/harfbuzz/src_old/hb-coretext.cc 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-coretext.cc 2016-06-05 23:48:34.938264688 +0200 @@ -22,7 +22,7 @@ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * GNU Author(s): Jonathan Kew + * Mozilla Author(s): Jonathan Kew * Google Author(s): Behdad Esfahbod */ @@ -125,6 +125,9 @@ CFRelease (data); } +/* + * Since: 0.9.10 + */ CGFontRef hb_coretext_face_get_cg_font (hb_face_t *face) { @@ -140,6 +143,7 @@ struct hb_coretext_shaper_font_data_t { CTFontRef ct_font; + CGFloat x_mult, y_mult; /* From CT space to HB space. */ }; hb_coretext_shaper_font_data_t * @@ -154,7 +158,55 @@ hb_face_t *face = font->face; hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - data->ct_font = CTFontCreateWithGraphicsFont (face_data, font->y_scale, NULL, NULL); + /* Choose a CoreText font size and calculate multipliers to convert to HarfBuzz space. */ + /* TODO: use upem instead of 36? */ + CGFloat font_size = 36.; /* Default... */ + /* No idea if the following is even a good idea. */ + if (font->y_ppem) + font_size = font->y_ppem; + + if (font_size < 0) + font_size = -font_size; + data->x_mult = (CGFloat) font->x_scale / font_size; + data->y_mult = (CGFloat) font->y_scale / font_size; + data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL); + if (unlikely (!data->ct_font)) { + DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); + free (data); + return NULL; + } + + /* Create font copy with cascade list that has LastResort first; this speeds up CoreText + * font fallback which we don't need anyway. */ + { + // TODO Handle allocation failures? + CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0); + CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault, + (const void **) &last_resort, + 1, + &kCFTypeArrayCallBacks); + CFRelease (last_resort); + CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault, + (const void **) &kCTFontCascadeListAttribute, + (const void **) &cascade_list, + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease (cascade_list); + + CTFontDescriptorRef new_font_desc = CTFontDescriptorCreateWithAttributes (attributes); + CFRelease (attributes); + + CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (data->ct_font, 0.0, NULL, new_font_desc); + if (new_ct_font) + { + CFRelease (data->ct_font); + data->ct_font = new_ct_font; + } + else + DEBUG_MSG (CORETEXT, font, "Font copy with empty cascade list failed"); + } + if (unlikely (!data->ct_font)) { DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); free (data); @@ -678,7 +730,6 @@ scratch += old_scratch_used; scratch_size -= old_scratch_used; } -retry: { string_ref = CFStringCreateWithCharactersNoCopy (NULL, pchars, chars_len, @@ -776,6 +827,18 @@ buffer->len = 0; uint32_t status_and = ~0, status_or = 0; + double advances_so_far = 0; + /* For right-to-left runs, CoreText returns the glyphs positioned such that + * any trailing whitespace is to the left of (0,0). Adjust coordinate system + * to fix for that. Test with any RTL string with trailing spaces. + * https://code.google.com/p/chromium/issues/detail?id=469028 + */ + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + { + advances_so_far -= CTLineGetTrailingWhitespaceWidth (line); + if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) + advances_so_far = -advances_so_far; + } const CFRange range_all = CFRangeMake (0, 0); @@ -786,6 +849,10 @@ status_or |= run_status; status_and &= run_status; DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status); + double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); + if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) + run_advance = -run_advance; + DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); /* CoreText does automatic font fallback (AKA "cascading") for characters * not supported by the requested font, and provides no way to turn it off, @@ -817,11 +884,9 @@ * However, even that wouldn't work if we were passed in the CGFont to * begin with. * - * Webkit uses a slightly different approach: it installs LastResort - * as fallback chain, and then checks PS name of used font against - * LastResort. That one is safe for any font except for LastResort, - * as opposed to ours, which can fail if we are using any uninstalled - * font that has the same name as an installed font. + * We might switch to checking PS name against "LastResort". That would + * be safe for all fonts except for those named "Last Resort". Might be + * better than what we have right now. * * See: http://github.com/behdad/harfbuzz/pull/36 */ @@ -860,8 +925,14 @@ goto resize_and_retry; hb_glyph_info_t *info = buffer->info + buffer->len; - CGGlyph notdef = 0; - double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1); + hb_codepoint_t notdef = 0; + hb_direction_t dir = buffer->props.direction; + hb_position_t x_advance, y_advance, x_offset, y_offset; + hb_font_get_glyph_advance_for_direction (font, notdef, dir, &x_advance, &y_advance); + hb_font_get_glyph_origin_for_direction (font, notdef, dir, &x_offset, &y_offset); + hb_position_t advance = x_advance + y_advance; + x_offset = -x_offset; + y_offset = -y_offset; unsigned int old_len = buffer->len; for (CFIndex j = range.location; j < range.location + range.length; j++) @@ -875,19 +946,22 @@ * for this one. */ continue; } + if (buffer->unicode->is_default_ignorable (ch)) + continue; info->codepoint = notdef; info->cluster = log_clusters[j]; info->mask = advance; - info->var1.u32 = 0; - info->var2.u32 = 0; + info->var1.i32 = x_offset; + info->var2.i32 = y_offset; info++; buffer->len++; } if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) buffer->reverse_range (old_len, buffer->len); + advances_so_far += run_advance; continue; } } @@ -917,7 +991,7 @@ scratch_size = scratch_size_saved; \ scratch = scratch_saved; - { + { /* Setup glyphs */ SCRATCH_SAVE(); const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL; if (!glyphs) { @@ -941,6 +1015,11 @@ SCRATCH_RESTORE(); } { + /* Setup positions. + * Note that CoreText does not return advances for glyphs. As such, + * for all but last glyph, we use the delta position to next glyph as + * advance (in the advance direction only), and for last glyph we set + * whatever is needed to make the whole run's advance add up. */ SCRATCH_SAVE(); const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL; if (!positions) { @@ -948,33 +1027,42 @@ CTRunGetPositions (run, range_all, position_buf); positions = position_buf; } - double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); - DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); hb_glyph_info_t *info = run_info; + CGFloat x_mult = font_data->x_mult, y_mult = font_data->y_mult; if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) { + hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult; for (unsigned int j = 0; j < num_glyphs; j++) { - double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_advance) - positions[j].x; - info->mask = advance; - info->var1.u32 = positions[0].x; /* Yes, zero. */ - info->var2.u32 = positions[j].y; + double advance; + if (likely (j + 1 < num_glyphs)) + advance = positions[j + 1].x - positions[j].x; + else /* last glyph */ + advance = run_advance - (positions[j].x - positions[0].x); + info->mask = advance * x_mult; + info->var1.i32 = x_offset; + info->var2.i32 = positions[j].y * y_mult; info++; } } else { - run_advance = -run_advance; + hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult; for (unsigned int j = 0; j < num_glyphs; j++) { - double advance = (j + 1 < num_glyphs ? positions[j + 1].y : positions[0].y + run_advance) - positions[j].y; - info->mask = advance; - info->var1.u32 = positions[j].x; - info->var2.u32 = positions[0].y; /* Yes, zero. */ + double advance; + if (likely (j + 1 < num_glyphs)) + advance = positions[j + 1].y - positions[j].y; + else /* last glyph */ + advance = run_advance - (positions[j].y - positions[0].y); + info->mask = advance * y_mult; + info->var1.i32 = positions[j].x * x_mult; + info->var2.i32 = y_offset; info++; } } SCRATCH_RESTORE(); + advances_so_far += run_advance; } #undef SCRATCH_RESTORE #undef SCRATCH_SAVE @@ -984,10 +1072,20 @@ buffer->len += num_glyphs; } - /* Make sure all runs had the expected direction. */ - bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); - assert (bool (status_and & kCTRunStatusRightToLeft) == backward); - assert (bool (status_or & kCTRunStatusRightToLeft) == backward); + /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel, + * or if it does, it doesn't resepct it. So we get runs with wrong + * directions. As such, disable the assert... It wouldn't crash, but + * cursoring will be off... + * + * http://crbug.com/419769 + */ + if (0) + { + /* Make sure all runs had the expected direction. */ + bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); + assert (bool (status_and & kCTRunStatusRightToLeft) == backward); + assert (bool (status_or & kCTRunStatusRightToLeft) == backward); + } buffer->clear_positions (); @@ -998,16 +1096,16 @@ for (unsigned int i = 0; i < count; i++) { pos->x_advance = info->mask; - pos->x_offset = info->var1.u32; - pos->y_offset = info->var2.u32; + pos->x_offset = info->var1.i32; + pos->y_offset = info->var2.i32; info++, pos++; } else for (unsigned int i = 0; i < count; i++) { pos->y_advance = info->mask; - pos->x_offset = info->var1.u32; - pos->y_offset = info->var2.u32; + pos->x_offset = info->var1.i32; + pos->y_offset = info->var2.i32; info++, pos++; } @@ -1065,10 +1163,6 @@ * AAT shaper */ -HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face) -HB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font) - - /* * shaper face data */ diff -uN gfx/harfbuzz/src_old/hb-coretext.h gfx/harfbuzz/src/hb-coretext.h --- gfx/harfbuzz/src_old/hb-coretext.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-coretext.h 2016-06-05 23:48:36.098258246 +0200 @@ -21,7 +21,7 @@ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * GNU Author(s): Jonathan Kew + * Mozilla Author(s): Jonathan Kew */ #ifndef HB_CORETEXT_H @@ -44,14 +44,14 @@ #define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x') -hb_face_t * +HB_EXTERN hb_face_t * hb_coretext_face_create (CGFontRef cg_font); -CGFontRef +HB_EXTERN CGFontRef hb_coretext_face_get_cg_font (hb_face_t *face); -CTFontRef +HB_EXTERN CTFontRef hb_coretext_font_get_ct_font (hb_font_t *font); diff -uN gfx/harfbuzz/src_old/hb-directwrite.cc gfx/harfbuzz/src/hb-directwrite.cc --- gfx/harfbuzz/src_old/hb-directwrite.cc 1970-01-01 01:00:00.000000000 +0100 +++ gfx/harfbuzz/src/hb-directwrite.cc 2016-06-05 23:48:38.757243479 +0200 @@ -0,0 +1,827 @@ +/* + * Copyright © 2015 Ebrahim Byagowi + * + * 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. + */ + +#define HB_SHAPER directwrite +#include "hb-shaper-impl-private.hh" + +#include + +#include "hb-directwrite.h" + +#include "hb-open-file-private.hh" +#include "hb-ot-name-table.hh" +#include "hb-ot-tag.h" + + +#ifndef HB_DEBUG_DIRECTWRITE +#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0) +#endif + +HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face) +HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font) + +/* +* shaper face data +*/ + +struct hb_directwrite_shaper_face_data_t { + HANDLE fh; + wchar_t face_name[LF_FACESIZE]; +}; + +/* face_name should point to a wchar_t[LF_FACESIZE] object. */ +static void +_hb_generate_unique_face_name(wchar_t *face_name, unsigned int *plen) +{ + /* We'll create a private name for the font from a UUID using a simple, + * somewhat base64-like encoding scheme */ + const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"; + UUID id; + UuidCreate ((UUID*)&id); + ASSERT_STATIC (2 + 3 * (16 / 2) < LF_FACESIZE); + unsigned int name_str_len = 0; + face_name[name_str_len++] = 'F'; + face_name[name_str_len++] = '_'; + unsigned char *p = (unsigned char *)&id; + for (unsigned int i = 0; i < 16; i += 2) + { + /* Spread the 16 bits from two bytes of the UUID across three chars of face_name, + * using the bits in groups of 5,5,6 to select chars from enc. + * This will generate 24 characters; with the 'F_' prefix we already provided, + * the name will be 26 chars (plus the NUL terminator), so will always fit within + * face_name (LF_FACESIZE = 32). */ + face_name[name_str_len++] = enc[p[i] >> 3]; + face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f]; + face_name[name_str_len++] = enc[p[i + 1] & 0x3f]; + } + face_name[name_str_len] = 0; + if (plen) + *plen = name_str_len; +} + +/* Destroys blob. */ +static hb_blob_t * +_hb_rename_font(hb_blob_t *blob, wchar_t *new_name) +{ + /* Create a copy of the font data, with the 'name' table replaced by a + * table that names the font with our private F_* name created above. + * For simplicity, we just append a new 'name' table and update the + * sfnt directory; the original table is left in place, but unused. + * + * The new table will contain just 5 name IDs: family, style, unique, + * full, PS. All of them point to the same name data with our unique name. + */ + + blob = OT::Sanitizer::sanitize (blob); + + unsigned int length, new_length, name_str_len; + const char *orig_sfnt_data = hb_blob_get_data (blob, &length); + + _hb_generate_unique_face_name (new_name, &name_str_len); + + static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 }; + + unsigned int name_table_length = OT::name::min_size + + ARRAY_LENGTH(name_IDs) * OT::NameRecord::static_size + + name_str_len * 2; /* for name data in UTF16BE form */ + unsigned int name_table_offset = (length + 3) & ~3; + + new_length = name_table_offset + ((name_table_length + 3) & ~3); + void *new_sfnt_data = calloc(1, new_length); + if (!new_sfnt_data) + { + hb_blob_destroy (blob); + return NULL; + } + + memcpy(new_sfnt_data, orig_sfnt_data, length); + + OT::name &name = OT::StructAtOffset (new_sfnt_data, name_table_offset); + name.format.set (0); + name.count.set (ARRAY_LENGTH (name_IDs)); + name.stringOffset.set (name.get_size()); + for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++) + { + OT::NameRecord &record = name.nameRecord[i]; + record.platformID.set(3); + record.encodingID.set(1); + record.languageID.set(0x0409u); /* English */ + record.nameID.set(name_IDs[i]); + record.length.set(name_str_len * 2); + record.offset.set(0); + } + + /* Copy string data from new_name, converting wchar_t to UTF16BE. */ + unsigned char *p = &OT::StructAfter(name); + for (unsigned int i = 0; i < name_str_len; i++) + { + *p++ = new_name[i] >> 8; + *p++ = new_name[i] & 0xff; + } + + /* Adjust name table entry to point to new name table */ + const OT::OpenTypeFontFile &file = *(OT::OpenTypeFontFile *) (new_sfnt_data); + unsigned int face_count = file.get_face_count (); + for (unsigned int face_index = 0; face_index < face_count; face_index++) + { + /* Note: doing multiple edits (ie. TTC) can be unsafe. There may be + * toe-stepping. But we don't really care. */ + const OT::OpenTypeFontFace &face = file.get_face (face_index); + unsigned int index; + if (face.find_table_index (HB_OT_TAG_name, &index)) + { + OT::TableRecord &record = const_cast (face.get_table (index)); + record.checkSum.set_for_data (&name, name_table_length); + record.offset.set (name_table_offset); + record.length.set (name_table_length); + } + else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */ + { + free (new_sfnt_data); + hb_blob_destroy (blob); + return NULL; + } + } + + /* The checkSumAdjustment field in the 'head' table is now wrong, + * but that doesn't actually seem to cause any problems so we don't + * bother. */ + + hb_blob_destroy (blob); + return hb_blob_create ((const char *)new_sfnt_data, new_length, + HB_MEMORY_MODE_WRITABLE, NULL, free); +} + +hb_directwrite_shaper_face_data_t * +_hb_directwrite_shaper_face_data_create(hb_face_t *face) +{ + hb_directwrite_shaper_face_data_t *data = (hb_directwrite_shaper_face_data_t *)calloc(1, sizeof (hb_directwrite_shaper_face_data_t)); + if (unlikely (!data)) + return NULL; + + hb_blob_t *blob = hb_face_reference_blob (face); + if (unlikely (!hb_blob_get_length (blob))) + DEBUG_MSG(DIRECTWRITE, face, "Face has empty blob"); + + blob = _hb_rename_font (blob, data->face_name); + if (unlikely (!blob)) + { + free(data); + return NULL; + } + + DWORD num_fonts_installed; + data->fh = AddFontMemResourceEx ((void *)hb_blob_get_data(blob, NULL), + hb_blob_get_length (blob), + 0, &num_fonts_installed); + if (unlikely (!data->fh)) + { + DEBUG_MSG (DIRECTWRITE, face, "Face AddFontMemResourceEx() failed"); + free (data); + return NULL; + } + + return data; +} + +void +_hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data) +{ + RemoveFontMemResourceEx(data->fh); + free(data); +} + + +/* + * shaper font data + */ + +struct hb_directwrite_shaper_font_data_t { + HDC hdc; + LOGFONTW log_font; + HFONT hfont; +}; + +static bool +populate_log_font (LOGFONTW *lf, + hb_font_t *font) +{ + memset (lf, 0, sizeof (*lf)); + lf->lfHeight = -font->y_scale; + lf->lfCharSet = DEFAULT_CHARSET; + + hb_face_t *face = font->face; + hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); + + memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName)); + + return true; +} + +hb_directwrite_shaper_font_data_t * +_hb_directwrite_shaper_font_data_create (hb_font_t *font) +{ + if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return NULL; + + hb_directwrite_shaper_font_data_t *data = (hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t)); + if (unlikely (!data)) + return NULL; + + data->hdc = GetDC (NULL); + + if (unlikely (!populate_log_font (&data->log_font, font))) { + DEBUG_MSG (DIRECTWRITE, font, "Font populate_log_font() failed"); + _hb_directwrite_shaper_font_data_destroy (data); + return NULL; + } + + data->hfont = CreateFontIndirectW (&data->log_font); + if (unlikely (!data->hfont)) { + DEBUG_MSG (DIRECTWRITE, font, "Font CreateFontIndirectW() failed"); + _hb_directwrite_shaper_font_data_destroy (data); + return NULL; + } + + if (!SelectObject (data->hdc, data->hfont)) { + DEBUG_MSG (DIRECTWRITE, font, "Font SelectObject() failed"); + _hb_directwrite_shaper_font_data_destroy (data); + return NULL; + } + + return data; +} + +void +_hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data) +{ + if (data->hdc) + ReleaseDC (NULL, data->hdc); + if (data->hfont) + DeleteObject (data->hfont); + free (data); +} + +LOGFONTW * +hb_directwrite_font_get_logfontw (hb_font_t *font) +{ + if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL; + hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); + return &font_data->log_font; +} + +HFONT +hb_directwrite_font_get_hfont (hb_font_t *font) +{ + if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL; + hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); + return font_data->hfont; +} + + +/* + * shaper shape_plan data + */ + +struct hb_directwrite_shaper_shape_plan_data_t {}; + +hb_directwrite_shaper_shape_plan_data_t * +_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, + const hb_feature_t *user_features HB_UNUSED, + unsigned int num_user_features HB_UNUSED) +{ + return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; +} + +void +_hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan_data_t *data HB_UNUSED) +{ +} + +// Most of here TextAnalysis is originally written by Bas Schouten for Mozilla project +// but now is relicensed to MIT for HarfBuzz use +class TextAnalysis + : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink +{ +public: + + IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; } + IFACEMETHOD_(ULONG, AddRef)() { return 1; } + IFACEMETHOD_(ULONG, Release)() { return 1; } + + // A single contiguous run of characters containing the same analysis + // results. + struct Run + { + UINT32 mTextStart; // starting text position of this run + UINT32 mTextLength; // number of contiguous code units covered + UINT32 mGlyphStart; // starting glyph in the glyphs array + UINT32 mGlyphCount; // number of glyphs associated with this run of + // text + DWRITE_SCRIPT_ANALYSIS mScript; + UINT8 mBidiLevel; + bool mIsSideways; + + inline bool ContainsTextPosition(UINT32 aTextPosition) const + { + return aTextPosition >= mTextStart + && aTextPosition < mTextStart + mTextLength; + } + + Run *nextRun; + }; + +public: + TextAnalysis(const wchar_t* text, + UINT32 textLength, + const wchar_t* localeName, + DWRITE_READING_DIRECTION readingDirection) + : mText(text) + , mTextLength(textLength) + , mLocaleName(localeName) + , mReadingDirection(readingDirection) + , mCurrentRun(NULL) { }; + + ~TextAnalysis() { + // delete runs, except mRunHead which is part of the TextAnalysis object + for (Run *run = mRunHead.nextRun; run;) { + Run *origRun = run; + run = run->nextRun; + delete origRun; + } + } + + STDMETHODIMP GenerateResults(IDWriteTextAnalyzer* textAnalyzer, + Run **runHead) { + // Analyzes the text using the script analyzer and returns + // the result as a series of runs. + + HRESULT hr = S_OK; + + // Initially start out with one result that covers the entire range. + // This result will be subdivided by the analysis processes. + mRunHead.mTextStart = 0; + mRunHead.mTextLength = mTextLength; + mRunHead.mBidiLevel = + (mReadingDirection == DWRITE_READING_DIRECTION_RIGHT_TO_LEFT); + mRunHead.nextRun = NULL; + mCurrentRun = &mRunHead; + + // Call each of the analyzers in sequence, recording their results. + if (SUCCEEDED(hr = textAnalyzer->AnalyzeScript(this, + 0, + mTextLength, + this))) { + *runHead = &mRunHead; + } + + return hr; + } + + // IDWriteTextAnalysisSource implementation + + IFACEMETHODIMP GetTextAtPosition(UINT32 textPosition, + OUT WCHAR const** textString, + OUT UINT32* textLength) + { + if (textPosition >= mTextLength) { + // No text at this position, valid query though. + *textString = NULL; + *textLength = 0; + } + else { + *textString = mText + textPosition; + *textLength = mTextLength - textPosition; + } + return S_OK; + } + + IFACEMETHODIMP GetTextBeforePosition(UINT32 textPosition, + OUT WCHAR const** textString, + OUT UINT32* textLength) + { + if (textPosition == 0 || textPosition > mTextLength) { + // Either there is no text before here (== 0), or this + // is an invalid position. The query is considered valid thouh. + *textString = NULL; + *textLength = 0; + } + else { + *textString = mText; + *textLength = textPosition; + } + return S_OK; + } + + IFACEMETHODIMP_(DWRITE_READING_DIRECTION) + GetParagraphReadingDirection() { return mReadingDirection; } + + IFACEMETHODIMP GetLocaleName(UINT32 textPosition, + UINT32* textLength, + WCHAR const** localeName) { + return S_OK; + } + + IFACEMETHODIMP + GetNumberSubstitution(UINT32 textPosition, + OUT UINT32* textLength, + OUT IDWriteNumberSubstitution** numberSubstitution) + { + // We do not support number substitution. + *numberSubstitution = NULL; + *textLength = mTextLength - textPosition; + + return S_OK; + } + + // IDWriteTextAnalysisSink implementation + + IFACEMETHODIMP + SetScriptAnalysis(UINT32 textPosition, + UINT32 textLength, + DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis) + { + SetCurrentRun(textPosition); + SplitCurrentRun(textPosition); + while (textLength > 0) { + Run *run = FetchNextRun(&textLength); + run->mScript = *scriptAnalysis; + } + + return S_OK; + } + + IFACEMETHODIMP + SetLineBreakpoints(UINT32 textPosition, + UINT32 textLength, + const DWRITE_LINE_BREAKPOINT* lineBreakpoints) { return S_OK; } + + IFACEMETHODIMP SetBidiLevel(UINT32 textPosition, + UINT32 textLength, + UINT8 explicitLevel, + UINT8 resolvedLevel) { return S_OK; } + + IFACEMETHODIMP + SetNumberSubstitution(UINT32 textPosition, + UINT32 textLength, + IDWriteNumberSubstitution* numberSubstitution) { return S_OK; } + +protected: + Run *FetchNextRun(IN OUT UINT32* textLength) + { + // Used by the sink setters, this returns a reference to the next run. + // Position and length are adjusted to now point after the current run + // being returned. + + Run *origRun = mCurrentRun; + // Split the tail if needed (the length remaining is less than the + // current run's size). + if (*textLength < mCurrentRun->mTextLength) { + SplitCurrentRun(mCurrentRun->mTextStart + *textLength); + } + else { + // Just advance the current run. + mCurrentRun = mCurrentRun->nextRun; + } + *textLength -= origRun->mTextLength; + + // Return a reference to the run that was just current. + return origRun; + } + + void SetCurrentRun(UINT32 textPosition) + { + // Move the current run to the given position. + // Since the analyzers generally return results in a forward manner, + // this will usually just return early. If not, find the + // corresponding run for the text position. + + if (mCurrentRun && mCurrentRun->ContainsTextPosition(textPosition)) { + return; + } + + for (Run *run = &mRunHead; run; run = run->nextRun) { + if (run->ContainsTextPosition(textPosition)) { + mCurrentRun = run; + return; + } + } + //NS_NOTREACHED("We should always be able to find the text position in one \ + // of our runs"); + } + + void SplitCurrentRun(UINT32 splitPosition) + { + if (!mCurrentRun) { + //NS_ASSERTION(false, "SplitCurrentRun called without current run."); + // Shouldn't be calling this when no current run is set! + return; + } + // Split the current run. + if (splitPosition <= mCurrentRun->mTextStart) { + // No need to split, already the start of a run + // or before it. Usually the first. + return; + } + Run *newRun = new Run; + + *newRun = *mCurrentRun; + + // Insert the new run in our linked list. + newRun->nextRun = mCurrentRun->nextRun; + mCurrentRun->nextRun = newRun; + + // Adjust runs' text positions and lengths. + UINT32 splitPoint = splitPosition - mCurrentRun->mTextStart; + newRun->mTextStart += splitPoint; + newRun->mTextLength -= splitPoint; + mCurrentRun->mTextLength = splitPoint; + mCurrentRun = newRun; + } + +protected: + // Input + // (weak references are fine here, since this class is a transient + // stack-based helper that doesn't need to copy data) + UINT32 mTextLength; + const WCHAR* mText; + const WCHAR* mLocaleName; + DWRITE_READING_DIRECTION mReadingDirection; + + // Current processing state. + Run *mCurrentRun; + + // Output is a list of runs starting here + Run mRunHead; +}; + + +/* + * shaper + */ + +hb_bool_t +_hb_directwrite_shape(hb_shape_plan_t *shape_plan, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features) +{ + hb_face_t *face = font->face; + hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); + hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); + + // factory probably should be cached + IDWriteFactory* dwriteFactory; + DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), + reinterpret_cast(&dwriteFactory) + ); + + IDWriteGdiInterop *gdiInterop; + dwriteFactory->GetGdiInterop (&gdiInterop); + IDWriteFontFace* fontFace; + gdiInterop->CreateFontFaceFromHdc (font_data->hdc, &fontFace); + + IDWriteTextAnalyzer* analyzer; + dwriteFactory->CreateTextAnalyzer (&analyzer); + + unsigned int scratch_size; + hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); +#define ALLOCATE_ARRAY(Type, name, len) \ + Type *name = (Type *) scratch; \ + { \ + unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ + assert (_consumed <= scratch_size); \ + scratch += _consumed; \ + scratch_size -= _consumed; \ + } + +#define utf16_index() var1.u32 + + ALLOCATE_ARRAY(WCHAR, pchars, buffer->len * 2); + + unsigned int chars_len = 0; + for (unsigned int i = 0; i < buffer->len; i++) + { + hb_codepoint_t c = buffer->info[i].codepoint; + buffer->info[i].utf16_index() = chars_len; + if (likely(c <= 0xFFFFu)) + pchars[chars_len++] = c; + else if (unlikely(c > 0x10FFFFu)) + pchars[chars_len++] = 0xFFFDu; + else { + pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); + pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1)); + } + } + + ALLOCATE_ARRAY(WORD, log_clusters, chars_len); + if (num_features) + { + /* Need log_clusters to assign features. */ + chars_len = 0; + for (unsigned int i = 0; i < buffer->len; i++) + { + hb_codepoint_t c = buffer->info[i].codepoint; + unsigned int cluster = buffer->info[i].cluster; + log_clusters[chars_len++] = cluster; + if (hb_in_range(c, 0x10000u, 0x10FFFFu)) + log_clusters[chars_len++] = cluster; /* Surrogates. */ + } + } + + HRESULT hr; + // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES + + DWRITE_READING_DIRECTION readingDirection = buffer->props.direction ? + DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : + DWRITE_READING_DIRECTION_LEFT_TO_RIGHT; + + /* + * There's an internal 16-bit limit on some things inside the analyzer, + * but we never attempt to shape a word longer than 64K characters + * in a single gfxShapedWord, so we cannot exceed that limit. + */ + UINT32 length = buffer->len; + + TextAnalysis analysis(pchars, length, NULL, readingDirection); + TextAnalysis::Run *runHead; + hr = analysis.GenerateResults(analyzer, &runHead); + + if (FAILED(hr)) { + //NS_WARNING("Analyzer failed to generate results."); + return false; + } + + UINT32 maxGlyphs = 3 * length / 2 + 16; + +#define INITIAL_GLYPH_SIZE 400 + UINT16* clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); + UINT16* glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); + DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*) + malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES)); + DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*) + malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES)); + + UINT32 actualGlyphs; + + bool backward = HB_DIRECTION_IS_BACKWARD(buffer->props.direction); + + wchar_t lang[4]; + mbstowcs(lang, hb_language_to_string(buffer->props.language), 4); + hr = analyzer->GetGlyphs(pchars, length, + fontFace, FALSE, + buffer->props.direction, + &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0, + maxGlyphs, clusters, textProperties, + glyphs, glyphProperties, &actualGlyphs); + + if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { + free(clusters); + free(glyphs); + free(textProperties); + free(glyphProperties); + + clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); + glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16)); + textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*) + malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES)); + glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*) + malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES)); + + hr = analyzer->GetGlyphs(pchars, length, + fontFace, FALSE, + buffer->props.direction, + &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0, + maxGlyphs, clusters, textProperties, + glyphs, glyphProperties, &actualGlyphs); + } + if (FAILED(hr)) { + //NS_WARNING("Analyzer failed to get glyphs."); + return false; + } + + FLOAT advances[400]; + DWRITE_GLYPH_OFFSET offsets[400]; + + + /* The -2 in the following is to compensate for possible + * alignment needed after the WORD array. sizeof(WORD) == 2. */ + unsigned int glyphs_size = (scratch_size * sizeof (int)-2) + / (sizeof (WORD) + + 4 + // sizeof (SCRIPT_GLYPHPROP) + + sizeof (int) + + 8 + // sizeof (GOFFSET) + + sizeof (uint32_t)); + ALLOCATE_ARRAY(uint32_t, vis_clusters, glyphs_size); + +#undef ALLOCATE_ARRAY + + hr = analyzer->GetGlyphPlacements(pchars, + clusters, + textProperties, + length, + glyphs, + glyphProperties, + actualGlyphs, + fontFace, + face->get_upem(), + FALSE, + FALSE, + &runHead->mScript, + NULL, + NULL, + NULL, + 0, + advances, + offsets); + + if (FAILED(hr)) { + //NS_WARNING("Analyzer failed to get glyph placements."); + return false; + } + + unsigned int glyphs_len = actualGlyphs; + + /* Ok, we've got everything we need, now compose output buffer, + * very, *very*, carefully! */ + + /* Calculate visual-clusters. That's what we ship. */ + for (unsigned int i = 0; i < glyphs_len; i++) + vis_clusters[i] = -1; + for (unsigned int i = 0; i < buffer->len; i++) { + uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]]; + //*p = MIN (*p, buffer->info[i].cluster); + } + for (unsigned int i = 1; i < glyphs_len; i++) + if (vis_clusters[i] == -1) + vis_clusters[i] = vis_clusters[i - 1]; + +#undef utf16_index + + //if (unlikely (!buffer->ensure (glyphs_len))) + // FAIL ("Buffer in error"); + +#undef FAIL + + /* Set glyph infos */ + buffer->len = 0; + for (unsigned int i = 0; i < glyphs_len; i++) + { + hb_glyph_info_t *info = &buffer->info[buffer->len++]; + + info->codepoint = glyphs[i]; + info->cluster = vis_clusters[i]; + + /* The rest is crap. Let's store position info there for now. */ + info->mask = advances[i]; + info->var1.u32 = offsets[i].ascenderOffset; + info->var2.u32 = -offsets[i].advanceOffset; + } + + free(clusters); + free(glyphs); + free(textProperties); + free(glyphProperties); + + /* Set glyph positions */ + buffer->clear_positions (); + for (unsigned int i = 0; i < glyphs_len; i++) + { + hb_glyph_info_t *info = &buffer->info[i]; + hb_glyph_position_t *pos = &buffer->pos[i]; + + /* TODO vertical */ + pos->x_advance = info->mask; + pos->x_offset = backward ? -info->var1.u32 : info->var1.u32; + pos->y_offset = info->var2.u32; + } + + if (backward) + hb_buffer_reverse (buffer); + + /* Wow, done! */ + return true; +} diff -uN gfx/harfbuzz/src_old/hb-directwrite.h gfx/harfbuzz/src/hb-directwrite.h --- gfx/harfbuzz/src_old/hb-directwrite.h 1970-01-01 01:00:00.000000000 +0100 +++ gfx/harfbuzz/src/hb-directwrite.h 2016-06-05 23:48:40.059236276 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright © 2015 Ebrahim Byagowi + * + * 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_DIRECTWRITE_H +#define HB_DIRECTWRITE_H + +#include "hb.h" + +HB_BEGIN_DECLS + +HB_END_DECLS + +#endif /* HB_UNISCRIBE_H */ diff -uN gfx/harfbuzz/src_old/hb-face.cc gfx/harfbuzz/src/hb-face.cc --- gfx/harfbuzz/src_old/hb-face.cc 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-face.cc 2016-06-05 23:48:42.449223049 +0200 @@ -77,7 +77,7 @@ * * Return value: (transfer full) * - * Since: 1.0 + * Since: 0.9.2 **/ hb_face_t * hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, @@ -113,7 +113,7 @@ { hb_face_for_data_closure_t *closure; - closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t)); + closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t)); if (unlikely (!closure)) return NULL; @@ -157,7 +157,7 @@ * * Return value: (transfer full): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_face_t * hb_face_create (hb_blob_t *blob, @@ -165,8 +165,8 @@ { hb_face_t *face; - if (unlikely (!blob || !hb_blob_get_length (blob))) - return hb_face_get_empty (); + if (unlikely (!blob)) + blob = hb_blob_get_empty (); hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer::sanitize (hb_blob_reference (blob)), index); @@ -189,7 +189,7 @@ * * Return value: (transfer full) * - * Since: 1.0 + * Since: 0.9.2 **/ hb_face_t * hb_face_get_empty (void) @@ -206,7 +206,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_face_t * hb_face_reference (hb_face_t *face) @@ -220,7 +220,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_face_destroy (hb_face_t *face) @@ -257,7 +257,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_face_set_user_data (hb_face_t *face, @@ -278,7 +278,7 @@ * * Return value: (transfer none): * - * Since: 1.0 + * Since: 0.9.2 **/ void * hb_face_get_user_data (hb_face_t *face, @@ -293,7 +293,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_face_make_immutable (hb_face_t *face) @@ -312,7 +312,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_face_is_immutable (hb_face_t *face) @@ -330,7 +330,7 @@ * * Return value: (transfer full): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_blob_t * hb_face_reference_table (hb_face_t *face, @@ -347,7 +347,7 @@ * * Return value: (transfer full): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_blob_t * hb_face_reference_blob (hb_face_t *face) @@ -362,7 +362,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_face_set_index (hb_face_t *face, @@ -382,7 +382,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ unsigned int hb_face_get_index (hb_face_t *face) @@ -397,7 +397,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_face_set_upem (hb_face_t *face, @@ -417,7 +417,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ unsigned int hb_face_get_upem (hb_face_t *face) @@ -441,7 +441,7 @@ * * * - * Since: 1.0 + * Since: 0.9.7 **/ void hb_face_set_glyph_count (hb_face_t *face, @@ -461,7 +461,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.7 **/ unsigned int hb_face_get_glyph_count (hb_face_t *face) diff -uN gfx/harfbuzz/src_old/hb-face.h gfx/harfbuzz/src/hb-face.h --- gfx/harfbuzz/src_old/hb-face.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-face.h 2016-06-05 23:48:43.669216308 +0200 @@ -43,28 +43,28 @@ typedef struct hb_face_t hb_face_t; -hb_face_t * +HB_EXTERN hb_face_t * hb_face_create (hb_blob_t *blob, unsigned int index); typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data); /* calls destroy() when not needing user_data anymore */ -hb_face_t * +HB_EXTERN hb_face_t * hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, void *user_data, hb_destroy_func_t destroy); -hb_face_t * +HB_EXTERN hb_face_t * hb_face_get_empty (void); -hb_face_t * +HB_EXTERN hb_face_t * hb_face_reference (hb_face_t *face); -void +HB_EXTERN void hb_face_destroy (hb_face_t *face); -hb_bool_t +HB_EXTERN hb_bool_t hb_face_set_user_data (hb_face_t *face, hb_user_data_key_t *key, void * data, @@ -72,43 +72,43 @@ hb_bool_t replace); -void * +HB_EXTERN void * hb_face_get_user_data (hb_face_t *face, hb_user_data_key_t *key); -void +HB_EXTERN void hb_face_make_immutable (hb_face_t *face); -hb_bool_t +HB_EXTERN hb_bool_t hb_face_is_immutable (hb_face_t *face); -hb_blob_t * +HB_EXTERN hb_blob_t * hb_face_reference_table (hb_face_t *face, hb_tag_t tag); -hb_blob_t * +HB_EXTERN hb_blob_t * hb_face_reference_blob (hb_face_t *face); -void +HB_EXTERN void hb_face_set_index (hb_face_t *face, unsigned int index); -unsigned int +HB_EXTERN unsigned int hb_face_get_index (hb_face_t *face); -void +HB_EXTERN void hb_face_set_upem (hb_face_t *face, unsigned int upem); -unsigned int +HB_EXTERN unsigned int hb_face_get_upem (hb_face_t *face); -void +HB_EXTERN void hb_face_set_glyph_count (hb_face_t *face, unsigned int glyph_count); -unsigned int +HB_EXTERN unsigned int hb_face_get_glyph_count (hb_face_t *face); diff -uN gfx/harfbuzz/src_old/hb-fallback-shape.cc gfx/harfbuzz/src/hb-fallback-shape.cc --- gfx/harfbuzz/src_old/hb-fallback-shape.cc 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-fallback-shape.cc 2016-06-05 23:48:44.900209512 +0200 @@ -106,7 +106,7 @@ */ hb_codepoint_t space; - bool has_space = font->get_glyph (' ', 0, &space); + bool has_space = (bool) font->get_glyph (' ', 0, &space); buffer->clear_positions (); diff -uN gfx/harfbuzz/src_old/hb-font.cc gfx/harfbuzz/src/hb-font.cc --- gfx/harfbuzz/src_old/hb-font.cc 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-font.cc 2016-06-05 23:48:47.920192879 +0200 @@ -45,130 +45,224 @@ */ static hb_bool_t -hb_font_get_glyph_nil (hb_font_t *font, +hb_font_get_font_h_extents_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + memset (metrics, 0, sizeof (*metrics)); + return false; +} +static hb_bool_t +hb_font_get_font_h_extents_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_font_h_extents (metrics); + if (ret) { + metrics->ascender = font->parent_scale_y_distance (metrics->ascender); + metrics->descender = font->parent_scale_y_distance (metrics->descender); + metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap); + } + return ret; +} + +static hb_bool_t +hb_font_get_font_v_extents_nil (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + memset (metrics, 0, sizeof (*metrics)); + return false; +} +static hb_bool_t +hb_font_get_font_v_extents_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_font_v_extents (metrics); + if (ret) { + metrics->ascender = font->parent_scale_x_distance (metrics->ascender); + metrics->descender = font->parent_scale_x_distance (metrics->descender); + metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap); + } + return ret; +} + +static hb_bool_t +hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent->get_glyph (unicode, variation_selector, glyph); - *glyph = 0; return false; } +static hb_bool_t +hb_font_get_glyph_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + return font->parent->get_glyph (unicode, variation_selector, glyph); +} static hb_position_t -hb_font_get_glyph_h_advance_nil (hb_font_t *font, +hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); - return font->x_scale; } +static hb_position_t +hb_font_get_glyph_h_advance_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) +{ + return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); +} static hb_position_t -hb_font_get_glyph_v_advance_nil (hb_font_t *font, +hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); - return font->y_scale; } +static hb_position_t +hb_font_get_glyph_v_advance_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) +{ + return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); +} static hb_bool_t -hb_font_get_glyph_h_origin_nil (hb_font_t *font, +hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) { - if (font->parent) { - hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y); - if (ret) - font->parent_scale_position (x, y); - return ret; - } - *x = *y = 0; - return false; + return true; +} +static hb_bool_t +hb_font_get_glyph_h_origin_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y); + if (ret) + font->parent_scale_position (x, y); + return ret; } static hb_bool_t -hb_font_get_glyph_v_origin_nil (hb_font_t *font, +hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) { - if (font->parent) { - hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y); - if (ret) - font->parent_scale_position (x, y); - return ret; - } - *x = *y = 0; return false; } +static hb_bool_t +hb_font_get_glyph_v_origin_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y); + if (ret) + font->parent_scale_position (x, y); + return ret; +} static hb_position_t -hb_font_get_glyph_h_kerning_nil (hb_font_t *font, +hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t left_glyph, hb_codepoint_t right_glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); - return 0; } +static hb_position_t +hb_font_get_glyph_h_kerning_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t left_glyph, + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) +{ + return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); +} static hb_position_t -hb_font_get_glyph_v_kerning_nil (hb_font_t *font, +hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); - return 0; } +static hb_position_t +hb_font_get_glyph_v_kerning_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t top_glyph, + hb_codepoint_t bottom_glyph, + void *user_data HB_UNUSED) +{ + return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); +} static hb_bool_t -hb_font_get_glyph_extents_nil (hb_font_t *font, +hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - if (font->parent) { - hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); - if (ret) { - font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); - font->parent_scale_distance (&extents->width, &extents->height); - } - return ret; - } - memset (extents, 0, sizeof (*extents)); return false; } +static hb_bool_t +hb_font_get_glyph_extents_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); + if (ret) { + font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); + font->parent_scale_distance (&extents->width, &extents->height); + } + return ret; +} static hb_bool_t -hb_font_get_glyph_contour_point_nil (hb_font_t *font, +hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, unsigned int point_index, @@ -176,45 +270,63 @@ hb_position_t *y, void *user_data HB_UNUSED) { - if (font->parent) { - hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); - if (ret) - font->parent_scale_position (x, y); - return ret; - } - *x = *y = 0; return false; } +static hb_bool_t +hb_font_get_glyph_contour_point_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + unsigned int point_index, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); + if (ret) + font->parent_scale_position (x, y); + return ret; +} static hb_bool_t -hb_font_get_glyph_name_nil (hb_font_t *font, +hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, char *name, unsigned int size, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent->get_glyph_name (glyph, name, size); - if (size) *name = '\0'; return false; } +static hb_bool_t +hb_font_get_glyph_name_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + char *name, unsigned int size, + void *user_data HB_UNUSED) +{ + return font->parent->get_glyph_name (glyph, name, size); +} static hb_bool_t -hb_font_get_glyph_from_name_nil (hb_font_t *font, +hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent->get_glyph_from_name (name, len, glyph); - *glyph = 0; return false; } - +static hb_bool_t +hb_font_get_glyph_from_name_parent (hb_font_t *font, + void *font_data HB_UNUSED, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + return font->parent->get_glyph_from_name (name, len, glyph); +} static const hb_font_funcs_t _hb_font_funcs_nil = { HB_OBJECT_HEADER_STATIC, @@ -222,9 +334,44 @@ true, /* immutable */ { +#define HB_FONT_FUNC_IMPLEMENT(name) NULL, + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + }, + { +#define HB_FONT_FUNC_IMPLEMENT(name) NULL, + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + }, + { + { #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil, + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + } + } +}; +static const hb_font_funcs_t _hb_font_funcs_parent = { + HB_OBJECT_HEADER_STATIC, + + true, /* immutable */ + + { +#define HB_FONT_FUNC_IMPLEMENT(name) NULL, + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + }, + { +#define HB_FONT_FUNC_IMPLEMENT(name) NULL, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT + }, + { + { +#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent, + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + } } }; @@ -236,7 +383,7 @@ * * Return value: (transfer full): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_font_funcs_t * hb_font_funcs_create (void) @@ -246,7 +393,7 @@ if (!(ffuncs = hb_object_create ())) return hb_font_funcs_get_empty (); - ffuncs->get = _hb_font_funcs_nil.get; + ffuncs->get = _hb_font_funcs_parent.get; return ffuncs; } @@ -258,12 +405,12 @@ * * Return value: (transfer full): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_font_funcs_t * hb_font_funcs_get_empty (void) { - return const_cast (&_hb_font_funcs_nil); + return const_cast (&_hb_font_funcs_parent); } /** @@ -274,7 +421,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_font_funcs_t * hb_font_funcs_reference (hb_font_funcs_t *ffuncs) @@ -288,7 +435,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) @@ -315,7 +462,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, @@ -336,7 +483,7 @@ * * Return value: (transfer none): * - * Since: 1.0 + * Since: 0.9.2 **/ void * hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, @@ -352,7 +499,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) @@ -371,7 +518,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs) @@ -398,11 +545,11 @@ ffuncs->destroy.name (ffuncs->user_data.name); \ \ if (func) { \ - ffuncs->get.name = func; \ + ffuncs->get.f.name = func; \ ffuncs->user_data.name = user_data; \ ffuncs->destroy.name = destroy; \ } else { \ - ffuncs->get.name = hb_font_get_##name##_nil; \ + ffuncs->get.f.name = hb_font_get_##name##_parent; \ ffuncs->user_data.name = NULL; \ ffuncs->destroy.name = NULL; \ } \ @@ -411,10 +558,53 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT +bool +hb_font_t::has_func (unsigned int i) +{ + if (parent && parent != hb_font_get_empty () && parent->has_func (i)) + return true; + return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i]; +} /* Public getters */ /** + * hb_font_get_h_extents: + * @font: a font. + * @extents: (out): + * + * + * + * Return value: + * + * Since: 1.1.3 + **/ +hb_bool_t +hb_font_get_h_extents (hb_font_t *font, + hb_font_extents_t *extents) +{ + return font->get_font_h_extents (extents); +} + +/** + * hb_font_get_v_extents: + * @font: a font. + * @extents: (out): + * + * + * + * Return value: + * + * Since: 1.1.3 + **/ +hb_bool_t +hb_font_get_v_extents (hb_font_t *font, + hb_font_extents_t *extents) +{ + return font->get_font_v_extents (extents); +} + +/** * hb_font_get_glyph: * @font: a font. * @unicode: @@ -425,7 +615,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_get_glyph (hb_font_t *font, @@ -444,7 +634,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_position_t hb_font_get_glyph_h_advance (hb_font_t *font, @@ -462,7 +652,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_position_t hb_font_get_glyph_v_advance (hb_font_t *font, @@ -482,7 +672,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_get_glyph_h_origin (hb_font_t *font, @@ -503,7 +693,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_get_glyph_v_origin (hb_font_t *font, @@ -523,7 +713,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_position_t hb_font_get_glyph_h_kerning (hb_font_t *font, @@ -542,7 +732,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, @@ -561,7 +751,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_get_glyph_extents (hb_font_t *font, @@ -583,7 +773,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_get_glyph_contour_point (hb_font_t *font, @@ -604,7 +794,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_get_glyph_name (hb_font_t *font, @@ -625,7 +815,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_get_glyph_from_name (hb_font_t *font, @@ -639,6 +829,23 @@ /* A bit higher-level, and with fallback */ /** + * hb_font_get_extents_for_direction: + * @font: a font. + * @direction: + * @extents: + * + * + * + * Since: 1.1.3 + **/ +void +hb_font_get_extents_for_direction (hb_font_t *font, + hb_direction_t direction, + hb_font_extents_t *extents) +{ + return font->get_extents_for_direction (direction, extents); +} +/** * hb_font_get_glyph_advance_for_direction: * @font: a font. * @glyph: @@ -648,7 +855,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_get_glyph_advance_for_direction (hb_font_t *font, @@ -669,7 +876,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_get_glyph_origin_for_direction (hb_font_t *font, @@ -690,7 +897,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_add_glyph_origin_for_direction (hb_font_t *font, @@ -711,7 +918,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, @@ -733,7 +940,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_get_glyph_kerning_for_direction (hb_font_t *font, @@ -755,7 +962,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_get_glyph_extents_for_origin (hb_font_t *font, @@ -779,7 +986,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, @@ -800,7 +1007,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_glyph_to_string (hb_font_t *font, @@ -814,7 +1021,7 @@ /** * hb_font_glyph_from_string: * @font: a font. - * @s: (array length=len): + * @s: (array length=len) (element-type uint8_t): * @len: * @glyph: (out): * @@ -822,7 +1029,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_glyph_from_string (hb_font_t *font, @@ -845,7 +1052,7 @@ * * Return value: (transfer full): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_font_t * hb_font_create (hb_face_t *face) @@ -854,15 +1061,16 @@ if (unlikely (!face)) face = hb_face_get_empty (); - if (unlikely (hb_object_is_inert (face))) - return hb_font_get_empty (); if (!(font = hb_object_create ())) return hb_font_get_empty (); hb_face_make_immutable (face); + font->parent = hb_font_get_empty (); font->face = hb_face_reference (face); font->klass = hb_font_funcs_get_empty (); + font->x_scale = font->y_scale = hb_face_get_upem (face); + return font; } @@ -874,20 +1082,19 @@ * * Return value: (transfer full): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_font_t * hb_font_create_sub_font (hb_font_t *parent) { if (unlikely (!parent)) - return hb_font_get_empty (); + parent = hb_font_get_empty (); hb_font_t *font = hb_font_create (parent->face); if (unlikely (hb_object_is_inert (font))) return font; - hb_font_make_immutable (parent); font->parent = hb_font_reference (parent); font->x_scale = parent->x_scale; @@ -905,7 +1112,7 @@ * * Return value: (transfer full) * - * Since: 1.0 + * Since: 0.9.2 **/ hb_font_t * hb_font_get_empty (void) @@ -918,8 +1125,8 @@ NULL, /* parent */ const_cast (&_hb_face_nil), - 0, /* x_scale */ - 0, /* y_scale */ + 1000, /* x_scale */ + 1000, /* y_scale */ 0, /* x_ppem */ 0, /* y_ppem */ @@ -946,7 +1153,7 @@ * * Return value: (transfer full): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_font_t * hb_font_reference (hb_font_t *font) @@ -960,7 +1167,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_destroy (hb_font_t *font) @@ -993,7 +1200,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_set_user_data (hb_font_t *font, @@ -1014,7 +1221,7 @@ * * Return value: (transfer none): * - * Since: 1.0 + * Since: 0.9.2 **/ void * hb_font_get_user_data (hb_font_t *font, @@ -1029,7 +1236,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_make_immutable (hb_font_t *font) @@ -1037,6 +1244,9 @@ if (unlikely (hb_object_is_inert (font))) return; + if (font->parent) + hb_font_make_immutable (font->parent); + font->immutable = true; } @@ -1048,7 +1258,7 @@ * * Return value: * - * Since: 1.0 + * Since: 0.9.2 **/ hb_bool_t hb_font_is_immutable (hb_font_t *font) @@ -1057,6 +1267,32 @@ } /** + * hb_font_set_parent: + * @font: a font. + * @parent: new parent. + * + * Sets parent font of @font. + * + * Since: 1.0.5 + **/ +void +hb_font_set_parent (hb_font_t *font, + hb_font_t *parent) +{ + if (font->immutable) + return; + + if (!parent) + parent = hb_font_get_empty (); + + hb_font_t *old = font->parent; + + font->parent = hb_font_reference (parent); + + hb_font_destroy (old); +} + +/** * hb_font_get_parent: * @font: a font. * @@ -1064,7 +1300,7 @@ * * Return value: (transfer none): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_font_t * hb_font_get_parent (hb_font_t *font) @@ -1080,7 +1316,7 @@ * * Return value: (transfer none): * - * Since: 1.0 + * Since: 0.9.2 **/ hb_face_t * hb_font_get_face (hb_font_t *font) @@ -1098,7 +1334,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_set_funcs (hb_font_t *font, @@ -1133,7 +1369,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_set_funcs_data (hb_font_t *font, @@ -1163,7 +1399,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_set_scale (hb_font_t *font, @@ -1185,7 +1421,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_get_scale (hb_font_t *font, @@ -1204,7 +1440,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_set_ppem (hb_font_t *font, @@ -1226,7 +1462,7 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ void hb_font_get_ppem (hb_font_t *font, diff -uN gfx/harfbuzz/src_old/hb-font.h gfx/harfbuzz/src/hb-font.h --- gfx/harfbuzz/src_old/hb-font.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-font.h 2016-06-05 23:48:49.311185210 +0200 @@ -46,19 +46,19 @@ typedef struct hb_font_funcs_t hb_font_funcs_t; -hb_font_funcs_t * +HB_EXTERN hb_font_funcs_t * hb_font_funcs_create (void); -hb_font_funcs_t * +HB_EXTERN hb_font_funcs_t * hb_font_funcs_get_empty (void); -hb_font_funcs_t * +HB_EXTERN hb_font_funcs_t * hb_font_funcs_reference (hb_font_funcs_t *ffuncs); -void +HB_EXTERN void hb_font_funcs_destroy (hb_font_funcs_t *ffuncs); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, hb_user_data_key_t *key, void * data, @@ -66,31 +66,56 @@ hb_bool_t replace); -void * +HB_EXTERN void * hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, hb_user_data_key_t *key); -void +HB_EXTERN void hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs); -/* glyph extents */ +/* font and glyph extents */ +/* Note that typically ascender is positive and descender negative in coordinate systems that grow up. */ +typedef struct hb_font_extents_t +{ + hb_position_t ascender; /* typographic ascender. */ + hb_position_t descender; /* typographic descender. */ + hb_position_t line_gap; /* suggested line spacing gap. */ + /*< private >*/ + hb_position_t reserved9; + hb_position_t reserved8; + hb_position_t reserved7; + hb_position_t reserved6; + hb_position_t reserved5; + hb_position_t reserved4; + hb_position_t reserved3; + hb_position_t reserved2; + hb_position_t reserved1; +} hb_font_extents_t; + +/* Note that height is negative in coordinate systems that grow up. */ typedef struct hb_glyph_extents_t { - hb_position_t x_bearing; - hb_position_t y_bearing; - hb_position_t width; - hb_position_t height; + hb_position_t x_bearing; /* left side of glyph from origin. */ + hb_position_t y_bearing; /* top side of glyph from origin. */ + hb_position_t width; /* distance from left to right side. */ + hb_position_t height; /* distance from top to bottom side. */ } hb_glyph_extents_t; - /* func types */ +typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data, + hb_font_extents_t *metrics, + void *user_data); +typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t; +typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t; + + typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph, @@ -140,6 +165,38 @@ /* func setters */ /** + * hb_font_funcs_set_font_h_extents_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.1.2 + **/ +HB_EXTERN void +hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs, + hb_font_get_font_h_extents_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_font_v_extents_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.1.2 + **/ +HB_EXTERN void +hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs, + hb_font_get_font_v_extents_func_t func, + void *user_data, hb_destroy_func_t destroy); + +/** * hb_font_funcs_set_glyph_func: * @ffuncs: font functions. * @func: (closure user_data) (destroy destroy) (scope notified): @@ -148,9 +205,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void 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); @@ -164,9 +221,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_advance_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -180,9 +237,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_advance_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -196,9 +253,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_origin_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -212,9 +269,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_origin_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -228,9 +285,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_kerning_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -244,9 +301,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_kerning_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -260,9 +317,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_extents_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -276,9 +333,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_contour_point_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -292,9 +349,9 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_name_func_t func, void *user_data, hb_destroy_func_t destroy); @@ -308,59 +365,65 @@ * * * - * Since: 1.0 + * Since: 0.9.2 **/ -void +HB_EXTERN void hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_from_name_func_t func, void *user_data, hb_destroy_func_t destroy); - /* func dispatch */ -hb_bool_t +HB_EXTERN hb_bool_t +hb_font_get_h_extents (hb_font_t *font, + hb_font_extents_t *extents); +HB_EXTERN hb_bool_t +hb_font_get_v_extents (hb_font_t *font, + hb_font_extents_t *extents); + +HB_EXTERN hb_bool_t hb_font_get_glyph (hb_font_t *font, hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph); -hb_position_t +HB_EXTERN hb_position_t hb_font_get_glyph_h_advance (hb_font_t *font, hb_codepoint_t glyph); -hb_position_t +HB_EXTERN hb_position_t hb_font_get_glyph_v_advance (hb_font_t *font, hb_codepoint_t glyph); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_h_origin (hb_font_t *font, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_v_origin (hb_font_t *font, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y); -hb_position_t +HB_EXTERN hb_position_t hb_font_get_glyph_h_kerning (hb_font_t *font, hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); -hb_position_t +HB_EXTERN hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_contour_point (hb_font_t *font, hb_codepoint_t glyph, unsigned int point_index, hb_position_t *x, hb_position_t *y); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_name (hb_font_t *font, hb_codepoint_t glyph, char *name, unsigned int size); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_from_name (hb_font_t *font, const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); @@ -368,52 +431,56 @@ /* high-level funcs, with fallback */ -void +HB_EXTERN void +hb_font_get_extents_for_direction (hb_font_t *font, + hb_direction_t direction, + hb_font_extents_t *extents); +HB_EXTERN void hb_font_get_glyph_advance_for_direction (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -void +HB_EXTERN void hb_font_get_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -void +HB_EXTERN void hb_font_add_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -void +HB_EXTERN void hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -void +HB_EXTERN void hb_font_get_glyph_kerning_for_direction (hb_font_t *font, hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_extents_for_origin (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, hb_glyph_extents_t *extents); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, hb_codepoint_t glyph, unsigned int point_index, hb_direction_t direction, hb_position_t *x, hb_position_t *y); /* Generates gidDDD if glyph has no name. */ -void +HB_EXTERN void hb_font_glyph_to_string (hb_font_t *font, hb_codepoint_t glyph, char *s, unsigned int size); /* Parses gidDDD and uniUUUU strings automatically. */ -hb_bool_t +HB_EXTERN hb_bool_t hb_font_glyph_from_string (hb_font_t *font, const char *s, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); @@ -425,22 +492,22 @@ /* Fonts are very light-weight objects */ -hb_font_t * +HB_EXTERN hb_font_t * hb_font_create (hb_face_t *face); -hb_font_t * +HB_EXTERN hb_font_t * hb_font_create_sub_font (hb_font_t *parent); -hb_font_t * +HB_EXTERN hb_font_t * hb_font_get_empty (void); -hb_font_t * +HB_EXTERN hb_font_t * hb_font_reference (hb_font_t *font); -void +HB_EXTERN void hb_font_destroy (hb_font_t *font); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_set_user_data (hb_font_t *font, hb_user_data_key_t *key, void * data, @@ -448,42 +515,46 @@ hb_bool_t replace); -void * +HB_EXTERN void * hb_font_get_user_data (hb_font_t *font, hb_user_data_key_t *key); -void +HB_EXTERN void hb_font_make_immutable (hb_font_t *font); -hb_bool_t +HB_EXTERN hb_bool_t hb_font_is_immutable (hb_font_t *font); -hb_font_t * +HB_EXTERN void +hb_font_set_parent (hb_font_t *font, + hb_font_t *parent); + +HB_EXTERN hb_font_t * hb_font_get_parent (hb_font_t *font); -hb_face_t * +HB_EXTERN hb_face_t * hb_font_get_face (hb_font_t *font); -void +HB_EXTERN void hb_font_set_funcs (hb_font_t *font, hb_font_funcs_t *klass, void *font_data, hb_destroy_func_t destroy); /* Be *very* careful with this function! */ -void +HB_EXTERN void hb_font_set_funcs_data (hb_font_t *font, void *font_data, hb_destroy_func_t destroy); -void +HB_EXTERN void hb_font_set_scale (hb_font_t *font, int x_scale, int y_scale); -void +HB_EXTERN void hb_font_get_scale (hb_font_t *font, int *x_scale, int *y_scale); @@ -491,12 +562,12 @@ /* * A zero value means "no hinting in that direction" */ -void +HB_EXTERN void hb_font_set_ppem (hb_font_t *font, unsigned int x_ppem, unsigned int y_ppem); -void +HB_EXTERN void hb_font_get_ppem (hb_font_t *font, unsigned int *x_ppem, unsigned int *y_ppem); diff -uN gfx/harfbuzz/src_old/hb-font-private.hh gfx/harfbuzz/src/hb-font-private.hh --- gfx/harfbuzz/src_old/hb-font-private.hh 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-font-private.hh 2016-06-05 23:48:46.442201028 +0200 @@ -42,6 +42,8 @@ */ #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ + HB_FONT_FUNC_IMPLEMENT (font_h_extents) \ + HB_FONT_FUNC_IMPLEMENT (font_v_extents) \ HB_FONT_FUNC_IMPLEMENT (glyph) \ HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ @@ -61,14 +63,6 @@ hb_bool_t immutable; - /* Don't access these directly. Call hb_font_get_*() instead. */ - - struct { -#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT - } get; - struct { #define HB_FONT_FUNC_IMPLEMENT(name) void *name; HB_FONT_FUNCS_IMPLEMENT_CALLBACKS @@ -80,6 +74,16 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT } destroy; + + /* Don't access these directly. Call font->get_*() instead. */ + union get_t { + struct get_funcs_t { +#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + } f; + void (*array[VAR]) (void); + } get; }; @@ -144,7 +148,36 @@ /* Public getters */ - inline hb_bool_t has_glyph (hb_codepoint_t unicode) + HB_INTERNAL bool has_func (unsigned int i); + + /* has_* ... */ +#define HB_FONT_FUNC_IMPLEMENT(name) \ + bool \ + has_##name##_func (void) \ + { \ + hb_font_funcs_t *funcs = this->klass; \ + unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ + return has_func (i); \ + } + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + + inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents) + { + memset (extents, 0, sizeof (*extents)); + return klass->get.f.font_h_extents (this, user_data, + extents, + klass->user_data.font_h_extents); + } + inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents) + { + memset (extents, 0, sizeof (*extents)); + return klass->get.f.font_v_extents (this, user_data, + extents, + klass->user_data.font_v_extents); + } + + inline bool has_glyph (hb_codepoint_t unicode) { hb_codepoint_t glyph; return get_glyph (unicode, 0, &glyph); @@ -154,85 +187,85 @@ hb_codepoint_t *glyph) { *glyph = 0; - return klass->get.glyph (this, user_data, - unicode, variation_selector, glyph, - klass->user_data.glyph); + return klass->get.f.glyph (this, user_data, + unicode, variation_selector, glyph, + klass->user_data.glyph); } inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) { - return klass->get.glyph_h_advance (this, user_data, - glyph, - klass->user_data.glyph_h_advance); + return klass->get.f.glyph_h_advance (this, user_data, + glyph, + klass->user_data.glyph_h_advance); } inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) { - return klass->get.glyph_v_advance (this, user_data, - glyph, - klass->user_data.glyph_v_advance); + return klass->get.f.glyph_v_advance (this, user_data, + glyph, + klass->user_data.glyph_v_advance); } inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y) { *x = *y = 0; - return klass->get.glyph_h_origin (this, user_data, - glyph, x, y, - klass->user_data.glyph_h_origin); + return klass->get.f.glyph_h_origin (this, user_data, + glyph, x, y, + klass->user_data.glyph_h_origin); } inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y) { *x = *y = 0; - return klass->get.glyph_v_origin (this, user_data, - glyph, x, y, - klass->user_data.glyph_v_origin); + return klass->get.f.glyph_v_origin (this, user_data, + glyph, x, y, + klass->user_data.glyph_v_origin); } inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) { - return klass->get.glyph_h_kerning (this, user_data, - left_glyph, right_glyph, - klass->user_data.glyph_h_kerning); + return klass->get.f.glyph_h_kerning (this, user_data, + left_glyph, right_glyph, + klass->user_data.glyph_h_kerning); } inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph) { - return klass->get.glyph_v_kerning (this, user_data, - top_glyph, bottom_glyph, - klass->user_data.glyph_v_kerning); + return klass->get.f.glyph_v_kerning (this, user_data, + top_glyph, bottom_glyph, + klass->user_data.glyph_v_kerning); } inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) { memset (extents, 0, sizeof (*extents)); - return klass->get.glyph_extents (this, user_data, - glyph, - extents, - klass->user_data.glyph_extents); + return klass->get.f.glyph_extents (this, user_data, + glyph, + extents, + klass->user_data.glyph_extents); } inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, hb_position_t *x, hb_position_t *y) { *x = *y = 0; - return klass->get.glyph_contour_point (this, user_data, - glyph, point_index, - x, y, - klass->user_data.glyph_contour_point); + return klass->get.f.glyph_contour_point (this, user_data, + glyph, point_index, + x, y, + klass->user_data.glyph_contour_point); } inline hb_bool_t get_glyph_name (hb_codepoint_t glyph, char *name, unsigned int size) { if (size) *name = '\0'; - return klass->get.glyph_name (this, user_data, - glyph, - name, size, - klass->user_data.glyph_name); + return klass->get.f.glyph_name (this, user_data, + glyph, + name, size, + klass->user_data.glyph_name); } inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ @@ -240,15 +273,35 @@ { *glyph = 0; if (len == -1) len = strlen (name); - return klass->get.glyph_from_name (this, user_data, - name, len, - glyph, - klass->user_data.glyph_from_name); + return klass->get.f.glyph_from_name (this, user_data, + name, len, + glyph, + klass->user_data.glyph_from_name); } /* A bit higher-level, and with fallback */ + inline void get_extents_for_direction (hb_direction_t direction, + hb_font_extents_t *extents) + { + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { + if (!get_font_h_extents (extents)) + { + extents->ascender = y_scale * .8; + extents->descender = y_scale - extents->ascender; + extents->line_gap = 0; + } + } else { + if (!get_font_v_extents (extents)) + { + extents->ascender = x_scale / 2; + extents->descender = x_scale - extents->ascender; + extents->line_gap = 0; + } + } + } + inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y) @@ -268,7 +321,7 @@ { *x = get_glyph_h_advance (glyph) / 2; - /* TODO use font_metics.ascent */ + /* TODO use font_extents.ascender */ *y = y_scale; } @@ -298,6 +351,26 @@ } } + inline void add_glyph_h_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_h_origin (glyph, &origin_x, &origin_y); + + *x += origin_x; + *y += origin_y; + } + inline void add_glyph_v_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_v_origin (glyph, &origin_x, &origin_y); + + *x += origin_x; + *y += origin_y; + } inline void add_glyph_origin_for_direction (hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y) @@ -310,6 +383,26 @@ *y += origin_y; } + inline void subtract_glyph_h_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_h_origin (glyph, &origin_x, &origin_y); + + *x -= origin_x; + *y -= origin_y; + } + inline void subtract_glyph_v_origin (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + hb_position_t origin_x, origin_y; + + get_glyph_v_origin (glyph, &origin_x, &origin_y); + + *x -= origin_x; + *y -= origin_y; + } inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y) diff -uN gfx/harfbuzz/src_old/hb-ft.cc gfx/harfbuzz/src/hb-ft.cc --- gfx/harfbuzz/src_old/hb-ft.cc 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-ft.cc 2016-06-05 23:48:50.916176399 +0200 @@ -1,6 +1,7 @@ /* * Copyright © 2009 Red Hat, Inc. * Copyright © 2009 Keith Stribley + * Copyright © 2015 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -23,6 +24,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod */ #include "hb-private.hh" @@ -46,10 +48,15 @@ * In general, this file does a fine job of what it's supposed to do. * There are, however, things that need more work: * - * - We don't handle any load_flags. That definitely has API implications. :( - * I believe hb_ft_font_create() should take load_flags input. - * In particular, FT_Get_Advance() without the NO_HINTING flag seems to be - * buggy. + * - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy. + * Have not investigated. + * + * - FreeType works in 26.6 mode. Clients can decide to use that mode, and everything + * would work fine. However, we also abuse this API for performing in font-space, + * but don't pass the correct flags to FreeType. We just abuse the no-hinting mode + * for that, such that no rounding etc happens. As such, we don't set ppem, and + * pass NO_HINTING as load_flags. Would be much better to use NO_SCALE, and scale + * ourselves, like we do in uniscribe, etc. * * - We don't handle / allow for emboldening / obliqueing. * @@ -59,6 +66,94 @@ */ +struct hb_ft_font_t +{ + FT_Face ft_face; + int load_flags; + bool unref; /* Whether to destroy ft_face when done. */ +}; + +static hb_ft_font_t * +_hb_ft_font_create (FT_Face ft_face, bool unref) +{ + hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); + + if (unlikely (!ft_font)) + return NULL; + + ft_font->ft_face = ft_face; + ft_font->unref = unref; + + ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; + + return ft_font; +} + +static void +_hb_ft_font_destroy (hb_ft_font_t *ft_font) +{ + if (ft_font->unref) + FT_Done_Face (ft_font->ft_face); + + free (ft_font); +} + +/** + * hb_ft_font_set_load_flags: + * @font: + * @load_flags: + * + * + * + * Since: 1.0.5 + **/ +void +hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) +{ + if (font->immutable) + return; + + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + return; + + hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; + + ft_font->load_flags = load_flags; +} + +/** + * hb_ft_font_get_load_flags: + * @font: + * + * + * + * Return value: + * Since: 1.0.5 + **/ +int +hb_ft_font_get_load_flags (hb_font_t *font) +{ + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + return 0; + + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; + + return ft_font->load_flags; +} + +FT_Face +hb_ft_font_get_face (hb_font_t *font) +{ + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + return NULL; + + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; + + return ft_font->ft_face; +} + + + static hb_bool_t hb_ft_get_glyph (hb_font_t *font HB_UNUSED, void *font_data, @@ -68,17 +163,19 @@ void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + unsigned int g; -#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX - if (unlikely (variation_selector)) { - *glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector); - return *glyph != 0; - } -#endif + if (likely (!variation_selector)) + g = FT_Get_Char_Index (ft_font->ft_face, unicode); + else + g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector); - *glyph = FT_Get_Char_Index (ft_face, unicode); - return *glyph != 0; + if (unlikely (!g)) + return false; + + *glyph = g; + return true; } static hb_position_t @@ -87,13 +184,15 @@ hb_codepoint_t glyph, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; FT_Fixed v; - if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) + if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v))) return 0; + if (font->x_scale < 0) + v = -v; + return (v + (1<<9)) >> 10; } @@ -103,31 +202,21 @@ hb_codepoint_t glyph, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOUT; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; FT_Fixed v; - if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) + if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v))) return 0; + if (font->y_scale < 0) + v = -v; + /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates * have a Y growing upward. Hence the extra negation. */ return (-v + (1<<9)) >> 10; } static hb_bool_t -hb_ft_get_glyph_h_origin (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t glyph HB_UNUSED, - hb_position_t *x HB_UNUSED, - hb_position_t *y HB_UNUSED, - void *user_data HB_UNUSED) -{ - /* We always work in the horizontal coordinates. */ - return true; -} - -static hb_bool_t hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, void *font_data, hb_codepoint_t glyph, @@ -135,10 +224,10 @@ hb_position_t *y, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; - if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) + if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) return false; /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates @@ -146,6 +235,11 @@ *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX; *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY); + if (font->x_scale < 0) + *x = -*x; + if (font->y_scale < 0) + *y = -*y; + return true; } @@ -156,27 +250,16 @@ hb_codepoint_t right_glyph, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; FT_Vector kerningv; FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED; - if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, mode, &kerningv)) + if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv)) return 0; return kerningv.x; } -static hb_position_t -hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t top_glyph HB_UNUSED, - hb_codepoint_t bottom_glyph HB_UNUSED, - void *user_data HB_UNUSED) -{ - /* FreeType API doesn't support vertical kerning */ - return 0; -} - static hb_bool_t hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED, void *font_data, @@ -184,16 +267,26 @@ hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; - if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) + if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) return false; extents->x_bearing = ft_face->glyph->metrics.horiBearingX; extents->y_bearing = ft_face->glyph->metrics.horiBearingY; extents->width = ft_face->glyph->metrics.width; extents->height = -ft_face->glyph->metrics.height; + if (font->x_scale < 0) + { + extents->x_bearing = -extents->x_bearing; + extents->width = -extents->width; + } + if (font->y_scale < 0) + { + extents->y_bearing = -extents->y_bearing; + extents->height = -extents->height; + } return true; } @@ -206,10 +299,10 @@ hb_position_t *y, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; - if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) + if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) return false; if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)) @@ -231,9 +324,9 @@ char *name, unsigned int size, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; - hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size); + hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size); if (ret && (size && !*name)) ret = false; @@ -247,7 +340,8 @@ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; if (len < 0) *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name); @@ -272,23 +366,76 @@ return *glyph != 0; } +static hb_bool_t +hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, + void *font_data, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) +{ + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; + metrics->ascender = ft_face->size->metrics.ascender; + metrics->descender = ft_face->size->metrics.descender; + metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender); + if (font->y_scale < 0) + { + metrics->ascender = -metrics->ascender; + metrics->descender = -metrics->descender; + metrics->line_gap = -metrics->line_gap; + } + return true; +} + +static hb_font_funcs_t *static_ft_funcs = NULL; + +#ifdef HB_USE_ATEXIT +static +void free_static_ft_funcs (void) +{ + hb_font_funcs_destroy (static_ft_funcs); +} +#endif -static hb_font_funcs_t * -_hb_ft_get_font_funcs (void) +static void +_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) { - static const hb_font_funcs_t ft_ffuncs = { - HB_OBJECT_HEADER_STATIC, +retry: + hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs); + + if (unlikely (!funcs)) + { + funcs = hb_font_funcs_create (); + + hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL); + //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL); + hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL); + hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL); + //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL); + hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL); + hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL); + //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL); + hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL); + hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL); + hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL); + hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, NULL, NULL); - true, /* immutable */ + hb_font_funcs_make_immutable (funcs); - { -#define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name, - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT + if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) { + hb_font_funcs_destroy (funcs); + goto retry; } + +#ifdef HB_USE_ATEXIT + atexit (free_static_ft_funcs); /* First person registers atexit() callback. */ +#endif }; - return const_cast (&ft_ffuncs); + hb_font_set_funcs (font, + funcs, + _hb_ft_font_create (ft_face, unref), + (hb_destroy_func_t) _hb_ft_font_destroy); } @@ -327,7 +474,7 @@ * * * Return value: (transfer full): - * Since: 1.0 + * Since: 0.9.2 **/ hb_face_t * hb_ft_face_create (FT_Face ft_face, @@ -340,11 +487,7 @@ blob = hb_blob_create ((const char *) ft_face->stream->base, (unsigned int) ft_face->stream->size, - /* TODO: We assume that it's mmap()'ed, but FreeType code - * suggests that there are cases we reach here but font is - * not mmapped. For example, when mmap() fails. No idea - * how to deal with it better here. */ - HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, + HB_MEMORY_MODE_READONLY, ft_face, destroy); face = hb_face_create (blob, ft_face->face_index); hb_blob_destroy (blob); @@ -358,6 +501,22 @@ return face; } +/** + * hb_ft_face_create_referenced: + * @ft_face: + * + * + * + * Return value: (transfer full): + * Since: 0.9.38 + **/ +hb_face_t * +hb_ft_face_create_referenced (FT_Face ft_face) +{ + FT_Reference_Face (ft_face); + return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face); +} + static void hb_ft_face_finalize (FT_Face ft_face) { @@ -371,7 +530,7 @@ * * * Return value: (transfer full): - * Since: 1.0 + * Since: 0.9.2 **/ hb_face_t * hb_ft_face_create_cached (FT_Face ft_face) @@ -388,11 +547,6 @@ return hb_face_reference ((hb_face_t *) ft_face->generic.data); } -static void -_do_nothing (void) -{ -} - /** * hb_ft_font_create: @@ -402,7 +556,7 @@ * * * Return value: (transfer full): - * Since: 1.0 + * Since: 0.9.2 **/ hb_font_t * hb_ft_font_create (FT_Face ft_face, @@ -414,29 +568,47 @@ face = hb_ft_face_create (ft_face, destroy); font = hb_font_create (face); hb_face_destroy (face); - hb_font_set_funcs (font, - _hb_ft_get_font_funcs (), - ft_face, (hb_destroy_func_t) _do_nothing); + _hb_ft_font_set_funcs (font, ft_face, false); hb_font_set_scale (font, (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16), (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16)); +#if 0 /* hb-ft works in no-hinting model */ hb_font_set_ppem (font, ft_face->size->metrics.x_ppem, ft_face->size->metrics.y_ppem); +#endif return font; } +/** + * hb_ft_font_create_referenced: + * @ft_face: + * + * + * + * Return value: (transfer full): + * Since: 0.9.38 + **/ +hb_font_t * +hb_ft_font_create_referenced (FT_Face ft_face) +{ + FT_Reference_Face (ft_face); + return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face); +} + /* Thread-safe, lock-free, FT_Library */ static FT_Library ft_library; -static inline +#ifdef HB_USE_ATEXIT +static void free_ft_library (void) { FT_Done_FreeType (ft_library); } +#endif static FT_Library get_ft_library (void) @@ -493,30 +665,23 @@ FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); - assert (font->y_scale >= 0); FT_Set_Char_Size (ft_face, - font->x_scale, font->y_scale, + abs (font->x_scale), abs (font->y_scale), 0, 0); #if 0 font->x_ppem * 72 * 64 / font->x_scale, font->y_ppem * 72 * 64 / font->y_scale); #endif + if (font->x_scale < 0 || font->y_scale < 0) + { + FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, + 0, font->y_scale < 0 ? -1 : +1}; + FT_Set_Transform (ft_face, &matrix, NULL); + } ft_face->generic.data = blob; ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; - hb_font_set_funcs (font, - _hb_ft_get_font_funcs (), - ft_face, - (hb_destroy_func_t) FT_Done_Face); -} - -FT_Face -hb_ft_font_get_face (hb_font_t *font) -{ - if (font->destroy == (hb_destroy_func_t) FT_Done_Face || - font->destroy == (hb_destroy_func_t) _do_nothing) - return (FT_Face) font->user_data; - - return NULL; + _hb_ft_font_set_funcs (font, ft_face, true); + hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); } diff -uN gfx/harfbuzz/src_old/hb-ft.h gfx/harfbuzz/src/hb-ft.h --- gfx/harfbuzz/src_old/hb-ft.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-ft.h 2016-06-05 23:48:52.044170188 +0200 @@ -1,5 +1,6 @@ /* * Copyright © 2009 Red Hat, Inc. + * Copyright © 2015 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -22,6 +23,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod */ #ifndef HB_FT_H @@ -34,28 +36,90 @@ HB_BEGIN_DECLS -/* Note: FreeType is not thread-safe. Hence, these functions are not either. */ +/* + * Note: FreeType is not thread-safe. + * Hence, these functions are not either. + */ -hb_face_t * +/* + * hb-face from ft-face. + */ + +/* This one creates a new hb-face for given ft-face. + * When the returned hb-face is destroyed, the destroy + * callback is called (if not NULL), with the ft-face passed + * to it. + * + * The client is responsible to make sure that ft-face is + * destroyed after hb-face is destroyed. + * + * Most often you don't want this function. You should use either + * hb_ft_face_create_cached(), or hb_ft_face_create_referenced(). + * In particular, if you are going to pass NULL as destroy, you + * probably should use (the more recent) hb_ft_face_create_referenced() + * instead. + */ +HB_EXTERN hb_face_t * hb_ft_face_create (FT_Face ft_face, hb_destroy_func_t destroy); -hb_face_t * +/* This version is like hb_ft_face_create(), except that it caches + * the hb-face using the generic pointer of the ft-face. This means + * that subsequent calls to this function with the same ft-face will + * return the same hb-face (correctly referenced). + * + * Client is still responsible for making sure that ft-face is destroyed + * after hb-face is. + */ +HB_EXTERN hb_face_t * hb_ft_face_create_cached (FT_Face ft_face); -hb_font_t * +/* This version is like hb_ft_face_create(), except that it calls + * FT_Reference_Face() on ft-face, as such keeping ft-face alive + * as long as the hb-face is. + * + * This is the most convenient version to use. Use it unless you have + * very good reasons not to. + */ +HB_EXTERN hb_face_t * +hb_ft_face_create_referenced (FT_Face ft_face); + + +/* + * hb-font from ft-face. + */ + +/* + * Note: + * + * Set face size on ft-face before creating hb-font from it. + * Otherwise hb-ft would NOT pick up the font size correctly. + */ + +/* See notes on hb_ft_face_create(). Same issues re lifecycle-management + * apply here. Use hb_ft_font_create_referenced() if you can. */ +HB_EXTERN hb_font_t * hb_ft_font_create (FT_Face ft_face, hb_destroy_func_t destroy); +/* See notes on hb_ft_face_create_referenced() re lifecycle-management + * issues. */ +HB_EXTERN hb_font_t * +hb_ft_font_create_referenced (FT_Face ft_face); + +HB_EXTERN FT_Face +hb_ft_font_get_face (hb_font_t *font); + +HB_EXTERN void +hb_ft_font_set_load_flags (hb_font_t *font, int load_flags); +HB_EXTERN int +hb_ft_font_get_load_flags (hb_font_t *font); /* Makes an hb_font_t use FreeType internally to implement font functions. */ -void +HB_EXTERN void hb_ft_font_set_funcs (hb_font_t *font); -FT_Face -hb_ft_font_get_face (hb_font_t *font); - HB_END_DECLS diff -uN gfx/harfbuzz/src_old/hb-glib.cc gfx/harfbuzz/src/hb-glib.cc --- gfx/harfbuzz/src_old/hb-glib.cc 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-glib.cc 2016-06-05 23:48:53.244163610 +0200 @@ -382,3 +382,19 @@ return const_cast (&_hb_glib_unicode_funcs); } +/** + * hb_glib_blob_create: + * + * Since: 0.9.38 + **/ +hb_blob_t * +hb_glib_blob_create (GBytes *gbytes) +{ + gsize size = 0; + gconstpointer data = g_bytes_get_data (gbytes, &size); + return hb_blob_create ((const char *) data, + size, + HB_MEMORY_MODE_READONLY, + g_bytes_ref (gbytes), + (hb_destroy_func_t) g_bytes_unref); +} diff -uN gfx/harfbuzz/src_old/hb-glib.h gfx/harfbuzz/src/hb-glib.h --- gfx/harfbuzz/src_old/hb-glib.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-glib.h 2016-06-05 23:48:54.401157255 +0200 @@ -36,16 +36,19 @@ HB_BEGIN_DECLS -hb_script_t +HB_EXTERN hb_script_t hb_glib_script_to_script (GUnicodeScript script); -GUnicodeScript +HB_EXTERN GUnicodeScript hb_glib_script_from_script (hb_script_t script); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_glib_get_unicode_funcs (void); +HB_EXTERN hb_blob_t * +hb_glib_blob_create (GBytes *gbytes); + HB_END_DECLS diff -uN gfx/harfbuzz/src_old/hb-gobject-enums.h.tmpl gfx/harfbuzz/src/hb-gobject-enums.h.tmpl --- gfx/harfbuzz/src_old/hb-gobject-enums.h.tmpl 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-gobject-enums.h.tmpl 2016-06-05 23:48:57.189141987 +0200 @@ -42,7 +42,7 @@ /*** END file-header ***/ /*** BEGIN value-header ***/ -GType @enum_name@_get_type (void) G_GNUC_CONST; +HB_EXTERN GType @enum_name@_get_type (void) G_GNUC_CONST; #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) /*** END value-header ***/ diff -uN gfx/harfbuzz/src_old/hb-gobject-structs.cc gfx/harfbuzz/src/hb-gobject-structs.cc --- gfx/harfbuzz/src_old/hb-gobject-structs.cc 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-gobject-structs.cc 2016-06-05 23:48:58.408135321 +0200 @@ -54,6 +54,17 @@ #define HB_DEFINE_OBJECT_TYPE(name) \ HB_DEFINE_BOXED_TYPE (name, hb_##name##_reference, hb_##name##_destroy); +#define HB_DEFINE_VALUE_TYPE(name) \ + static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \ + { \ + hb_##name##_t *c = (hb_##name##_t *) calloc (1, sizeof (hb_##name##_t)); \ + if (unlikely (!c)) return NULL; \ + *c = *l; \ + return c; \ + } \ + static void _hb_##name##_destroy (hb_##name##_t *l) { free (l); } \ + HB_DEFINE_BOXED_TYPE (name, _hb_##name##_reference, _hb_##name##_destroy); + HB_DEFINE_OBJECT_TYPE (buffer) HB_DEFINE_OBJECT_TYPE (blob) HB_DEFINE_OBJECT_TYPE (face) @@ -62,59 +73,8 @@ HB_DEFINE_OBJECT_TYPE (set) HB_DEFINE_OBJECT_TYPE (shape_plan) HB_DEFINE_OBJECT_TYPE (unicode_funcs) - - -static hb_feature_t *feature_reference (hb_feature_t *g) -{ - hb_feature_t *c = (hb_feature_t *) calloc (1, sizeof (hb_feature_t)); - if (unlikely (!c)) return NULL; - *c = *g; - return c; -} -static void feature_destroy (hb_feature_t *g) { free (g); } -HB_DEFINE_BOXED_TYPE (feature, feature_reference, feature_destroy) - -static hb_glyph_info_t *glyph_info_reference (hb_glyph_info_t *g) -{ - hb_glyph_info_t *c = (hb_glyph_info_t *) calloc (1, sizeof (hb_glyph_info_t)); - if (unlikely (!c)) return NULL; - *c = *g; - return c; -} -static void glyph_info_destroy (hb_glyph_info_t *g) { free (g); } -HB_DEFINE_BOXED_TYPE (glyph_info, glyph_info_reference, glyph_info_destroy) - -static hb_glyph_position_t *glyph_position_reference (hb_glyph_position_t *g) -{ - hb_glyph_position_t *c = (hb_glyph_position_t *) calloc (1, sizeof (hb_glyph_position_t)); - if (unlikely (!c)) return NULL; - *c = *g; - return c; -} -static void glyph_position_destroy (hb_glyph_position_t *g) { free (g); } -HB_DEFINE_BOXED_TYPE (glyph_position, glyph_position_reference, glyph_position_destroy) - -static hb_segment_properties_t *segment_properties_reference (hb_segment_properties_t *g) -{ - hb_segment_properties_t *c = (hb_segment_properties_t *) calloc (1, sizeof (hb_segment_properties_t)); - if (unlikely (!c)) return NULL; - *c = *g; - return c; -} -static void segment_properties_destroy (hb_segment_properties_t *g) { free (g); } -HB_DEFINE_BOXED_TYPE (segment_properties, segment_properties_reference, segment_properties_destroy) - -static hb_user_data_key_t user_data_key_reference (hb_user_data_key_t l) { return l; } -static void user_data_key_destroy (hb_user_data_key_t l) { } -HB_DEFINE_BOXED_TYPE (user_data_key, user_data_key_reference, user_data_key_destroy) - - -static hb_language_t *language_reference (hb_language_t *l) -{ - hb_language_t *c = (hb_language_t *) calloc (1, sizeof (hb_language_t)); - if (unlikely (!c)) return NULL; - *c = *l; - return c; -} -static void language_destroy (hb_language_t *l) { free (l); } -HB_DEFINE_BOXED_TYPE (language, language_reference, language_destroy) +HB_DEFINE_VALUE_TYPE (feature) +HB_DEFINE_VALUE_TYPE (glyph_info) +HB_DEFINE_VALUE_TYPE (glyph_position) +HB_DEFINE_VALUE_TYPE (segment_properties) +HB_DEFINE_VALUE_TYPE (user_data_key) diff -uN gfx/harfbuzz/src_old/hb-gobject-structs.h gfx/harfbuzz/src/hb-gobject-structs.h --- gfx/harfbuzz/src_old/hb-gobject-structs.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-gobject-structs.h 2016-06-05 23:48:59.577128929 +0200 @@ -40,55 +40,65 @@ /* Object types */ -GType hb_gobject_blob_get_type (void); +/** + * Since: 0.9.2 + **/ +HB_EXTERN GType hb_gobject_blob_get_type (void); #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ()) -GType hb_gobject_buffer_get_type (void); +/** + * Since: 0.9.2 + **/ +HB_EXTERN GType hb_gobject_buffer_get_type (void); #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ()) -GType hb_gobject_face_get_type (void); +/** + * Since: 0.9.2 + **/ +HB_EXTERN GType hb_gobject_face_get_type (void); #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ()) -GType hb_gobject_font_get_type (void); +/** + * Since: 0.9.2 + **/ +HB_EXTERN GType hb_gobject_font_get_type (void); #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ()) -GType hb_gobject_font_funcs_get_type (void); +/** + * Since: 0.9.2 + **/ +HB_EXTERN GType hb_gobject_font_funcs_get_type (void); #define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ()) -GType hb_gobject_set_get_type (void); +HB_EXTERN GType hb_gobject_set_get_type (void); #define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ()) -GType hb_gobject_shape_plan_get_type (void); +HB_EXTERN GType hb_gobject_shape_plan_get_type (void); #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ()) -GType hb_gobject_unicode_funcs_get_type (void); +/** + * Since: 0.9.2 + **/ +HB_EXTERN GType hb_gobject_unicode_funcs_get_type (void); #define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ()) /* Value types */ -GType hb_gobject_feature_get_type (void); +HB_EXTERN GType hb_gobject_feature_get_type (void); #define HB_GOBJECT_TYPE_FEATURE (hb_gobject_feature_get_type ()) -GType hb_gobject_glyph_info_get_type (void); +HB_EXTERN GType hb_gobject_glyph_info_get_type (void); #define HB_GOBJECT_TYPE_GLYPH_INFO (hb_gobject_glyph_info_get_type ()) -GType hb_gobject_glyph_position_get_type (void); +HB_EXTERN GType hb_gobject_glyph_position_get_type (void); #define HB_GOBJECT_TYPE_GLYPH_POSITION (hb_gobject_glyph_position_get_type ()) -GType hb_gobject_segment_properties_get_type (void); +HB_EXTERN GType hb_gobject_segment_properties_get_type (void); #define HB_GOBJECT_TYPE_SEGMENT_PROPERTIES (hb_gobject_segment_properties_get_type ()) -GType hb_gobject_user_data_key_get_type (void); +HB_EXTERN GType hb_gobject_user_data_key_get_type (void); #define HB_GOBJECT_TYPE_USER_DATA_KEY (hb_gobject_user_data_key_get_type ()) -/* Currently gobject-introspection doesn't understand that hb_language_t - * can be passed by-value. As such we box it up. May remove in the - * future. - * - * https://bugzilla.gnome.org/show_bug.cgi?id=707656 - */ -GType hb_gobject_language_get_type (void); -#define HB_GOBJECT_TYPE_LANGUAGE (hb_gobject_language_get_type ()) HB_END_DECLS diff -uN gfx/harfbuzz/src_old/hb-graphite2.cc gfx/harfbuzz/src/hb-graphite2.cc --- gfx/harfbuzz/src_old/hb-graphite2.cc 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-graphite2.cc 2016-06-05 23:49:01.899116257 +0200 @@ -138,6 +138,9 @@ free (data); } +/* + * Since: 0.9.10 + */ gr_face * hb_graphite2_face_get_gr_face (hb_face_t *face) { @@ -172,6 +175,9 @@ gr_font_destroy (data); } +/* + * Since: 0.9.10 + */ gr_font * hb_graphite2_font_get_gr_font (hb_font_t *font) { @@ -228,12 +234,11 @@ int lang_len = lang_end ? lang_end - lang : -1; gr_feature_val *feats = gr_face_featureval_for_lang (grface, lang ? hb_tag_from_string (lang, lang_len) : 0); - while (num_features--) + for (unsigned int i = 0; i < num_features; i++) { - const gr_feature_ref *fref = gr_face_find_fref (grface, features->tag); + const gr_feature_ref *fref = gr_face_find_fref (grface, features[i].tag); if (fref) - gr_fref_set_feature_value (fref, features->value, feats); - features++; + gr_fref_set_feature_value (fref, features[i].value, feats); } gr_segment *seg = NULL; @@ -249,6 +254,8 @@ for (unsigned int i = 0; i < buffer->len; ++i) chars[i] = buffer->info[i].codepoint; + /* TODO ensure_native_direction. */ + hb_tag_t script_tag[2]; hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]); @@ -267,9 +274,11 @@ if (unlikely (!glyph_count)) { if (feats) gr_featureval_destroy (feats); gr_seg_destroy (seg); - return false; + buffer->len = 0; + return true; } + buffer->ensure (glyph_count); scratch = buffer->get_scratch_buffer (&scratch_size); while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) + DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size) @@ -331,7 +340,6 @@ } ci++; - //buffer->clear_output (); for (unsigned int i = 0; i < ci; ++i) { for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j) @@ -342,32 +350,58 @@ } } buffer->len = glyph_count; - //buffer->swap_buffers (); - - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) - curradvx = gr_seg_advance_X(seg); - hb_glyph_position_t *pPos; - for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg); - is; pPos++, is = gr_slot_next_in_segment (is)) - { - pPos->x_offset = gr_slot_origin_X (is) - curradvx; - pPos->y_offset = gr_slot_origin_Y (is) - curradvy; - pPos->x_advance = gr_slot_advance_X (is, grface, grfont); - pPos->y_advance = gr_slot_advance_Y (is, grface, grfont); - if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) - curradvx -= pPos->x_advance; - pPos->x_offset = gr_slot_origin_X (is) - curradvx; - if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + float yscale = font->y_scale / font->x_scale; + /* Positioning. */ + if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + { + hb_glyph_position_t *pPos; + for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg); + is; pPos++, is = gr_slot_next_in_segment (is)) + { + pPos->x_offset = gr_slot_origin_X (is) - curradvx; + pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; + pPos->x_advance = gr_slot_advance_X (is, grface, grfont); + pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; curradvx += pPos->x_advance; - pPos->y_offset = gr_slot_origin_Y (is) - curradvy; - curradvy += pPos->y_advance; - } - if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + curradvy += pPos->y_advance; + } pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx; - - if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) + } + else + { + hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL) + buffer->len - 1; + const hb_glyph_info_t *info = buffer->info + buffer->len - 1; + const hb_glyph_info_t *tinfo; + const gr_slot *tis; + int currclus = -1; + float clusx = 0., clusy = 0.; + for (is = gr_seg_last_slot (seg); is; pPos--, info--, is = gr_slot_prev_in_segment (is)) + { + if (info->cluster != currclus) + { + curradvx += clusx; + curradvy += clusy; + currclus = info->cluster; + clusx = 0.; + clusy = 0.; + for (tis = is, tinfo = info; tis && tinfo->cluster == currclus; tis = gr_slot_prev_in_segment (tis), tinfo--) + { + clusx += gr_slot_advance_X (tis, grface, grfont); + clusy += gr_slot_advance_Y (tis, grface, grfont) * yscale; + } + curradvx += clusx; + curradvy += clusy; + } + pPos->x_advance = gr_slot_advance_X (is, grface, grfont); + pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; + curradvx -= pPos->x_advance; + curradvy -= pPos->y_advance; + pPos->x_offset = gr_slot_origin_X (is) - curradvx; + pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; + } hb_buffer_reverse_clusters (buffer); + } if (feats) gr_featureval_destroy (feats); gr_seg_destroy (seg); diff -uN gfx/harfbuzz/src_old/hb-graphite2.h gfx/harfbuzz/src/hb-graphite2.h --- gfx/harfbuzz/src_old/hb-graphite2.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-graphite2.h 2016-06-05 23:49:03.057109946 +0200 @@ -36,10 +36,10 @@ #define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f') -gr_face * +HB_EXTERN gr_face * hb_graphite2_face_get_gr_face (hb_face_t *face); -gr_font * +HB_EXTERN gr_font * hb_graphite2_font_get_gr_font (hb_font_t *font); diff -uN gfx/harfbuzz/src_old/hb.h gfx/harfbuzz/src/hb.h --- gfx/harfbuzz/src_old/hb.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb.h 2016-06-05 23:50:56.057516793 +0200 @@ -28,6 +28,10 @@ #define HB_H #define HB_H_IN +#ifndef HB_EXTERN +#define HB_EXTERN extern +#endif + #include "hb-blob.h" #include "hb-buffer.h" #include "hb-common.h" diff -uN gfx/harfbuzz/src_old/hb-icu.cc gfx/harfbuzz/src/hb-icu.cc --- gfx/harfbuzz/src_old/hb-icu.cc 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-icu.cc 2016-06-05 23:49:04.387102711 +0200 @@ -363,10 +363,8 @@ if (!hb_atomic_ptr_get (&normalizer)) { UErrorCode icu_err = U_ZERO_ERROR; /* We ignore failure in getNFCInstace(). */ - hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err)); + (void) hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err)); } #endif return const_cast (&_hb_icu_unicode_funcs); } - - diff -uN gfx/harfbuzz/src_old/hb-icu.h gfx/harfbuzz/src/hb-icu.h --- gfx/harfbuzz/src_old/hb-icu.h 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-icu.h 2016-06-05 23:49:05.565096299 +0200 @@ -36,14 +36,14 @@ HB_BEGIN_DECLS -hb_script_t +HB_EXTERN hb_script_t hb_icu_script_to_script (UScriptCode script); -UScriptCode +HB_EXTERN UScriptCode hb_icu_script_from_script (hb_script_t script); -hb_unicode_funcs_t * +HB_EXTERN hb_unicode_funcs_t * hb_icu_get_unicode_funcs (void); diff -uN gfx/harfbuzz/src_old/hb-mutex-private.hh gfx/harfbuzz/src/hb-mutex-private.hh --- gfx/harfbuzz/src_old/hb-mutex-private.hh 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-mutex-private.hh 2016-06-05 23:49:06.735089929 +0200 @@ -39,7 +39,13 @@ /* We need external help for these */ -#if 0 +#if defined(HB_MUTEX_IMPL_INIT) \ + && defined(hb_mutex_impl_init) \ + && defined(hb_mutex_impl_lock) \ + && defined(hb_mutex_impl_unlock) \ + && defined(hb_mutex_impl_finish) + +/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */ #elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) @@ -47,7 +53,11 @@ #include typedef CRITICAL_SECTION hb_mutex_impl_t; #define HB_MUTEX_IMPL_INIT {0} +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0) +#else #define hb_mutex_impl_init(M) InitializeCriticalSection (M) +#endif #define hb_mutex_impl_lock(M) EnterCriticalSection (M) #define hb_mutex_impl_unlock(M) LeaveCriticalSection (M) #define hb_mutex_impl_finish(M) DeleteCriticalSection (M) @@ -109,10 +119,12 @@ #define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END #define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END + #endif #define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT} + struct hb_mutex_t { /* TODO Add tracing. */ diff -uN gfx/harfbuzz/src_old/hb-object-private.hh gfx/harfbuzz/src/hb-object-private.hh --- gfx/harfbuzz/src_old/hb-object-private.hh 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-object-private.hh 2016-06-05 23:49:07.940083385 +0200 @@ -47,19 +47,22 @@ /* reference_count */ -#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1) -#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE} +#define HB_REFERENCE_COUNT_INERT_VALUE -1 +#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD +#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT(HB_REFERENCE_COUNT_INERT_VALUE)} + struct hb_reference_count_t { hb_atomic_int_t ref_count; - inline void init (int v) { ref_count = v; } - inline int inc (void) { return hb_atomic_int_add (const_cast (ref_count), 1); } - inline int dec (void) { return hb_atomic_int_add (const_cast (ref_count), -1); } - inline void finish (void) { ref_count = HB_REFERENCE_COUNT_INVALID_VALUE; } - - inline bool is_invalid (void) const { return ref_count == HB_REFERENCE_COUNT_INVALID_VALUE; } + inline void init (int v) { ref_count.set_unsafe (v); } + inline int get_unsafe (void) const { return ref_count.get_unsafe (); } + inline int inc (void) { return ref_count.inc (); } + inline int dec (void) { return ref_count.dec (); } + inline void finish (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); } + inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; } + inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; } }; @@ -102,7 +105,7 @@ hb_reference_count_t ref_count; hb_user_data_array_t user_data; -#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID, HB_USER_DATA_ARRAY_INIT} +#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_USER_DATA_ARRAY_INIT} private: ASSERT_POD (); @@ -117,7 +120,7 @@ DEBUG_MSG (OBJECT, (void *) obj, "%s refcount=%d", function, - obj ? obj->header.ref_count.ref_count : 0); + obj ? obj->header.ref_count.get_unsafe () : 0); } template @@ -141,7 +144,12 @@ template static inline bool hb_object_is_inert (const Type *obj) { - return unlikely (obj->header.ref_count.is_invalid ()); + return unlikely (obj->header.ref_count.is_inert ()); +} +template +static inline bool hb_object_is_valid (const Type *obj) +{ + return likely (obj->header.ref_count.is_valid ()); } template static inline Type *hb_object_reference (Type *obj) @@ -149,6 +157,7 @@ hb_object_trace (obj, HB_FUNC); if (unlikely (!obj || hb_object_is_inert (obj))) return obj; + assert (hb_object_is_valid (obj)); obj->header.ref_count.inc (); return obj; } @@ -158,6 +167,7 @@ hb_object_trace (obj, HB_FUNC); if (unlikely (!obj || hb_object_is_inert (obj))) return false; + assert (hb_object_is_valid (obj)); if (obj->header.ref_count.dec () != 1) return false; @@ -174,6 +184,7 @@ { if (unlikely (!obj || hb_object_is_inert (obj))) return false; + assert (hb_object_is_valid (obj)); return obj->header.user_data.set (key, data, destroy, replace); } @@ -183,6 +194,7 @@ { if (unlikely (!obj || hb_object_is_inert (obj))) return NULL; + assert (hb_object_is_valid (obj)); return obj->header.user_data.get (key); } diff -uN gfx/harfbuzz/src_old/hb-open-file-private.hh gfx/harfbuzz/src/hb-open-file-private.hh --- gfx/harfbuzz/src_old/hb-open-file-private.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-open-file-private.hh 2016-06-05 23:49:09.207076516 +0200 @@ -53,9 +53,10 @@ typedef struct TableRecord { - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this)); + return_trace (c->check_struct (this)); } Tag tag; /* 4-byte identifier. */ @@ -102,9 +103,10 @@ } public: - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables)); + return_trace (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables)); } protected: @@ -130,9 +132,10 @@ inline unsigned int get_face_count (void) const { return table.len; } inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (table.sanitize (c, this)); + return_trace (table.sanitize (c, this)); } protected: @@ -169,13 +172,14 @@ } } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false); + if (unlikely (!u.header.version.sanitize (c))) return_trace (false); switch (u.header.version.major) { case 2: /* version 2 is compatible with version 1 */ - case 1: return TRACE_RETURN (u.version1.sanitize (c)); - default:return TRACE_RETURN (true); + case 1: return_trace (u.version1.sanitize (c)); + default:return_trace (true); } } @@ -233,16 +237,17 @@ } } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false); + if (unlikely (!u.tag.sanitize (c))) return_trace (false); switch (u.tag) { case CFFTag: /* All the non-collection tags */ case TrueTag: case Typ1Tag: - case TrueTypeTag: return TRACE_RETURN (u.fontFace.sanitize (c)); - case TTCTag: return TRACE_RETURN (u.ttcHeader.sanitize (c)); - default: return TRACE_RETURN (true); + case TrueTypeTag: return_trace (u.fontFace.sanitize (c)); + case TTCTag: return_trace (u.ttcHeader.sanitize (c)); + default: return_trace (true); } } diff -uN gfx/harfbuzz/src_old/hb-open-type-private.hh gfx/harfbuzz/src/hb-open-type-private.hh --- gfx/harfbuzz/src_old/hb-open-type-private.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-open-type-private.hh 2016-06-05 23:49:10.574069085 +0200 @@ -103,9 +103,6 @@ static const unsigned int static_size = (size); \ static const unsigned int min_size = (size) -/* Size signifying variable-sized array */ -#define VAR 1 - #define DEFINE_SIZE_UNION(size, _member) \ DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ static const unsigned int min_size = (size) @@ -154,6 +151,20 @@ #define Null(Type) Null() +/* + * Dispatch + */ + +template +struct hb_dispatch_context_t +{ + static const unsigned int max_debug_depth = MaxDebugDepth; + typedef Return return_t; + template + inline bool may_dispatch (const T *obj, const F *format) { return true; } + static return_t no_dispatch_return_value (void) { return Context::default_return_value (); } +}; + /* * Sanitize @@ -171,18 +182,27 @@ /* This limits sanitizing time on really broken fonts. */ #ifndef HB_SANITIZE_MAX_EDITS -#define HB_SANITIZE_MAX_EDITS 100 +#define HB_SANITIZE_MAX_EDITS 32 #endif -struct hb_sanitize_context_t +struct hb_sanitize_context_t : + hb_dispatch_context_t { + inline hb_sanitize_context_t (void) : + debug_depth (0), + start (NULL), end (NULL), + writable (false), edit_count (0), + blob (NULL) {} + inline const char *get_name (void) { return "SANITIZE"; } - static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; - typedef bool return_t; + template + inline bool may_dispatch (const T *obj, const F *format) + { return format->sanitize (this); } template inline return_t dispatch (const T &obj) { return obj.sanitize (this); } static return_t default_return_value (void) { return true; } - bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } + static return_t no_dispatch_return_value (void) { return false; } + bool stop_sublookup_iteration (const return_t r) const { return !r; } inline void init (hb_blob_t *b) { @@ -270,9 +290,9 @@ } template - inline bool try_set (Type *obj, const ValueType &v) { + inline bool try_set (const Type *obj, const ValueType &v) { if (this->may_edit (obj, obj->static_size)) { - obj->set (v); + const_cast (obj)->set (v); return true; } return false; @@ -292,7 +312,7 @@ struct Sanitizer { static hb_blob_t *sanitize (hb_blob_t *blob) { - hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}}; + hb_sanitize_context_t c[1]; bool sane; /* TODO is_sane() stuff */ @@ -376,9 +396,9 @@ struct hb_serialize_context_t { - inline hb_serialize_context_t (void *start, unsigned int size) + inline hb_serialize_context_t (void *start_, unsigned int size) { - this->start = (char *) start; + this->start = (char *) start_; this->end = this->start + size; this->ran_out_of_room = false; @@ -472,10 +492,10 @@ return reinterpret_cast (&obj); } - inline void truncate (void *head) + inline void truncate (void *new_head) { - assert (this->start < head && head <= this->head); - this->head = (char *) head; + assert (this->start < new_head && new_head <= this->head); + this->head = (char *) new_head; } unsigned int debug_depth; @@ -533,6 +553,20 @@ template struct BEInt; template +struct BEInt +{ + public: + inline void set (Type V) + { + v = V; + } + inline operator Type (void) const + { + return v; + } + private: uint8_t v; +}; +template struct BEInt { public: @@ -546,12 +580,6 @@ return (v[0] << 8) + (v[1] ); } - inline bool operator == (const BEInt& o) const - { - return v[0] == o.v[0] - && v[1] == o.v[1]; - } - inline bool operator != (const BEInt& o) const { return !(*this == o); } private: uint8_t v[2]; }; template @@ -570,13 +598,6 @@ + (v[1] << 8) + (v[2] ); } - inline bool operator == (const BEInt& o) const - { - return v[0] == o.v[0] - && v[1] == o.v[1] - && v[2] == o.v[2]; - } - inline bool operator != (const BEInt& o) const { return !(*this == o); } private: uint8_t v[3]; }; template @@ -597,14 +618,6 @@ + (v[2] << 8) + (v[3] ); } - inline bool operator == (const BEInt& o) const - { - return v[0] == o.v[0] - && v[1] == o.v[1] - && v[2] == o.v[2] - && v[3] == o.v[3]; - } - inline bool operator != (const BEInt& o) const { return !(*this == o); } private: uint8_t v[4]; }; @@ -614,14 +627,21 @@ { inline void set (Type i) { v.set (i); } inline operator Type(void) const { return v; } - inline bool operator == (const IntType &o) const { return v == o.v; } - inline bool operator != (const IntType &o) const { return v != o.v; } + inline bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } + inline bool operator != (const IntType &o) const { return !(*this == o); } static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } - inline int cmp (IntType va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } - inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline int cmp (Type a) const + { + Type b = v; + if (sizeof (Type) < sizeof (int)) + return (int) a - (int) b; + else + return a < b ? -1 : a == b ? 0 : +1; + } + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (likely (c->check_struct (this))); + return_trace (likely (c->check_struct (this))); } protected: BEInt v; @@ -629,7 +649,7 @@ DEFINE_SIZE_STATIC (Size); }; -typedef uint8_t BYTE; /* 8-bit unsigned integer. */ +typedef IntType BYTE; /* 8-bit unsigned integer. */ typedef IntType USHORT; /* 16-bit unsigned integer. */ typedef IntType SHORT; /* 16-bit signed integer. */ typedef IntType ULONG; /* 32-bit unsigned integer. */ @@ -646,9 +666,10 @@ * 1904. The value is represented as a signed 64-bit integer. */ struct LONGDATETIME { - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (likely (c->check_struct (this))); + return_trace (likely (c->check_struct (this))); } protected: LONG major; @@ -670,7 +691,10 @@ DEFINE_NULL_DATA (Tag, " "); /* Glyph index number, same as uint16 (length = 16 bits) */ -typedef USHORT GlyphID; +struct GlyphID : USHORT { + static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); } + inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; } +}; /* Script/language-system/feature index */ struct Index : USHORT { @@ -719,9 +743,10 @@ { inline uint32_t to_int (void) const { return (major << 16) + minor; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this)); + return_trace (c->check_struct (this)); } USHORT major; @@ -747,33 +772,35 @@ return StructAtOffset (base, offset); } - inline Type& serialize (hb_serialize_context_t *c, void *base) + inline Type& serialize (hb_serialize_context_t *c, const void *base) { Type *t = c->start_embed (); this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ return *t; } - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); + if (unlikely (!c->check_struct (this))) return_trace (false); unsigned int offset = *this; - if (unlikely (!offset)) return TRACE_RETURN (true); - Type &obj = StructAtOffset (base, offset); - return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); + if (unlikely (!offset)) return_trace (true); + const Type &obj = StructAtOffset (base, offset); + return_trace (likely (obj.sanitize (c)) || neuter (c)); } template - inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const + { TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); + if (unlikely (!c->check_struct (this))) return_trace (false); unsigned int offset = *this; - if (unlikely (!offset)) return TRACE_RETURN (true); - Type &obj = StructAtOffset (base, offset); - return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); + if (unlikely (!offset)) return_trace (true); + const Type &obj = StructAtOffset (base, offset); + return_trace (likely (obj.sanitize (c, user_data)) || neuter (c)); } /* Set the offset to Null */ - inline bool neuter (hb_sanitize_context_t *c) { + inline bool neuter (hb_sanitize_context_t *c) const { return c->try_set (this, 0); } DEFINE_SIZE_STATIC (sizeof(OffsetType)); @@ -820,10 +847,10 @@ unsigned int items_len) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!c->extend_min (*this))) return_trace (false); len.set (items_len); /* TODO(serialize) Overflow? */ - if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); - return TRACE_RETURN (true); + if (unlikely (!c->extend (*this))) return_trace (false); + return_trace (true); } inline bool serialize (hb_serialize_context_t *c, @@ -831,16 +858,17 @@ unsigned int items_len) { TRACE_SERIALIZE (this); - if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); + if (unlikely (!serialize (c, items_len))) return_trace (false); for (unsigned int i = 0; i < items_len; i++) array[i] = items[i]; items.advance (items_len); - return TRACE_RETURN (true); + return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + if (unlikely (!sanitize_shallow (c))) return_trace (false); /* Note: for structs that do not reference other structs, * we do not need to call their sanitize() as we already did @@ -851,26 +879,28 @@ */ (void) (false && array[0].sanitize (c)); - return TRACE_RETURN (true); + return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + if (unlikely (!sanitize_shallow (c))) return_trace (false); unsigned int count = len; for (unsigned int i = 0; i < count; i++) if (unlikely (!array[i].sanitize (c, base))) - return TRACE_RETURN (false); - return TRACE_RETURN (true); + return_trace (false); + return_trace (true); } template - inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const + { TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + if (unlikely (!sanitize_shallow (c))) return_trace (false); unsigned int count = len; for (unsigned int i = 0; i < count; i++) if (unlikely (!array[i].sanitize (c, base, user_data))) - return TRACE_RETURN (false); - return TRACE_RETURN (true); + return_trace (false); + return_trace (true); } template @@ -884,9 +914,10 @@ } private: - inline bool sanitize_shallow (hb_sanitize_context_t *c) { + inline bool sanitize_shallow (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); + return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len)); } public: @@ -910,14 +941,16 @@ return this+this->array[i]; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (OffsetArrayOf::sanitize (c, this)); + return_trace (OffsetArrayOf::sanitize (c, this)); } template - inline bool sanitize (hb_sanitize_context_t *c, T user_data) { + inline bool sanitize (hb_sanitize_context_t *c, T user_data) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (OffsetArrayOf::sanitize (c, this, user_data)); + return_trace (OffsetArrayOf::sanitize (c, this, user_data)); } }; @@ -939,24 +972,26 @@ unsigned int items_len) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); + if (unlikely (!c->extend_min (*this))) return_trace (false); len.set (items_len); /* TODO(serialize) Overflow? */ - if (unlikely (!items_len)) return TRACE_RETURN (true); - if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); + if (unlikely (!items_len)) return_trace (true); + if (unlikely (!c->extend (*this))) return_trace (false); for (unsigned int i = 0; i < items_len - 1; i++) array[i] = items[i]; items.advance (items_len - 1); - return TRACE_RETURN (true); + return_trace (true); } - inline bool sanitize_shallow (hb_sanitize_context_t *c) { + inline bool sanitize_shallow (hb_sanitize_context_t *c) const + { return c->check_struct (this) && c->check_array (this, Type::static_size, len); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); + if (unlikely (!sanitize_shallow (c))) return_trace (false); /* Note: for structs that do not reference other structs, * we do not need to call their sanitize() as we already did @@ -967,7 +1002,7 @@ */ (void) (false && array[0].sanitize (c)); - return TRACE_RETURN (true); + return_trace (true); } LenType len; diff -uN gfx/harfbuzz/src_old/hb-ot-cmap-table.hh gfx/harfbuzz/src/hb-ot-cmap-table.hh --- gfx/harfbuzz/src_old/hb-ot-cmap-table.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-ot-cmap-table.hh 2016-06-05 23:49:11.982061464 +0200 @@ -51,9 +51,10 @@ return true; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this)); + return_trace (c->check_struct (this)); } protected: @@ -125,11 +126,11 @@ return true; } - inline bool sanitize (hb_sanitize_context_t *c) + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) - return TRACE_RETURN (false); + return_trace (false); if (unlikely (!c->check_range (this, length))) { @@ -140,10 +141,10 @@ (uintptr_t) (c->end - (char *) this)); if (!c->try_set (&length, new_length)) - return TRACE_RETURN (false); + return_trace (false); } - return TRACE_RETURN (16 + 4 * (unsigned int) segCountX2 <= length); + return_trace (16 + 4 * (unsigned int) segCountX2 <= length); } protected: @@ -183,9 +184,10 @@ return 0; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this)); + return_trace (c->check_struct (this)); } private: @@ -210,9 +212,10 @@ return true; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c)); + return_trace (c->check_struct (this) && glyphIdArray.sanitize (c)); } protected: @@ -242,9 +245,10 @@ return true; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c)); + return_trace (c->check_struct (this) && groups.sanitize (c)); } protected: @@ -288,9 +292,10 @@ return 0; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this)); + return_trace (c->check_struct (this)); } UINT24 startUnicodeValue; /* First value in this range. */ @@ -309,9 +314,10 @@ return unicodeValue.cmp (codepoint); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this)); + return_trace (c->check_struct (this)); } UINT24 unicodeValue; /* Base Unicode value of the UVS */ @@ -348,11 +354,12 @@ return varSelector.cmp (variation_selector); } - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && - defaultUVS.sanitize (c, base) && - nonDefaultUVS.sanitize (c, base)); + return_trace (c->check_struct (this) && + defaultUVS.sanitize (c, base) && + nonDefaultUVS.sanitize (c, base)); } UINT24 varSelector; /* Variation selector. */ @@ -373,10 +380,11 @@ return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && - record.sanitize (c, this)); + return_trace (c->check_struct (this) && + record.sanitize (c, this)); } protected: @@ -418,18 +426,19 @@ } } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - if (!u.format.sanitize (c)) return TRACE_RETURN (false); + if (!u.format.sanitize (c)) return_trace (false); switch (u.format) { - case 0: return TRACE_RETURN (u.format0 .sanitize (c)); - case 4: return TRACE_RETURN (u.format4 .sanitize (c)); - case 6: return TRACE_RETURN (u.format6 .sanitize (c)); - case 10: return TRACE_RETURN (u.format10.sanitize (c)); - case 12: return TRACE_RETURN (u.format12.sanitize (c)); - case 13: return TRACE_RETURN (u.format13.sanitize (c)); - case 14: return TRACE_RETURN (u.format14.sanitize (c)); - default:return TRACE_RETURN (true); + case 0: return_trace (u.format0 .sanitize (c)); + case 4: return_trace (u.format4 .sanitize (c)); + case 6: return_trace (u.format6 .sanitize (c)); + case 10: return_trace (u.format10.sanitize (c)); + case 12: return_trace (u.format12.sanitize (c)); + case 13: return_trace (u.format13.sanitize (c)); + case 14: return_trace (u.format14.sanitize (c)); + default:return_trace (true); } } @@ -461,10 +470,11 @@ return 0; } - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && - subtable.sanitize (c, base)); + return_trace (c->check_struct (this) && + subtable.sanitize (c, base)); } USHORT platformID; /* Platform ID. */ @@ -496,11 +506,12 @@ return &(this+encodingRecord[result].subtable); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && - likely (version == 0) && - encodingRecord.sanitize (c, this)); + return_trace (c->check_struct (this) && + likely (version == 0) && + encodingRecord.sanitize (c, this)); } USHORT version; /* Table version number (0). */ diff -uN gfx/harfbuzz/src_old/hb-ot-font.cc gfx/harfbuzz/src/hb-ot-font.cc --- gfx/harfbuzz/src_old/hb-ot-font.cc 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-ot-font.cc 2016-06-05 23:49:13.433053614 +0200 @@ -31,8 +31,11 @@ #include "hb-font-private.hh" #include "hb-ot-cmap-table.hh" +#include "hb-ot-glyf-table.hh" +#include "hb-ot-head-table.hh" #include "hb-ot-hhea-table.hh" #include "hb-ot-hmtx-table.hh" +#include "hb-ot-os2-table.hh" struct hb_ot_face_metrics_accelerator_t @@ -40,24 +43,58 @@ unsigned int num_metrics; unsigned int num_advances; unsigned int default_advance; + unsigned short ascender; + unsigned short descender; + unsigned short line_gap; + const OT::_mtx *table; hb_blob_t *blob; inline void init (hb_face_t *face, - hb_tag_t _hea_tag, hb_tag_t _mtx_tag, - unsigned int default_advance) + hb_tag_t _hea_tag, + hb_tag_t _mtx_tag, + hb_tag_t os2_tag) { - this->default_advance = default_advance; - this->num_metrics = face->get_num_glyphs (); + this->default_advance = face->get_upem (); + + bool got_font_extents = false; + if (os2_tag) + { + hb_blob_t *os2_blob = OT::Sanitizer::sanitize (face->reference_table (os2_tag)); + const OT::os2 *os2 = OT::Sanitizer::lock_instance (os2_blob); +#define USE_TYPO_METRICS (1u<<7) + if (0 != (os2->fsSelection & USE_TYPO_METRICS)) + { + this->ascender = os2->sTypoAscender; + this->descender = os2->sTypoDescender; + this->line_gap = os2->sTypoLineGap; + got_font_extents = (this->ascender | this->descender) != 0; + } + hb_blob_destroy (os2_blob); + } hb_blob_t *_hea_blob = OT::Sanitizer::sanitize (face->reference_table (_hea_tag)); const OT::_hea *_hea = OT::Sanitizer::lock_instance (_hea_blob); this->num_advances = _hea->numberOfLongMetrics; + if (!got_font_extents) + { + this->ascender = _hea->ascender; + this->descender = _hea->descender; + this->line_gap = _hea->lineGap; + } hb_blob_destroy (_hea_blob); this->blob = OT::Sanitizer::sanitize (face->reference_table (_mtx_tag)); - if (unlikely (!this->num_advances || - 2 * (this->num_advances + this->num_metrics) < hb_blob_get_length (this->blob))) + + /* Cap num_metrics() and num_advances() based on table length. */ + unsigned int len = hb_blob_get_length (this->blob); + if (unlikely (this->num_advances * 4 > len)) + this->num_advances = len / 4; + this->num_metrics = this->num_advances + (len - 4 * this->num_advances) / 2; + + /* We MUST set num_metrics to zero if num_advances is zero. + * Our get_advance() depends on that. */ + if (unlikely (!this->num_advances)) { this->num_metrics = this->num_advances = 0; hb_blob_destroy (this->blob); @@ -76,8 +113,8 @@ if (unlikely (glyph >= this->num_metrics)) { /* If this->num_metrics is zero, it means we don't have the metrics table - * for this direction: return one EM. Otherwise, it means that the glyph - * index is out of bound: return zero. */ + * for this direction: return default advance. Otherwise, it means that the + * glyph index is out of bound: return zero. */ if (this->num_metrics) return 0; else @@ -91,6 +128,79 @@ } }; +struct hb_ot_face_glyf_accelerator_t +{ + bool short_offset; + unsigned int num_glyphs; + const OT::loca *loca; + const OT::glyf *glyf; + hb_blob_t *loca_blob; + hb_blob_t *glyf_blob; + unsigned int glyf_len; + + inline void init (hb_face_t *face) + { + hb_blob_t *head_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_head)); + const OT::head *head = OT::Sanitizer::lock_instance (head_blob); + if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0) + { + /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ + hb_blob_destroy (head_blob); + return; + } + this->short_offset = 0 == head->indexToLocFormat; + hb_blob_destroy (head_blob); + + this->loca_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_loca)); + this->loca = OT::Sanitizer::lock_instance (this->loca_blob); + this->glyf_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_glyf)); + this->glyf = OT::Sanitizer::lock_instance (this->glyf_blob); + + this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1; + this->glyf_len = hb_blob_get_length (this->glyf_blob); + } + + inline void fini (void) + { + hb_blob_destroy (this->loca_blob); + hb_blob_destroy (this->glyf_blob); + } + + inline bool get_extents (hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const + { + if (unlikely (glyph >= this->num_glyphs)) + return false; + + unsigned int start_offset, end_offset; + if (this->short_offset) + { + start_offset = 2 * this->loca->u.shortsZ[glyph]; + end_offset = 2 * this->loca->u.shortsZ[glyph + 1]; + } + else + { + start_offset = this->loca->u.longsZ[glyph]; + end_offset = this->loca->u.longsZ[glyph + 1]; + } + + if (start_offset > end_offset || end_offset > this->glyf_len) + return false; + + if (end_offset - start_offset < OT::glyfGlyphHeader::static_size) + return true; /* Empty glyph; zero extents. */ + + const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset (this->glyf, start_offset); + + extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax); + extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax); + extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing; + extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing; + + return true; + } +}; + struct hb_ot_face_cmap_accelerator_t { const OT::CmapSubtable *table; @@ -114,6 +224,7 @@ if (!subtable) subtable = cmap->find_subtable (0, 2); if (!subtable) subtable = cmap->find_subtable (0, 1); if (!subtable) subtable = cmap->find_subtable (0, 0); + if (!subtable) subtable = cmap->find_subtable (3, 0); /* Meh. */ if (!subtable) subtable = &OT::Null(OT::CmapSubtable); @@ -157,23 +268,22 @@ hb_ot_face_cmap_accelerator_t cmap; hb_ot_face_metrics_accelerator_t h_metrics; hb_ot_face_metrics_accelerator_t v_metrics; + hb_ot_face_glyf_accelerator_t glyf; }; static hb_ot_font_t * -_hb_ot_font_create (hb_font_t *font) +_hb_ot_font_create (hb_face_t *face) { hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); - hb_face_t *face = font->face; if (unlikely (!ot_font)) return NULL; - unsigned int upem = face->get_upem (); - ot_font->cmap.init (face); - ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1); - ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */ + ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2); + ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE); /* TODO Can we do this lazily? */ + ot_font->glyf.init (face); return ot_font; } @@ -184,6 +294,7 @@ ot_font->cmap.fini (); ot_font->h_metrics.fini (); ot_font->v_metrics.fini (); + ot_font->glyf.fini (); free (ot_font); } @@ -219,53 +330,7 @@ void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_y (-ot_font->v_metrics.get_advance (glyph)); -} - -static hb_bool_t -hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t glyph HB_UNUSED, - hb_position_t *x HB_UNUSED, - hb_position_t *y HB_UNUSED, - void *user_data HB_UNUSED) -{ - /* We always work in the horizontal coordinates. */ - return true; -} - -static hb_bool_t -hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED, - void *font_data, - hb_codepoint_t glyph, - hb_position_t *x, - hb_position_t *y, - void *user_data HB_UNUSED) -{ - /* TODO */ - return false; -} - -static hb_position_t -hb_ot_get_glyph_h_kerning (hb_font_t *font, - void *font_data, - hb_codepoint_t left_glyph, - hb_codepoint_t right_glyph, - void *user_data HB_UNUSED) -{ - /* TODO */ - return 0; -} - -static hb_position_t -hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t top_glyph HB_UNUSED, - hb_codepoint_t bottom_glyph HB_UNUSED, - void *user_data HB_UNUSED) -{ - /* OpenType doesn't have vertical-kerning other than GPOS. */ - return 0; + return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph)); } static hb_bool_t @@ -275,69 +340,100 @@ hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - /* TODO */ - return false; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + bool ret = ot_font->glyf.get_extents (glyph, extents); + extents->x_bearing = font->em_scale_x (extents->x_bearing); + extents->y_bearing = font->em_scale_y (extents->y_bearing); + extents->width = font->em_scale_x (extents->width); + extents->height = font->em_scale_y (extents->height); + return ret; } static hb_bool_t -hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED, - void *font_data, - hb_codepoint_t glyph, - unsigned int point_index, - hb_position_t *x, - hb_position_t *y, - void *user_data HB_UNUSED) +hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED, + void *font_data, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) { - /* TODO */ - return false; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); + metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); + metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); + return true; } static hb_bool_t -hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, - void *font_data, - hb_codepoint_t glyph, - char *name, unsigned int size, - void *user_data HB_UNUSED) +hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED, + void *font_data, + hb_font_extents_t *metrics, + void *user_data HB_UNUSED) { - /* TODO */ - return false; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); + metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); + metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); + return true; } -static hb_bool_t -hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, - void *font_data, - const char *name, int len, /* -1 means nul-terminated */ - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) +static hb_font_funcs_t *static_ot_funcs = NULL; + +#ifdef HB_USE_ATEXIT +static +void free_static_ot_funcs (void) { - /* TODO */ - return false; + hb_font_funcs_destroy (static_ot_funcs); } - +#endif static hb_font_funcs_t * _hb_ot_get_font_funcs (void) { - static const hb_font_funcs_t ot_ffuncs = { - HB_OBJECT_HEADER_STATIC, +retry: + hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs); - true, /* immutable */ + if (unlikely (!funcs)) + { + funcs = hb_font_funcs_create (); - { -#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name, - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT + hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL); + hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL); + hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL); + hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL); + //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL); + //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL); + //hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); TODO + //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL); + hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL); + //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); TODO + //hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); TODO + //hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); TODO + + hb_font_funcs_make_immutable (funcs); + + if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, NULL, funcs)) { + hb_font_funcs_destroy (funcs); + goto retry; } + +#ifdef HB_USE_ATEXIT + atexit (free_static_ot_funcs); /* First person registers atexit() callback. */ +#endif }; - return const_cast (&ot_ffuncs); + return funcs; } +/** + * hb_ot_font_set_funcs: + * + * Since: 0.9.28 + **/ void hb_ot_font_set_funcs (hb_font_t *font) { - hb_ot_font_t *ot_font = _hb_ot_font_create (font); + hb_ot_font_t *ot_font = _hb_ot_font_create (font->face); if (unlikely (!ot_font)) return; diff -uN gfx/harfbuzz/src_old/hb-ot-font.h gfx/harfbuzz/src/hb-ot-font.h --- gfx/harfbuzz/src_old/hb-ot-font.h 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-ot-font.h 2016-06-05 23:49:14.679046863 +0200 @@ -24,6 +24,10 @@ * Google Author(s): Behdad Esfahbod, Roozbeh Pournader */ +#ifndef HB_OT_H_IN +#error "Include instead." +#endif + #ifndef HB_OT_FONT_H #define HB_OT_FONT_H @@ -32,7 +36,7 @@ HB_BEGIN_DECLS -void +HB_EXTERN void hb_ot_font_set_funcs (hb_font_t *font); diff -uN gfx/harfbuzz/src_old/hb-ot-glyf-table.hh gfx/harfbuzz/src/hb-ot-glyf-table.hh --- gfx/harfbuzz/src_old/hb-ot-glyf-table.hh 1970-01-01 01:00:00.000000000 +0100 +++ gfx/harfbuzz/src/hb-ot-glyf-table.hh 2016-06-05 23:49:15.900040281 +0200 @@ -0,0 +1,104 @@ +/* + * Copyright © 2015 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_GLYF_TABLE_HH +#define HB_OT_GLYF_TABLE_HH + +#include "hb-open-type-private.hh" + + +namespace OT { + + +/* + * loca -- Index to Location + */ + +#define HB_OT_TAG_loca HB_TAG('l','o','c','a') + + +struct loca +{ + static const hb_tag_t tableTag = HB_OT_TAG_loca; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (true); + } + + public: + union { + USHORT shortsZ[VAR]; /* Location offset divided by 2. */ + ULONG longsZ[VAR]; /* Location offset. */ + } u; + DEFINE_SIZE_ARRAY (0, u.longsZ); +}; + + +/* + * glyf -- TrueType Glyph Data + */ + +#define HB_OT_TAG_glyf HB_TAG('g','l','y','f') + + +struct glyf +{ + static const hb_tag_t tableTag = HB_OT_TAG_glyf; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + /* We don't check for anything specific here. The users of the + * struct do all the hard work... */ + return_trace (true); + } + + public: + BYTE dataX[VAR]; /* Glyphs data. */ + + DEFINE_SIZE_ARRAY (0, dataX); +}; + +struct glyfGlyphHeader +{ + SHORT numberOfContours; /* If the number of contours is + * greater than or equal to zero, + * this is a simple glyph; if negative, + * this is a composite glyph. */ + SHORT xMin; /* Minimum x for coordinate data. */ + SHORT yMin; /* Minimum y for coordinate data. */ + SHORT xMax; /* Maximum x for coordinate data. */ + SHORT yMax; /* Maximum y for coordinate data. */ + + DEFINE_SIZE_STATIC (10); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_GLYF_TABLE_HH */ diff -uN gfx/harfbuzz/src_old/hb-ot-head-table.hh gfx/harfbuzz/src/hb-ot-head-table.hh --- gfx/harfbuzz/src_old/hb-ot-head-table.hh 2016-05-10 22:26:55.000000000 +0200 +++ gfx/harfbuzz/src/hb-ot-head-table.hh 2016-06-05 23:49:17.080033892 +0200 @@ -45,15 +45,19 @@ { static const hb_tag_t tableTag = HB_OT_TAG_head; - inline unsigned int get_upem (void) const { + inline unsigned int get_upem (void) const + { unsigned int upem = unitsPerEm; /* If no valid head table found, assume 1000, which matches typical Type1 usage. */ return 16 <= upem && upem <= 16384 ? upem : 1000; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); + return_trace (c->check_struct (this) && + version.major == 1 && + magicNumber == 0x5F0F3CF5u); } protected: @@ -136,9 +140,10 @@ * 2: Like 1 but also contains neutrals; * -1: Only strongly right to left; * -2: Like -1 but also contains neutrals. */ + public: SHORT indexToLocFormat; /* 0 for short offsets, 1 for long. */ SHORT glyphDataFormat; /* 0 for current format. */ - public: + DEFINE_SIZE_STATIC (54); }; diff -uN gfx/harfbuzz/src_old/hb-ot-hhea-table.hh gfx/harfbuzz/src/hb-ot-hhea-table.hh --- gfx/harfbuzz/src_old/hb-ot-hhea-table.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-ot-hhea-table.hh 2016-06-05 23:49:18.320027217 +0200 @@ -49,9 +49,10 @@ static const hb_tag_t hheaTag = HB_OT_TAG_hhea; static const hb_tag_t vheaTag = HB_OT_TAG_vhea; - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); + return_trace (c->check_struct (this) && likely (version.major == 1)); } public: diff -uN gfx/harfbuzz/src_old/hb-ot-hmtx-table.hh gfx/harfbuzz/src/hb-ot-hmtx-table.hh --- gfx/harfbuzz/src_old/hb-ot-hmtx-table.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-ot-hmtx-table.hh 2016-06-05 23:49:19.601020309 +0200 @@ -57,11 +57,12 @@ static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx; static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx; - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); /* We don't check for anything specific here. The users of the * struct do all the hard work... */ - return TRACE_RETURN (true); + return_trace (true); } public: diff -uN gfx/harfbuzz/src_old/hb-ot-layout.cc gfx/harfbuzz/src/hb-ot-layout.cc --- gfx/harfbuzz/src_old/hb-ot-layout.cc 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-ot-layout.cc 2016-06-05 23:49:31.325957413 +0200 @@ -28,6 +28,7 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb-open-type-private.hh" #include "hb-ot-layout-private.hh" #include "hb-ot-layout-gdef-table.hh" @@ -84,9 +85,9 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) { for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) - layout->gsub_accels[i].fini (layout->gsub->get_lookup (i)); + layout->gsub_accels[i].fini (); for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) - layout->gpos_accels[i].fini (layout->gpos->get_lookup (i)); + layout->gpos_accels[i].fini (); free (layout->gsub_accels); free (layout->gpos_accels); @@ -128,6 +129,11 @@ return _get_gdef (face).has_glyph_classes (); } +/** + * hb_ot_layout_get_glyph_class: + * + * Since: 0.9.7 + **/ hb_ot_layout_glyph_class_t hb_ot_layout_get_glyph_class (hb_face_t *face, hb_codepoint_t glyph) @@ -135,6 +141,11 @@ return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph); } +/** + * hb_ot_layout_get_glyphs_in_class: + * + * Since: 0.9.7 + **/ void hb_ot_layout_get_glyphs_in_class (hb_face_t *face, hb_ot_layout_glyph_class_t klass, @@ -285,6 +296,28 @@ return g.get_feature_tags (start_offset, feature_count, feature_tags); } +hb_bool_t +hb_ot_layout_table_find_feature (hb_face_t *face, + hb_tag_t table_tag, + hb_tag_t feature_tag, + unsigned int *feature_index) +{ + ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + unsigned int num_features = g.get_feature_count (); + for (unsigned int i = 0; i < num_features; i++) + { + if (feature_tag == g.get_feature_tag (i)) { + if (feature_index) *feature_index = i; + return true; + } + } + + if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; + return false; +} + unsigned int hb_ot_layout_script_get_language_tags (hb_face_t *face, @@ -335,6 +368,11 @@ NULL); } +/** + * hb_ot_layout_language_get_required_feature: + * + * Since: 0.9.30 + **/ hb_bool_t hb_ot_layout_language_get_required_feature (hb_face_t *face, hb_tag_t table_tag, @@ -419,6 +457,11 @@ return false; } +/** + * hb_ot_layout_feature_get_lookups: + * + * Since: 0.9.7 + **/ unsigned int hb_ot_layout_feature_get_lookups (hb_face_t *face, hb_tag_t table_tag, @@ -433,6 +476,11 @@ return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); } +/** + * hb_ot_layout_table_get_lookup_count: + * + * Since: 0.9.22 + **/ unsigned int hb_ot_layout_table_get_lookup_count (hb_face_t *face, hb_tag_t table_tag) @@ -590,6 +638,11 @@ } } +/** + * hb_ot_layout_collect_lookups: + * + * Since: 0.9.8 + **/ void hb_ot_layout_collect_lookups (hb_face_t *face, hb_tag_t table_tag, @@ -631,6 +684,11 @@ } } +/** + * hb_ot_layout_lookup_collect_glyphs: + * + * Since: 0.9.7 + **/ void hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, hb_tag_t table_tag, @@ -676,6 +734,11 @@ return &_get_gsub (face) != &OT::Null(OT::GSUB); } +/** + * hb_ot_layout_lookup_would_substitute: + * + * Since: 0.9.7 + **/ hb_bool_t hb_ot_layout_lookup_would_substitute (hb_face_t *face, unsigned int lookup_index, @@ -695,11 +758,11 @@ hb_bool_t zero_context) { if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false; - OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context); + OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context); const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); - return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index].digest); + return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]); } void @@ -714,6 +777,11 @@ OT::GSUB::substitute_finish (font, buffer); } +/** + * hb_ot_layout_lookup_substitute_closure: + * + * Since: 0.9.7 + **/ void hb_ot_layout_lookup_substitute_closure (hb_face_t *face, unsigned int lookup_index, @@ -748,6 +816,11 @@ OT::GPOS::position_finish (font, buffer); } +/** + * hb_ot_layout_get_size_params: + * + * Since: 0.9.10 + **/ hb_bool_t hb_ot_layout_get_size_params (hb_face_t *face, unsigned int *design_size, /* OUT. May be NULL */ @@ -829,28 +902,82 @@ }; -template -static inline bool apply_once (OT::hb_apply_context_t *c, - const Lookup &lookup) +template +static inline bool +apply_forward (OT::hb_apply_context_t *c, + const Obj &obj, + const hb_ot_layout_lookup_accelerator_t &accel) { - if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props)) - return false; - return lookup.dispatch (c); + bool ret = false; + hb_buffer_t *buffer = c->buffer; + while (buffer->idx < buffer->len && !buffer->in_error) + { + if (accel.may_have (buffer->cur().codepoint) && + (buffer->cur().mask & c->lookup_mask) && + c->check_glyph_property (&buffer->cur(), c->lookup_props) && + obj.apply (c)) + ret = true; + else + buffer->next_glyph (); + } + return ret; } -template +template static inline bool +apply_backward (OT::hb_apply_context_t *c, + const Obj &obj, + const hb_ot_layout_lookup_accelerator_t &accel) +{ + bool ret = false; + hb_buffer_t *buffer = c->buffer; + do + { + if (accel.may_have (buffer->cur().codepoint) && + (buffer->cur().mask & c->lookup_mask) && + c->check_glyph_property (&buffer->cur(), c->lookup_props) && + obj.apply (c)) + ret = true; + /* The reverse lookup doesn't "advance" cursor (for good reason). */ + buffer->idx--; + + } + while ((int) buffer->idx >= 0); + return ret; +} + +struct hb_apply_forward_context_t : + OT::hb_dispatch_context_t +{ + inline const char *get_name (void) { return "APPLY_FWD"; } + template + inline return_t dispatch (const T &obj) { return apply_forward (c, obj, accel); } + static return_t default_return_value (void) { return false; } + bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return true; } + + hb_apply_forward_context_t (OT::hb_apply_context_t *c_, + const hb_ot_layout_lookup_accelerator_t &accel_) : + c (c_), + accel (accel_), + debug_depth (0) {} + + OT::hb_apply_context_t *c; + const hb_ot_layout_lookup_accelerator_t &accel; + unsigned int debug_depth; +}; + +template +static inline void apply_string (OT::hb_apply_context_t *c, const typename Proxy::Lookup &lookup, const hb_ot_layout_lookup_accelerator_t &accel) { - bool ret = false; hb_buffer_t *buffer = c->buffer; if (unlikely (!buffer->len || !c->lookup_mask)) - return false; + return; - c->set_lookup (lookup); + c->set_lookup_props (lookup.get_props ()); if (likely (!lookup.is_reverse ())) { @@ -859,21 +986,20 @@ buffer->clear_output (); buffer->idx = 0; - while (buffer->idx < buffer->len) + bool ret; + if (lookup.get_subtable_count () == 1) { - if (accel.digest.may_have (buffer->cur().codepoint) && - (buffer->cur().mask & c->lookup_mask) && - apply_once (c, lookup)) - ret = true; - else - buffer->next_glyph (); + hb_apply_forward_context_t c_forward (c, accel); + ret = lookup.dispatch (&c_forward); } + else + ret = apply_forward (c, lookup, accel); if (ret) { if (!Proxy::inplace) buffer->swap_buffers (); else - assert (!buffer->has_separate_output ()); + assert (!buffer->has_separate_output ()); } } else @@ -882,20 +1008,9 @@ if (Proxy::table_index == 0) buffer->remove_output (); buffer->idx = buffer->len - 1; - do - { - if (accel.digest.may_have (buffer->cur().codepoint) && - (buffer->cur().mask & c->lookup_mask) && - apply_once (c, lookup)) - ret = true; - /* The reverse lookup doesn't "advance" cursor (for good reason). */ - buffer->idx--; - } - while ((int) buffer->idx >= 0); + apply_backward (c, lookup, accel); } - - return ret; } template @@ -914,11 +1029,14 @@ for (; i < stage->last_lookup; i++) { unsigned int lookup_index = lookups[table_index][i].index; + if (!buffer->message (font, "start lookup %d", lookup_index)) continue; + c.set_lookup_index (lookup_index); c.set_lookup_mask (lookups[table_index][i].mask); c.set_auto_zwj (lookups[table_index][i].auto_zwj); apply_string (&c, proxy.table.get_lookup (lookup_index), proxy.accels[lookup_index]); + (void) buffer->message (font, "end lookup %d", lookup_index); } if (stage->pause_func) diff -uN gfx/harfbuzz/src_old/hb-ot-layout-common-private.hh gfx/harfbuzz/src/hb-ot-layout-common-private.hh --- gfx/harfbuzz/src_old/hb-ot-layout-common-private.hh 2016-05-10 22:26:56.000000000 +0200 +++ gfx/harfbuzz/src/hb-ot-layout-common-private.hh 2016-06-05 23:49:21.127012094 +0200 @@ -34,12 +34,24 @@ #include "hb-set-private.hh" +#ifndef HB_MAX_NESTING_LEVEL +#define HB_MAX_NESTING_LEVEL 6 +#endif +#ifndef HB_MAX_CONTEXT_LENGTH +#define HB_MAX_CONTEXT_LENGTH 64 +#endif + + namespace OT { +#define TRACE_DISPATCH(this, format) \ + hb_auto_trace_t trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "format %d", (int) format); + + #define NOT_COVERED ((unsigned int) -1) -#define MAX_NESTING_LEVEL 8 -#define MAX_CONTEXT_LENGTH 64 @@ -63,12 +75,13 @@ struct sanitize_closure_t { hb_tag_t tag; - void *list_base; + const void *list_base; }; - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); const sanitize_closure_t closure = {tag, base}; - return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure)); + return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure)); } Tag tag; /* 4-byte Tag identifier */ @@ -121,9 +134,10 @@ inline const Type& operator [] (unsigned int i) const { return this+RecordArrayOf::operator [](i).offset; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (RecordArrayOf::sanitize (c, this)); + return_trace (RecordArrayOf::sanitize (c, this)); } }; @@ -134,9 +148,10 @@ return g < start ? -1 : g <= end ? 0 : +1 ; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this)); + return_trace (c->check_struct (this)); } inline bool intersects (const hb_set_t *glyphs) const { @@ -199,9 +214,10 @@ } inline bool sanitize (hb_sanitize_context_t *c, - const Record::sanitize_closure_t * = NULL) { + const Record::sanitize_closure_t * = NULL) const + { TRACE_SANITIZE (this); - return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c)); + return_trace (c->check_struct (this) && featureIndex.sanitize (c)); } Offset<> lookupOrderZ; /* = Null (reserved for an offset to a @@ -238,9 +254,10 @@ inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } inline bool sanitize (hb_sanitize_context_t *c, - const Record