Bug 1757738 - Update HarfBuzz to 4.1.0. r=jfkthame

Differential Revision: https://phabricator.services.mozilla.com/D140064
This commit is contained in:
Ryan VanderMeulen 2022-03-23 20:13:18 +00:00
Родитель cb0a86aae4
Коммит d18a71361f
72 изменённых файлов: 3549 добавлений и 1325 удалений

Просмотреть файл

@ -1,3 +1,127 @@
Overview of changes leading to 4.1.0
Wednesday, March 23, 2022
====================================
- Various OSS-Fuzz fixes. (Behdad Esfahbod)
- Make fallback vertical-origin match FreeTypes. (Behdad Esfahbod)
- Treat visible viramas like dependent vowels in USE shaper. (David Corbett)
- Apply presentation forms features and discretionary features in one go in
Indic shaper, which seems to match Uniscribe and CoreText behaviour.
(Behdad Esfahbod, David Corbett)
- Various bug fixes.
- New API
+hb_set_add_sorted_array()
Overview of changes leading to 4.0.1
Friday, March 11, 2022
====================================
- Update OpenType to AAT mappings for “hist” and “vrtr” features.
(Florian Pircher)
- Update IANA Language Subtag Registry to 2022-03-02. (David Corbett)
- Update USE shaper to allow any non-numeric tail in a symbol cluster, and
remove obsolete data overrides. (David Corbett)
- Fix handling of baseline variations to return correctly scaled values.
(Matthias Clasen)
- A new experimental hb_subset_repack_or_fail() to repack an array of objects,
eliminating offset overflows. The API is not available unless HarfBuzz is
built with experimental APIs enabled. (Qunxin Liu)
- New experimental API
+hb_link_t
+hb_object_t
+hb_subset_repack_or_fail()
Overview of changes leading to 4.0.0
Tuesday, March 1, 2022
====================================
- New public API to create subset plan and gather information on things like
glyph mappings in the final subset. The plan can then be passed on to perform
the subsetting operation. (Garret Rieger)
- Draw API for extracting glyph shapes have been extended and finalized and is
no longer an experimental API. The draw API supports glyf, CFF and CFF2
glyph outlines tables, and applies variation settings set on the font as well
as synthetic slant. The new public API is not backward compatible with the
previous, non-public, experimental API. (Behdad Esfahbod)
- The hb-view tool will use HarfBuzz draw API to render the glyphs instead of
cairo-ft when compiled with Cairo 1.17.5 or newer, setting HB_DRAW
environment variable to 1 or 0 will force using or not use the draw API,
respectively. (Behdad Esfahbod)
- The hb-shape and hb-view tools now default to using HarfBuzzs own font
loading functions (ot) instead of FreeType ones (ft). They also have a new
option, --font-slant, to apply synthetic slant to the font. (Behdad Esfahbod)
- HarfBuzz now supports more than 65535 (the OpenType limit) glyph shapes and
metrics. See https://github.com/be-fonts/boring-expansion-spec/issues/6 and
https://github.com/be-fonts/boring-expansion-spec/issues/7 for details.
(Behdad Esfahbod)
- New API to get the dominant horizontal baseline tag for a given script.
(Behdad Esfahbod)
- New API to get the baseline positions from the font, and synthesize missing
ones. As well as new API to get font metrics and synthesize missing ones.
(Matthias Clasen)
- Improvements to finding dependencies on Windows when building with Visual
Studio. (Chun-wei Fan)
- New buffer flag, HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT, that must be set
during shaping for HB_GLYPH_FLAG_UNSAFE_TO_CONCAT flag to be reliably
produced. This is to limit the performance hit of producing this flag to when
it is actually needed. (Behdad Esfahbod)
- Documentation improvements. (Matthias Clasen)
- New API
- General:
+HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT
+hb_var_num_t
- Draw:
+hb_draw_funcs_t
+hb_draw_funcs_create()
+hb_draw_funcs_reference()
+hb_draw_funcs_destroy()
+hb_draw_funcs_is_immutable()
+hb_draw_funcs_make_immutable()
+hb_draw_move_to_func_t
+hb_draw_funcs_set_move_to_func()
+hb_draw_line_to_func_t
+hb_draw_funcs_set_line_to_func()
+hb_draw_quadratic_to_func_t
+hb_draw_funcs_set_quadratic_to_func()
+hb_draw_cubic_to_func_t
+hb_draw_funcs_set_cubic_to_func()
+hb_draw_close_path_func_t
+hb_draw_funcs_set_close_path_func()
+hb_draw_state_t
+HB_DRAW_STATE_DEFAULT
+hb_draw_move_to()
+hb_draw_line_to()
+hb_draw_quadratic_to()
+hb_draw_cubic_to()
+hb_draw_close_path()
+hb_font_get_glyph_shape_func_t
+hb_font_funcs_set_glyph_shape_func()
+hb_font_get_glyph_shape()
- OpenType layout
+HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL
+HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL
+hb_ot_layout_get_horizontal_baseline_tag_for_script()
+hb_ot_layout_get_baseline_with_fallback()
- Metrics:
+hb_ot_metrics_get_position_with_fallback()
- Subset:
+hb_subset_plan_t
+hb_subset_plan_create_or_fail()
+hb_subset_plan_reference()
+hb_subset_plan_destroy()
+hb_subset_plan_set_user_data()
+hb_subset_plan_get_user_data()
+hb_subset_plan_execute_or_fail()
+hb_subset_plan_unicode_to_old_glyph_mapping()
+hb_subset_plan_new_to_old_glyph_mapping()
+hb_subset_plan_old_to_new_glyph_mapping()
Overview of changes leading to 3.4.0
Sunday, February 13, 2022
====================================
@ -10,15 +134,15 @@ Sunday, February 13, 2022
math tag. (Alexis King)
- It is now possible to get at once all math kerning values for a given glyph
at a given corner. (Alexis King)
- Fix locale_t portability issues on systems the typdefs it to a void pointer.
(Behdad Esfahbod)
- Fix locale_t portability issues on systems the typedefs it to a void
pointer. (Behdad Esfahbod)
- New API:
+HB_BUFFER_FLAG_VERIFY
+HB_OT_TAG_MATH_SCRIPT
+HB_SCRIPT_MATH
+hb_ot_math_kern_entry_t
+hb_ot_math_get_glyph_kernings
+hb_ot_math_get_glyph_kernings()
- Deprecated API
+HB_OT_MATH_SCRIPT

Просмотреть файл

@ -1,7 +1,7 @@
This directory contains the HarfBuzz source from the upstream repo:
https://github.com/harfbuzz/harfbuzz
Current version: 3.4.0 [commit 0a129961341da370ec82bfccdd11ec9b1094b5a2]
Current version: 4.1.0 [commit c36844d6d923bfc765f841fde10d6f505ff297fd]
!!!Please Note!!!
Because LLVM added in D100581 support for -Wunused-but-set-parameter and -Wunused-but-set-variable

Просмотреть файл

@ -1,28 +0,0 @@
API issues:
===========
- API to accept a list of languages?
- Remove hb_ot_shape_glyphs_closure()?
API additions
=============
- Language to/from script.
- Add hb-cairo glue
- Add sanitize API.
- Add query / enumeration API for aalt-like features?
- Add segmentation API
- Add hb-fribidi glue?
hb-view / hb-shape enhancements:
===============================
- Add --width, --height, --auto-size, --ink-box, --align, etc?

Просмотреть файл

@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
[3.4.0],
[4.1.0],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])
@ -194,6 +194,10 @@ AC_ARG_WITH(cairo,
have_cairo=false
if test "x$with_cairo" = "xyes" -o "x$with_cairo" = "xauto"; then
PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, :)
save_libs=$LIBS
LIBS="$LIBS $CAIRO_LIBS"
AC_CHECK_FUNCS(cairo_user_font_face_set_render_color_glyph_func)
LIBS=$save_libs
fi
if test "x$with_cairo" = "xyes" -a "x$have_cairo" != "xtrue"; then
AC_MSG_ERROR([cairo support requested but not found])

Просмотреть файл

@ -275,6 +275,7 @@ HB_SUBSET_sources = \
hb-subset-input.hh \
hb-subset-plan.cc \
hb-subset-plan.hh \
hb-subset-repacker.cc \
hb-subset.cc \
hb-subset.hh \
hb-repacker.hh \
@ -282,6 +283,7 @@ HB_SUBSET_sources = \
HB_SUBSET_headers = \
hb-subset.h \
hb-subset-repacker.h \
$(NULL)
HB_GOBJECT_DIST_sources = hb-gobject-structs.cc

Просмотреть файл

@ -19,23 +19,7 @@ symbols = sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re
if '--experimental-api' not in sys.argv:
# Move these to harfbuzz-sections.txt when got stable
experimental_symbols = \
"""hb_font_draw_glyph
hb_draw_funcs_t
hb_draw_close_path_func_t
hb_draw_cubic_to_func_t
hb_draw_line_to_func_t
hb_draw_move_to_func_t
hb_draw_quadratic_to_func_t
hb_draw_funcs_create
hb_draw_funcs_destroy
hb_draw_funcs_is_immutable
hb_draw_funcs_make_immutable
hb_draw_funcs_reference
hb_draw_funcs_set_close_path_func
hb_draw_funcs_set_cubic_to_func
hb_draw_funcs_set_line_to_func
hb_draw_funcs_set_move_to_func
hb_draw_funcs_set_quadratic_to_func""".splitlines ()
"""hb_subset_repack_or_fail""".splitlines ()
symbols = [x for x in symbols if x not in experimental_symbols]
symbols = "\n".join (symbols)

Просмотреть файл

@ -39,7 +39,7 @@ for j in range(7, 9):
headers[j - 1].append(line)
headers.append (["UnicodeData.txt does not have a header."])
data = [{} for _ in files]
unicode_data = [{} for _ in files]
values = [{} for _ in files]
for i, f in enumerate (files):
for line in f:
@ -73,38 +73,16 @@ for i, f in enumerate (files):
i0 = i if i < 7 else i - 7
for u in range (start, end + 1):
data[i0][u] = t
unicode_data[i0][u] = t
values[i0][t] = values[i0].get (t, 0) + end - start + 1
defaults = ('Other', 'Not_Applicable', 'jt_X', '', 'Cn', 'No_Block', 'Unknown')
# TODO Characters that are not in Unicode Indic files, but used in USE
data[0][0x1B61] = defaults[0]
data[0][0x1B63] = defaults[0]
data[0][0x1B64] = defaults[0]
data[0][0x1B65] = defaults[0]
data[0][0x1B66] = defaults[0]
data[0][0x1B67] = defaults[0]
data[0][0x1B69] = defaults[0]
data[0][0x1B6A] = defaults[0]
data[0][0x2060] = defaults[0]
# TODO https://github.com/harfbuzz/harfbuzz/pull/1685
data[0][0x1B5B] = 'Consonant_Placeholder'
data[0][0x1B5C] = 'Consonant_Placeholder'
data[0][0x1B5F] = 'Consonant_Placeholder'
data[0][0x1B62] = 'Consonant_Placeholder'
data[0][0x1B68] = 'Consonant_Placeholder'
# TODO https://github.com/harfbuzz/harfbuzz/issues/1035
data[0][0x11C44] = 'Consonant_Placeholder'
data[0][0x11C45] = 'Consonant_Placeholder'
# TODO https://github.com/harfbuzz/harfbuzz/pull/1399
data[0][0x111C8] = 'Consonant_Placeholder'
# 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 i,d in enumerate (unicode_data):
for u,v in d.items ():
if not u in combined:
if i >= 4:
@ -112,8 +90,6 @@ for i,d in enumerate (data):
combined[u] = list (defaults)
combined[u][i] = v
combined = {k: v for k, v in combined.items() if v[6] not in DISABLED_SCRIPTS}
data = combined
del combined
property_names = [
@ -226,8 +202,8 @@ def is_BASE_OTHER(U, UISC, UDI, UGC, AJT):
if UISC == Consonant_Placeholder: return True
return U in [0x2015, 0x2022, 0x25FB, 0x25FC, 0x25FD, 0x25FE]
def is_CGJ(U, UISC, UDI, UGC, AJT):
# Also includes VARIATION_SELECTOR, WJ, and ZWJ
return U == 0x200D or UDI and UGC in [Mc, Me, Mn]
# Also includes VARIATION_SELECTOR and ZWJ
return UISC == Joiner or UDI and UGC in [Mc, Me, Mn]
def is_CONS_FINAL(U, UISC, UDI, UGC, AJT):
return ((UISC == Consonant_Final and UGC != Lo) or
UISC == Consonant_Succeeding_Repha)
@ -245,13 +221,7 @@ def is_CONS_SUB(U, UISC, UDI, UGC, AJT):
def is_CONS_WITH_STACKER(U, UISC, UDI, UGC, AJT):
return UISC == Consonant_With_Stacker
def is_HALANT(U, UISC, UDI, UGC, AJT):
return (UISC in [Virama, Invisible_Stacker]
and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UDI, UGC, AJT)
and not is_SAKOT(U, UISC, UDI, UGC, AJT))
def is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UDI, UGC, AJT):
# Split off of HALANT
# https://github.com/harfbuzz/harfbuzz/issues/1379
return U == 0x1134D
return UISC == Virama
def is_HALANT_NUM(U, UISC, UDI, UGC, AJT):
return UISC == Number_Joiner
def is_HIEROGLYPH(U, UISC, UDI, UGC, AJT):
@ -262,15 +232,21 @@ def is_HIEROGLYPH_SEGMENT_BEGIN(U, UISC, UDI, UGC, AJT):
return UISC == Hieroglyph_Segment_Begin
def is_HIEROGLYPH_SEGMENT_END(U, UISC, UDI, UGC, AJT):
return UISC == Hieroglyph_Segment_End
def is_INVISIBLE_STACKER(U, UISC, UDI, UGC, AJT):
# Split off of HALANT
return (UISC == Invisible_Stacker
and not is_SAKOT(U, UISC, UDI, UGC, AJT)
)
def is_ZWNJ(U, UISC, UDI, UGC, AJT):
return UISC == Non_Joiner
def is_OTHER(U, UISC, UDI, UGC, AJT):
# Also includes BASE_IND, Rsv, and SYM
return ((UGC in [Cn, Po] or UISC in [Consonant_Dead, Joiner, Modifying_Letter, Other])
# Also includes BASE_IND and SYM
return ((UGC == Po or UISC in [Consonant_Dead, Joiner, Modifying_Letter, Other])
and not is_BASE(U, UISC, UDI, UGC, AJT)
and not is_BASE_OTHER(U, UISC, UDI, UGC, AJT)
and not is_CGJ(U, UISC, UDI, UGC, AJT)
and not is_SYM_MOD(U, UISC, UDI, UGC, AJT)
and not is_Word_Joiner(U, UISC, UDI, UGC, AJT)
)
def is_REPHA(U, UISC, UDI, UGC, AJT):
return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed]
@ -280,13 +256,17 @@ def is_SAKOT(U, UISC, UDI, UGC, AJT):
def is_SYM_MOD(U, UISC, UDI, UGC, AJT):
return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
def is_VOWEL(U, UISC, UDI, UGC, AJT):
# https://github.com/harfbuzz/harfbuzz/issues/376
return (UISC == Pure_Killer or
(UGC != Lo and UISC in [Vowel, Vowel_Dependent] and U not in [0xAA29]))
UGC != Lo and UISC in [Vowel, Vowel_Dependent])
def is_VOWEL_MOD(U, UISC, UDI, UGC, AJT):
# https://github.com/harfbuzz/harfbuzz/issues/376
return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or
(UGC != Lo and (UISC == Bindu or U in [0xAA29])))
UGC != Lo and UISC == Bindu)
def is_Word_Joiner(U, UISC, UDI, UGC, AJT):
# Also includes Rsv
return (UDI and U not in [0x115F, 0x1160, 0x3164, 0xFFA0, 0x1BCA0, 0x1BCA1, 0x1BCA2, 0x1BCA3]
and UISC == Other
and not is_CGJ(U, UISC, UDI, UGC, AJT)
) or UGC == Cn
use_mapping = {
'B': is_BASE,
@ -300,8 +280,8 @@ use_mapping = {
'SUB': is_CONS_SUB,
'CS': is_CONS_WITH_STACKER,
'H': is_HALANT,
'HVM': is_HALANT_OR_VOWEL_MODIFIER,
'HN': is_HALANT_NUM,
'IS': is_INVISIBLE_STACKER,
'G': is_HIEROGLYPH,
'J': is_HIEROGLYPH_JOINER,
'SB': is_HIEROGLYPH_SEGMENT_BEGIN,
@ -313,6 +293,7 @@ use_mapping = {
'SM': is_SYM_MOD,
'V': is_VOWEL,
'VM': is_VOWEL_MOD,
'WJ': is_Word_Joiner,
}
use_positions = {
@ -348,7 +329,7 @@ use_positions = {
'Blw': [Bottom],
},
'H': None,
'HVM': None,
'IS': None,
'B': None,
'FM': {
'Abv': [Top],
@ -380,9 +361,6 @@ def map_to_use(data):
# the nasalization marks, maybe only for U+1CE9..U+1CF1.
if U == 0x1CED: UISC = Tone_Mark
# TODO: https://github.com/microsoft/font-tools/issues/1
if U == 0xA982: UISC = Consonant_Succeeding_Repha
values = [k for k,v in items if v(U, UISC, UDI, UGC, AJT)]
assert len(values) == 1, "%s %s %s %s %s %s" % (hex(U), UISC, UDI, UGC, AJT, values)
USE = values[0]
@ -416,8 +394,7 @@ def map_to_use(data):
out[U] = (USE, UBlock)
return out
defaults = ('O', 'No_Block')
data = map_to_use(data)
use_data = map_to_use(combined)
print ("/* == Start of generated table == */")
print ("/*")
@ -443,7 +420,7 @@ print ()
total = 0
used = 0
last_block = None
def print_block (block, start, end, data):
def print_block (block, start, end, use_data):
global total, used, last_block
if block and block != last_block:
print ()
@ -458,17 +435,23 @@ def print_block (block, start, end, data):
if u % 16 == 0:
print ()
print (" /* %04X */" % u, end='')
if u in data:
if u in use_data:
num += 1
d = data.get (u, defaults)
print ("%6s," % d[0], end='')
d = use_data.get (u)
if d is not None:
d = d[0]
elif u in unicode_data[4]:
d = 'O'
else:
d = 'WJ'
print ("%6s," % d, end='')
total += end - start + 1
used += num
if block:
last_block = block
uu = sorted (data.keys ())
uu = sorted (use_data.keys ())
last = -100000
num = 0
@ -491,19 +474,19 @@ print ("static const uint8_t use_table[] = {")
for u in uu:
if u <= last:
continue
if data[u][0] == 'O':
if use_data[u][0] == 'O':
continue
block = data[u][1]
block = use_data[u][1]
start = u//8*8
end = start+1
while end in uu and block == data[end][1]:
while end in uu and block == use_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)
print_block (None, last+1, start-1, use_data)
else:
if last >= 0:
ends.append (last + 1)
@ -513,7 +496,7 @@ for u in uu:
print ("#define use_offset_0x%04xu %d" % (start, offset))
starts.append (start)
print_block (block, start, end, data)
print_block (block, start, end, use_data)
last = end
ends.append (last + 1)
offset += ends[-1] - starts[-1]
@ -524,8 +507,9 @@ page_bits = 12
print ("}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy))
print ()
print ("static inline uint8_t")
print ("hb_use_get_category (hb_codepoint_t u)")
print ("hb_use_get_category (hb_glyph_info_t info)")
print ("{")
print (" hb_codepoint_t u = info.codepoint;")
print (" switch (u >> %d)" % page_bits)
print (" {")
pages = set([u>>page_bits for u in starts+ends])
@ -540,7 +524,9 @@ for p in sorted(pages):
print (" default:")
print (" break;")
print (" }")
print (" return USE(O);")
print (" if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED)")
print (" return WJ;")
print (" return O;")
print ("}")
print ()
for k in sorted(use_mapping.keys()):

Просмотреть файл

@ -108,7 +108,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
{HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
{HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT, (hb_aat_layout_feature_selector_t) 7},
{HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
{HB_TAG ('h','i','s','t'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
{HB_TAG ('h','i','s','t'), (hb_aat_layout_feature_type_t) 40, (hb_aat_layout_feature_selector_t) 0, (hb_aat_layout_feature_selector_t) 1},
{HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF},
{HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
{HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION, HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION},
@ -170,6 +170,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
{HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF},
{HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
{HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
{HB_TAG ('v','r','t','r'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, (hb_aat_layout_feature_selector_t) 2, (hb_aat_layout_feature_selector_t) 3},
{HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
};

Просмотреть файл

@ -226,14 +226,8 @@ struct
template <typename T> constexpr auto
impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
/* Sadly, we must give further hints to VS2015 to build the following template item */
#if !defined (_MSC_VER) || defined (__clang__) || (_MSC_VER >= 1910)
template <typename T> constexpr auto
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
#else
template <typename T> constexpr auto
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v).hash ())>>{} (hb_deref (v)))
#endif
template <typename T,
hb_enable_if (std::is_integral<T>::value)> constexpr auto
@ -504,7 +498,7 @@ struct hb_pair_t
template <typename Q1, typename Q2,
hb_enable_if (hb_is_convertible (T1, Q1) &&
hb_is_convertible (T2, T2))>
hb_is_convertible (T2, Q2))>
operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
hb_pair_t<T1, T2> reverse () const

Просмотреть файл

@ -179,6 +179,8 @@ struct hb_bit_page_t
typedef unsigned long long elt_t;
static constexpr unsigned PAGE_BITS = 512;
static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
static constexpr unsigned PAGE_BITS_LOG_2 = 9;
static_assert (1 << PAGE_BITS_LOG_2 == PAGE_BITS, "");
static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
@ -186,6 +188,9 @@ struct hb_bit_page_t
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
static constexpr unsigned ELT_BITS_LOG_2 = 6;
static_assert (1 << ELT_BITS_LOG_2 == ELT_BITS, "");
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
static constexpr unsigned BITS = sizeof (vector_t) * 8;
static constexpr unsigned MASK = BITS - 1;

Просмотреть файл

@ -203,7 +203,7 @@ struct hb_bit_set_t
bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
if (!count) return true;
if (unlikely (!count)) return true;
dirty ();
hb_codepoint_t g = *array;
hb_codepoint_t last_g = g;
@ -222,7 +222,7 @@ struct hb_bit_set_t
if (v || page) /* The v check is to optimize out the page check if v is true. */
page->add (g);
array = (const T *) ((const char *) array + stride);
array = &StructAtOffsetUnaligned<T> (array, stride);
count--;
}
while (count && (g = *array, g < end));
@ -809,8 +809,8 @@ struct hb_bit_set_t
}
page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; }
hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; }
};

Просмотреть файл

@ -478,7 +478,7 @@ _resume:
case 18:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimeters. */
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@ -535,7 +535,7 @@ _resume:
case 16:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimeters. */
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@ -635,7 +635,7 @@ _resume:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimeters. */
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@ -645,7 +645,7 @@ _resume:
case 17:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimeters. */
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@ -674,7 +674,7 @@ _resume:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimeters. */
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@ -701,7 +701,7 @@ _resume:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimeters. */
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@ -733,7 +733,7 @@ _again:
case 16:
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimeters. */
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@ -820,7 +820,7 @@ _again:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
/* TODO Unescape delimeters. */
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))

Просмотреть файл

@ -56,7 +56,7 @@ action ensure_glyphs { if (unlikely (!buffer->ensure_glyphs ())) return false; }
action ensure_unicode { if (unlikely (!buffer->ensure_unicode ())) return false; }
action parse_glyph {
/* TODO Unescape delimeters. */
/* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))

Просмотреть файл

@ -397,7 +397,8 @@ hb_buffer_t::verify (hb_buffer_t *text_buffer,
ret = false;
if (!buffer_verify_unsafe_to_break (this, text_buffer, font, features, num_features, shapers))
ret = false;
if (!buffer_verify_unsafe_to_concat (this, text_buffer, font, features, num_features, shapers))
if ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) != 0 &&
!buffer_verify_unsafe_to_concat (this, text_buffer, font, features, num_features, shapers))
ret = false;
if (!ret)
{

Просмотреть файл

@ -295,7 +295,6 @@ hb_buffer_t::clear ()
idx = 0;
len = 0;
out_len = 0;
out_info = info;
memset (context, 0, sizeof context);
@ -405,6 +404,7 @@ hb_buffer_t::sync ()
reset:
have_output = false;
out_len = 0;
out_info = info;
idx = 0;
}

Просмотреть файл

@ -117,7 +117,7 @@ typedef struct hb_glyph_info_t {
* from there, and repeat.
* At the start of next line a similar algorithm can
* be implemented. That is: 1. Iterate forward from
* the line-break position untill the first cluster
* the line-break position until the first cluster
* start position that is NOT unsafe-to-concat, 2.
* shape the segment from beginning of the line to
* that position, 3. check whether the resulting
@ -137,7 +137,11 @@ typedef struct hb_glyph_info_t {
* clusters.
* The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will
* always imply this flag.
* Since: 3.3.0
* To use this flag, you must enable the buffer flag
* @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT during
* shaping, otherwise the buffer flag will not be
* reliably produced.
* Since: 4.0.0
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*
* Flags for #hb_glyph_info_t.
@ -365,6 +369,10 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* handler is installed on the buffer, or a message is written
* to standard error. In either case, the shaping result might
* be modified to show the failed output. Since: 3.4.0
* @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT:
* flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
* glyph-flag should be produced by the shaper. By default
* it will not be produced since it incurs a cost. Since: 4.0.0
*
* Flags for #hb_buffer_t.
*
@ -377,7 +385,8 @@ typedef enum { /*< flags >*/
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u,
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u,
HB_BUFFER_FLAG_VERIFY = 0x00000020u
HB_BUFFER_FLAG_VERIFY = 0x00000020u,
HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u
} hb_buffer_flags_t;
HB_EXTERN void

Просмотреть файл

@ -460,6 +460,8 @@ struct hb_buffer_t
}
void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
{
if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
return;
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
true);
@ -472,6 +474,8 @@ struct hb_buffer_t
}
void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
{
if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
return;
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
false, true);

Просмотреть файл

@ -130,6 +130,16 @@ typedef union _hb_var_int_t {
int8_t i8[4];
} hb_var_int_t;
typedef union _hb_var_num_t {
float f;
uint32_t u32;
int32_t i32;
uint16_t u16[2];
int16_t i16[2];
uint8_t u8[4];
int8_t i8[4];
} hb_var_num_t;
/* hb_tag_t */

Просмотреть файл

@ -85,6 +85,7 @@
#ifdef HB_MINI
#define HB_NO_AAT
#define HB_NO_LEGACY
#define HB_NO_BORING_EXPANSION
#endif
#if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H)

Просмотреть файл

@ -897,7 +897,7 @@ resize_and_retry:
DEBUG_MSG (CORETEXT, nullptr, "Num runs: %d", num_runs);
buffer->len = 0;
uint32_t status_and = ~0, status_or = 0;
uint32_t status_or = 0;
CGFloat 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
@ -918,7 +918,6 @@ resize_and_retry:
CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex (glyph_runs, i));
CTRunStatus run_status = CTRunGetStatus (run);
status_or |= run_status;
status_and &= run_status;
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
CGFloat run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr);
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
@ -1140,21 +1139,6 @@ resize_and_retry:
buffer->len += num_glyphs;
}
/* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
* or if it does, it doesn't respect it. So we get runs with wrong
* directions. As such, disable the assert... It wouldn't crash, but
* cursoring will be off...
*
* https://crbug.com/419769
*/
if (false)
{
/* Make sure all runs had the expected direction. */
HB_UNUSED bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
assert (bool (status_or & kCTRunStatusRightToLeft) == backward);
}
buffer->clear_positions ();
unsigned int count = buffer->len;

Просмотреть файл

@ -25,237 +25,313 @@
#include "hb.hh"
#ifndef HB_NO_DRAW
#ifdef HB_EXPERIMENTAL_API
#include "hb-draw.hh"
#include "hb-ot.h"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-cff1-table.hh"
#include "hb-ot-cff2-table.hh"
/**
* hb_draw_funcs_set_move_to_func:
* @funcs: draw functions object
* @move_to: move-to callback
* SECTION:hb-draw
* @title: hb-draw
* @short_description: Glyph drawing
* @include: hb.h
*
* Sets move-to callback to the draw functions object.
*
* Since: EXPERIMENTAL
* Functions for drawing (extracting) glyph shapes.
**/
void
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
hb_draw_move_to_func_t move_to)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->move_to = move_to;
}
/**
* hb_draw_funcs_set_line_to_func:
* @funcs: draw functions object
* @line_to: line-to callback
*
* Sets line-to callback to the draw functions object.
*
* Since: EXPERIMENTAL
**/
void
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
hb_draw_line_to_func_t line_to)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->line_to = line_to;
}
static void
hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
hb_draw_state_t *st HB_UNUSED,
float to_x HB_UNUSED, float to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
/**
* hb_draw_funcs_set_quadratic_to_func:
* @funcs: draw functions object
* @move_to: quadratic-to callback
*
* Sets quadratic-to callback to the draw functions object.
*
* Since: EXPERIMENTAL
**/
void
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
hb_draw_quadratic_to_func_t quadratic_to)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->quadratic_to = quadratic_to;
funcs->is_quadratic_to_set = true;
}
static void
hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
hb_draw_state_t *st HB_UNUSED,
float to_x HB_UNUSED, float to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
/**
* hb_draw_funcs_set_cubic_to_func:
* @funcs: draw functions
* @cubic_to: cubic-to callback
*
* Sets cubic-to callback to the draw functions object.
*
* Since: EXPERIMENTAL
**/
void
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
hb_draw_cubic_to_func_t cubic_to)
static void
hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float control_x, float control_y,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->cubic_to = cubic_to;
}
/**
* hb_draw_funcs_set_close_path_func:
* @funcs: draw functions object
* @close_path: close-path callback
*
* Sets close-path callback to the draw functions object.
*
* Since: EXPERIMENTAL
**/
void
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
hb_draw_close_path_func_t close_path)
{
if (unlikely (hb_object_is_immutable (funcs))) return;
funcs->close_path = close_path;
dfuncs->emit_cubic_to (draw_data, *st,
(st->current_x + 2.f * control_x) / 3.f,
(st->current_y + 2.f * control_y) / 3.f,
(to_x + 2.f * control_x) / 3.f,
(to_y + 2.f * control_y) / 3.f,
to_x, to_y);
}
static void
_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
hb_draw_state_t *st HB_UNUSED,
float control1_x HB_UNUSED, float control1_y HB_UNUSED,
float control2_x HB_UNUSED, float control2_y HB_UNUSED,
float to_x HB_UNUSED, float to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
hb_draw_state_t *st HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
static void
_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
void *user_data HB_UNUSED) {}
#define HB_DRAW_FUNC_IMPLEMENT(name) \
\
void \
hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \
hb_draw_##name##_func_t func, \
void *user_data, \
hb_destroy_func_t destroy) \
{ \
if (hb_object_is_immutable (dfuncs)) \
return; \
\
if (dfuncs->destroy.name) \
dfuncs->destroy.name (dfuncs->user_data.name); \
\
if (func) { \
dfuncs->func.name = func; \
dfuncs->user_data.name = user_data; \
dfuncs->destroy.name = destroy; \
} else { \
dfuncs->func.name = hb_draw_##name##_nil; \
dfuncs->user_data.name = nullptr; \
dfuncs->destroy.name = nullptr; \
} \
}
static void
_close_path_nil (void *user_data HB_UNUSED) {}
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
/**
* hb_draw_funcs_create:
* hb_draw_funcs_create: (Xconstructor)
*
* Creates a new draw callbacks object.
*
* Since: EXPERIMENTAL
* Return value: (transfer full):
* A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
* reference count should be released with hb_draw_funcs_destroy when you are
* done using the #hb_draw_funcs_t. This function never returns %NULL. If
* memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
* be returned.
*
* Since: 4.0.0
**/
hb_draw_funcs_t *
hb_draw_funcs_create ()
{
hb_draw_funcs_t *funcs;
if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ())))
hb_draw_funcs_t *dfuncs;
if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ())))
return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil;
funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil;
funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil;
funcs->is_quadratic_to_set = false;
funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil;
funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil;
return funcs;
dfuncs->func = Null (hb_draw_funcs_t).func;
return dfuncs;
}
DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
{
HB_OBJECT_HEADER_STATIC,
{
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
}
};
/**
* hb_draw_funcs_reference:
* @funcs: draw functions
* hb_draw_funcs_reference: (skip)
* @dfuncs: draw functions
*
* Add to callbacks object refcount.
* Increases the reference count on @dfuncs by one. This prevents @buffer from
* being destroyed until a matching call to hb_draw_funcs_destroy() is made.
*
* Returns: The same object.
* Since: EXPERIMENTAL
* Return value: (transfer full):
* The referenced #hb_draw_funcs_t.
*
* Since: 4.0.0
**/
hb_draw_funcs_t *
hb_draw_funcs_reference (hb_draw_funcs_t *funcs)
hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs)
{
return hb_object_reference (funcs);
return hb_object_reference (dfuncs);
}
/**
* hb_draw_funcs_destroy:
* @funcs: draw functions
* hb_draw_funcs_destroy: (skip)
* @dfuncs: draw functions
*
* Decreases refcount of callbacks object and deletes the object if it reaches
* to zero.
* Deallocate the @dfuncs.
* Decreases the reference count on @dfuncs by one. If the result is zero, then
* @dfuncs and all associated resources are freed. See hb_draw_funcs_reference().
*
* Since: EXPERIMENTAL
* Since: 4.0.0
**/
void
hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
{
if (!hb_object_destroy (funcs)) return;
if (!hb_object_destroy (dfuncs)) return;
hb_free (funcs);
#define HB_DRAW_FUNC_IMPLEMENT(name) \
if (dfuncs->destroy.name) dfuncs->destroy.name (dfuncs->user_data.name);
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
hb_free (dfuncs);
}
/**
* hb_draw_funcs_make_immutable:
* @funcs: draw functions
* @dfuncs: draw functions
*
* Makes funcs object immutable.
* Makes @dfuncs object immutable.
*
* Since: EXPERIMENTAL
* Since: 4.0.0
**/
void
hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs)
hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
{
if (hb_object_is_immutable (funcs))
if (hb_object_is_immutable (dfuncs))
return;
hb_object_make_immutable (funcs);
hb_object_make_immutable (dfuncs);
}
/**
* hb_draw_funcs_is_immutable:
* @funcs: draw functions
* @dfuncs: draw functions
*
* Checks whether funcs is immutable.
* Checks whether @dfuncs is immutable.
*
* Returns: If is immutable.
* Since: EXPERIMENTAL
* Return value: %true if @dfuncs is immutable, %false otherwise
*
* Since: 4.0.0
**/
hb_bool_t
hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs)
hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs)
{
return hb_object_is_immutable (funcs);
return hb_object_is_immutable (dfuncs);
}
/**
* hb_draw_move_to:
* @dfuncs: draw functions
* @draw_data: associated draw data passed by the caller
* @st: current draw state
* @to_x: X component of target point
* @to_y: Y component of target point
*
* Perform a "move-to" draw operation.
*
* Since: 4.0.0
**/
void
hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float to_x, float to_y)
{
dfuncs->move_to (draw_data, *st,
to_x, to_y);
}
/**
* hb_font_draw_glyph:
* @font: a font object
* @glyph: a glyph id
* @funcs: draw callbacks object
* @user_data: parameter you like be passed to the callbacks when are called
* hb_draw_line_to:
* @dfuncs: draw functions
* @draw_data: associated draw data passed by the caller
* @st: current draw state
* @to_x: X component of target point
* @to_y: Y component of target point
*
* Draw a glyph.
* Perform a "line-to" draw operation.
*
* Returns: Whether the font had the glyph and the operation completed successfully.
* Since: EXPERIMENTAL
* Since: 4.0.0
**/
hb_bool_t
hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
const hb_draw_funcs_t *funcs,
void *user_data)
void
hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float to_x, float to_y)
{
if (unlikely (funcs == &Null (hb_draw_funcs_t) ||
glyph >= font->face->get_num_glyphs ()))
return false;
draw_helper_t draw_helper (funcs, user_data);
if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true;
#ifndef HB_NO_CFF
if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true;
if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true;
#endif
return false;
dfuncs->line_to (draw_data, *st,
to_x, to_y);
}
#endif
/**
* hb_draw_quadratic_to:
* @dfuncs: draw functions
* @draw_data: associated draw data passed by the caller
* @st: current draw state
* @control_x: X component of control point
* @control_y: Y component of control point
* @to_x: X component of target point
* @to_y: Y component of target point
*
* Perform a "quadratic-to" draw operation.
*
* Since: 4.0.0
**/
void
hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float control_x, float control_y,
float to_x, float to_y)
{
dfuncs->quadratic_to (draw_data, *st,
control_x, control_y,
to_x, to_y);
}
/**
* hb_draw_cubic_to:
* @dfuncs: draw functions
* @draw_data: associated draw data passed by the caller
* @st: current draw state
* @control1_x: X component of first control point
* @control1_y: Y component of first control point
* @control2_x: X component of second control point
* @control2_y: Y component of second control point
* @to_x: X component of target point
* @to_y: Y component of target point
*
* Perform a "cubic-to" draw operation.
*
* Since: 4.0.0
**/
void
hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y)
{
dfuncs->cubic_to (draw_data, *st,
control1_x, control1_y,
control2_x, control2_y,
to_x, to_y);
}
/**
* hb_draw_close_path:
* @dfuncs: draw functions
* @draw_data: associated draw data passed by the caller
* @st: current draw state
*
* Perform a "close-path" draw operation.
*
* Since: 4.0.0
**/
void
hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st)
{
dfuncs->close_path (draw_data, *st);
}
#endif

Просмотреть файл

@ -33,65 +33,292 @@
HB_BEGIN_DECLS
#ifdef HB_EXPERIMENTAL_API
typedef void (*hb_draw_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
typedef void (*hb_draw_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
typedef void (*hb_draw_quadratic_to_func_t) (hb_position_t control_x, hb_position_t control_y,
hb_position_t to_x, hb_position_t to_y,
void *user_data);
typedef void (*hb_draw_cubic_to_func_t) (hb_position_t control1_x, hb_position_t control1_y,
hb_position_t control2_x, hb_position_t control2_y,
hb_position_t to_x, hb_position_t to_y,
void *user_data);
typedef void (*hb_draw_close_path_func_t) (void *user_data);
/**
* hb_draw_state_t
* @path_open: Whether there is an open path
* @path_start_x: X component of the start of current path
* @path_start_y: Y component of the start of current path
* @current_x: X component of current point
* @current_y: Y component of current point
*
* Current drawing state.
*
* Since: 4.0.0
**/
typedef struct hb_draw_state_t {
hb_bool_t path_open;
float path_start_x;
float path_start_y;
float current_x;
float current_y;
/*< private >*/
hb_var_num_t reserved1;
hb_var_num_t reserved2;
hb_var_num_t reserved3;
hb_var_num_t reserved4;
hb_var_num_t reserved5;
hb_var_num_t reserved6;
hb_var_num_t reserved7;
} hb_draw_state_t;
/**
* HB_DRAW_STATE_DEFAULT:
*
* The default #hb_draw_state_t at the start of glyph drawing.
*/
#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}}
/**
* hb_draw_funcs_t:
*
* Glyph draw callbacks.
*
* _move_to, _line_to and _cubic_to calls are necessary to be defined but we
* translate _quadratic_to calls to _cubic_to if the callback isn't defined.
* #hb_draw_move_to_func_t, #hb_draw_line_to_func_t and
* #hb_draw_cubic_to_func_t calls are necessary to be defined but we translate
* #hb_draw_quadratic_to_func_t calls to #hb_draw_cubic_to_func_t if the
* callback isn't defined.
*
* Since: EXPERIMENTAL
* Since: 4.0.0
**/
typedef struct hb_draw_funcs_t hb_draw_funcs_t;
HB_EXTERN void
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
hb_draw_move_to_func_t move_to);
HB_EXTERN void
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
hb_draw_line_to_func_t line_to);
/**
* hb_draw_move_to_func_t:
* @dfuncs: draw functions object
* @draw_data: The data accompanying the draw functions
* @st: current draw state
* @to_x: X component of target point
* @to_y: Y component of target point
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_draw_funcs_t to perform a "move-to" draw
* operation.
*
* Since: 4.0.0
*
**/
typedef void (*hb_draw_move_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float to_x, float to_y,
void *user_data);
HB_EXTERN void
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
hb_draw_quadratic_to_func_t quadratic_to);
/**
* hb_draw_line_to_func_t:
* @dfuncs: draw functions object
* @draw_data: The data accompanying the draw functions
* @st: current draw state
* @to_x: X component of target point
* @to_y: Y component of target point
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_draw_funcs_t to perform a "line-to" draw
* operation.
*
* Since: 4.0.0
*
**/
typedef void (*hb_draw_line_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float to_x, float to_y,
void *user_data);
HB_EXTERN void
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
hb_draw_cubic_to_func_t cubic_to);
/**
* hb_draw_quadratic_to_func_t:
* @dfuncs: draw functions object
* @draw_data: The data accompanying the draw functions
* @st: current draw state
* @control_x: X component of control point
* @control_y: Y component of control point
* @to_x: X component of target point
* @to_y: Y component of target point
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_draw_funcs_t to perform a "quadratic-to" draw
* operation.
*
* Since: 4.0.0
*
**/
typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float control_x, float control_y,
float to_x, float to_y,
void *user_data);
/**
* hb_draw_cubic_to_func_t:
* @dfuncs: draw functions object
* @draw_data: The data accompanying the draw functions
* @st: current draw state
* @control1_x: X component of first control point
* @control1_y: Y component of first control point
* @control2_x: X component of second control point
* @control2_y: Y component of second control point
* @to_x: X component of target point
* @to_y: Y component of target point
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_draw_funcs_t to perform a "cubic-to" draw
* operation.
*
* Since: 4.0.0
*
**/
typedef void (*hb_draw_cubic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y,
void *user_data);
/**
* hb_draw_close_path_func_t:
* @dfuncs: draw functions object
* @draw_data: The data accompanying the draw functions
* @st: current draw state
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_draw_funcs_t to perform a "close-path" draw
* operation.
*
* Since: 4.0.0
*
**/
typedef void (*hb_draw_close_path_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
void *user_data);
/**
* hb_draw_funcs_set_move_to_func:
* @dfuncs: draw functions object
* @func: (closure user_data) (destroy destroy) (scope notified): move-to callback
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets move-to callback to the draw functions object.
*
* Since: 4.0.0
**/
HB_EXTERN void
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
hb_draw_close_path_func_t close_path);
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *dfuncs,
hb_draw_move_to_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_draw_funcs_set_line_to_func:
* @dfuncs: draw functions object
* @func: (closure user_data) (destroy destroy) (scope notified): line-to callback
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets line-to callback to the draw functions object.
*
* Since: 4.0.0
**/
HB_EXTERN void
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *dfuncs,
hb_draw_line_to_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_draw_funcs_set_quadratic_to_func:
* @dfuncs: draw functions object
* @func: (closure user_data) (destroy destroy) (scope notified): quadratic-to callback
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets quadratic-to callback to the draw functions object.
*
* Since: 4.0.0
**/
HB_EXTERN void
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *dfuncs,
hb_draw_quadratic_to_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_draw_funcs_set_cubic_to_func:
* @dfuncs: draw functions
* @func: (closure user_data) (destroy destroy) (scope notified): cubic-to callback
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets cubic-to callback to the draw functions object.
*
* Since: 4.0.0
**/
HB_EXTERN void
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *dfuncs,
hb_draw_cubic_to_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_draw_funcs_set_close_path_func:
* @dfuncs: draw functions object
* @func: (closure user_data) (destroy destroy) (scope notified): close-path callback
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets close-path callback to the draw functions object.
*
* Since: 4.0.0
**/
HB_EXTERN void
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *dfuncs,
hb_draw_close_path_func_t func,
void *user_data, hb_destroy_func_t destroy);
HB_EXTERN hb_draw_funcs_t *
hb_draw_funcs_create (void);
HB_EXTERN hb_draw_funcs_t *
hb_draw_funcs_reference (hb_draw_funcs_t *funcs);
hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
hb_draw_funcs_destroy (hb_draw_funcs_t *funcs);
hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs);
hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs);
HB_EXTERN hb_bool_t
hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs);
#endif
hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float to_x, float to_y);
HB_EXTERN void
hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float to_x, float to_y);
HB_EXTERN void
hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float control_x, float control_y,
float to_x, float to_y);
HB_EXTERN void
hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y);
HB_EXTERN void
hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
hb_draw_state_t *st);
HB_END_DECLS

Просмотреть файл

@ -27,113 +27,205 @@
#include "hb.hh"
#ifdef HB_EXPERIMENTAL_API
/*
* hb_draw_funcs_t
*/
#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \
HB_DRAW_FUNC_IMPLEMENT (move_to) \
HB_DRAW_FUNC_IMPLEMENT (line_to) \
HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \
HB_DRAW_FUNC_IMPLEMENT (cubic_to) \
HB_DRAW_FUNC_IMPLEMENT (close_path) \
/* ^--- Add new callbacks here */
struct hb_draw_funcs_t
{
hb_object_header_t header;
hb_draw_move_to_func_t move_to;
hb_draw_line_to_func_t line_to;
hb_draw_quadratic_to_func_t quadratic_to;
bool is_quadratic_to_set;
hb_draw_cubic_to_func_t cubic_to;
hb_draw_close_path_func_t close_path;
};
struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name;
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
} func;
struct draw_helper_t
{
draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_)
{
funcs = funcs_;
user_data = user_data_;
path_open = false;
path_start_x = current_x = path_start_y = current_y = 0;
}
~draw_helper_t () { end_path (); }
struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
} user_data;
void move_to (hb_position_t x, hb_position_t y)
struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
} destroy;
void emit_move_to (void *draw_data, hb_draw_state_t &st,
float to_x, float to_y)
{ func.move_to (this, draw_data, &st,
to_x, to_y,
user_data.move_to); }
void emit_line_to (void *draw_data, hb_draw_state_t &st,
float to_x, float to_y)
{ func.line_to (this, draw_data, &st,
to_x, to_y,
user_data.line_to); }
void emit_quadratic_to (void *draw_data, hb_draw_state_t &st,
float control_x, float control_y,
float to_x, float to_y)
{ func.quadratic_to (this, draw_data, &st,
control_x, control_y,
to_x, to_y,
user_data.quadratic_to); }
void emit_cubic_to (void *draw_data, hb_draw_state_t &st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y)
{ func.cubic_to (this, draw_data, &st,
control1_x, control1_y,
control2_x, control2_y,
to_x, to_y,
user_data.cubic_to); }
void emit_close_path (void *draw_data, hb_draw_state_t &st)
{ func.close_path (this, draw_data, &st,
user_data.close_path); }
void move_to (void *draw_data, hb_draw_state_t &st,
float to_x, float to_y)
{
if (path_open) end_path ();
current_x = path_start_x = x;
current_y = path_start_y = y;
if (st.path_open) close_path (draw_data, st);
st.current_x = to_x;
st.current_y = to_y;
}
void line_to (hb_position_t x, hb_position_t y)
void line_to (void *draw_data, hb_draw_state_t &st,
float to_x, float to_y)
{
if (equal_to_current (x, y)) return;
if (!path_open) start_path ();
funcs->line_to (x, y, user_data);
current_x = x;
current_y = y;
if (!st.path_open) start_path (draw_data, st);
emit_line_to (draw_data, st, to_x, to_y);
st.current_x = to_x;
st.current_y = to_y;
}
void
quadratic_to (hb_position_t control_x, hb_position_t control_y,
hb_position_t to_x, hb_position_t to_y)
quadratic_to (void *draw_data, hb_draw_state_t &st,
float control_x, float control_y,
float to_x, float to_y)
{
if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y))
return;
if (!path_open) start_path ();
if (funcs->is_quadratic_to_set)
funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data);
else
funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f),
roundf ((current_y + 2.f * control_y) / 3.f),
roundf ((to_x + 2.f * control_x) / 3.f),
roundf ((to_y + 2.f * control_y) / 3.f),
to_x, to_y, user_data);
current_x = to_x;
current_y = to_y;
if (!st.path_open) start_path (draw_data, st);
emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
st.current_x = to_x;
st.current_y = to_y;
}
void
cubic_to (hb_position_t control1_x, hb_position_t control1_y,
hb_position_t control2_x, hb_position_t control2_y,
hb_position_t to_x, hb_position_t to_y)
cubic_to (void *draw_data, hb_draw_state_t &st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y)
{
if (equal_to_current (control1_x, control1_y) &&
equal_to_current (control2_x, control2_y) &&
equal_to_current (to_x, to_y))
return;
if (!path_open) start_path ();
funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data);
current_x = to_x;
current_y = to_y;
if (!st.path_open) start_path (draw_data, st);
emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
st.current_x = to_x;
st.current_y = to_y;
}
void end_path ()
void
close_path (void *draw_data, hb_draw_state_t &st)
{
if (path_open)
if (st.path_open)
{
if ((path_start_x != current_x) || (path_start_y != current_y))
funcs->line_to (path_start_x, path_start_y, user_data);
funcs->close_path (user_data);
if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y))
emit_line_to (draw_data, st, st.path_start_x, st.path_start_y);
emit_close_path (draw_data, st);
}
path_open = false;
path_start_x = current_x = path_start_y = current_y = 0;
st.path_open = false;
st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0;
}
protected:
bool equal_to_current (hb_position_t x, hb_position_t y)
{ return current_x == x && current_y == y; }
void start_path ()
void start_path (void *draw_data, hb_draw_state_t &st)
{
if (path_open) end_path ();
path_open = true;
funcs->move_to (path_start_x, path_start_y, user_data);
assert (!st.path_open);
emit_move_to (draw_data, st, st.current_x, st.current_y);
st.path_open = true;
st.path_start_x = st.current_x;
st.path_start_y = st.current_y;
}
};
DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
struct hb_draw_session_t
{
hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f)
: slant {slant_}, not_slanted {slant == 0.f},
funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
{}
~hb_draw_session_t () { close_path (); }
void move_to (float to_x, float to_y)
{
if (likely (not_slanted))
funcs->move_to (draw_data, st,
to_x, to_y);
else
funcs->move_to (draw_data, st,
to_x + to_y * slant, to_y);
}
void line_to (float to_x, float to_y)
{
if (likely (not_slanted))
funcs->line_to (draw_data, st,
to_x, to_y);
else
funcs->line_to (draw_data, st,
to_x + to_y * slant, to_y);
}
void
quadratic_to (float control_x, float control_y,
float to_x, float to_y)
{
if (likely (not_slanted))
funcs->quadratic_to (draw_data, st,
control_x, control_y,
to_x, to_y);
else
funcs->quadratic_to (draw_data, st,
control_x + control_y * slant, control_y,
to_x + to_y * slant, to_y);
}
void
cubic_to (float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y)
{
if (likely (not_slanted))
funcs->cubic_to (draw_data, st,
control1_x, control1_y,
control2_x, control2_y,
to_x, to_y);
else
funcs->cubic_to (draw_data, st,
control1_x + control1_y * slant, control1_y,
control2_x + control2_y * slant, control2_y,
to_x + to_y * slant, to_y);
}
void close_path ()
{
funcs->close_path (draw_data, st);
}
hb_position_t path_start_x;
hb_position_t path_start_y;
hb_position_t current_x;
hb_position_t current_y;
bool path_open;
const hb_draw_funcs_t *funcs;
void *user_data;
protected:
float slant;
bool not_slanted;
hb_draw_funcs_t *funcs;
void *draw_data;
hb_draw_state_t st;
};
#endif
#endif /* HB_DRAW_HH */

Просмотреть файл

@ -29,6 +29,7 @@
#include "hb.hh"
#include "hb-font.hh"
#include "hb-draw.hh"
#include "hb-machinery.hh"
#include "hb-ot.h"
@ -501,6 +502,136 @@ hb_font_get_glyph_from_name_default (hb_font_t *font,
return font->parent->get_glyph_from_name (name, len, glyph);
}
static void
hb_font_get_glyph_shape_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs,
void *draw_data,
void *user_data HB_UNUSED)
{
}
typedef struct hb_font_get_glyph_shape_default_adaptor_t {
hb_draw_funcs_t *draw_funcs;
void *draw_data;
float x_scale;
float y_scale;
} hb_font_get_glyph_shape_default_adaptor_t;
static void
hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
void *draw_data,
hb_draw_state_t *st,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
x_scale * to_x, y_scale * to_y);
}
static void
hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_draw_state_t *st,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
st->current_x *= x_scale;
st->current_y *= y_scale;
adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
x_scale * to_x, y_scale * to_y);
}
static void
hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_draw_state_t *st,
float control_x, float control_y,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
st->current_x *= x_scale;
st->current_y *= y_scale;
adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
x_scale * control_x, y_scale * control_y,
x_scale * to_x, y_scale * to_y);
}
static void
hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_draw_state_t *st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
float x_scale = adaptor->x_scale;
float y_scale = adaptor->y_scale;
st->current_x *= x_scale;
st->current_y *= y_scale;
adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
x_scale * control1_x, y_scale * control1_y,
x_scale * control2_x, y_scale * control2_y,
x_scale * to_x, y_scale * to_y);
}
static void
hb_draw_close_path_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
hb_draw_state_t *st,
void *user_data HB_UNUSED)
{
hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
adaptor->draw_funcs->emit_close_path (adaptor->draw_data, *st);
}
static const hb_draw_funcs_t _hb_draw_funcs_default = {
HB_OBJECT_HEADER_STATIC,
{
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_default,
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
}
};
static void
hb_font_get_glyph_shape_default (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs,
void *draw_data,
void *user_data HB_UNUSED)
{
hb_font_get_glyph_shape_default_adaptor_t adaptor = {
draw_funcs,
draw_data,
(float) font->x_scale / (float) font->parent->x_scale,
(float) font->y_scale / (float) font->parent->y_scale
};
font->parent->get_glyph_shape (glyph,
const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default),
&adaptor);
}
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
{
HB_OBJECT_HEADER_STATIC,
@ -1168,6 +1299,26 @@ hb_font_get_glyph_from_name (hb_font_t *font,
return font->get_glyph_from_name (name, len, glyph);
}
/**
* hb_font_get_glyph_shape:
* @font: #hb_font_t to work upon
* @glyph: : The glyph ID
* @dfuncs: #hb_draw_funcs_t to draw to
* @draw_data: User data to pass to draw callbacks
*
* Fetches the glyph shape that corresponds to a glyph in the specified @font.
* The shape is returned by way of calls to the callsbacks of the @dfuncs
* objects, with @draw_data passed to them.
*
* Since: 4.0.0
**/
void
hb_font_get_glyph_shape (hb_font_t *font,
hb_codepoint_t glyph,
hb_draw_funcs_t *dfuncs, void *draw_data)
{
font->get_glyph_shape (glyph, dfuncs, draw_data);
}
/* A bit higher-level, and with fallback */
@ -1190,7 +1341,7 @@ 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);
font->get_extents_for_direction (direction, extents);
}
/**
* hb_font_get_glyph_advance_for_direction:
@ -1215,7 +1366,7 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
hb_position_t *x,
hb_position_t *y)
{
return font->get_glyph_advance_for_direction (glyph, direction, x, y);
font->get_glyph_advance_for_direction (glyph, direction, x, y);
}
/**
* hb_font_get_glyph_advances_for_direction:
@ -2044,12 +2195,16 @@ hb_font_get_ptem (hb_font_t *font)
* @slant: synthetic slant value.
*
* Sets the "synthetic slant" of a font. By default is zero.
* Synthetic slant is the graphical skew that the renderer
* applies to the font at rendering time.
* Synthetic slant is the graphical skew applied to the font
* at rendering time.
*
* HarfBuzz needs to know this value to adjust shaping results,
* metrics, and style values to match the slanted rendering.
*
* <note>Note: The glyph shape fetched via the
* hb_font_get_glyph_shape() is slanted to reflect this value
* as well.</note>
*
* <note>Note: The slant value is a ratio. For example, a
* 20% slant would be represented as a 0.2 value.</note>
*

Просмотреть файл

@ -511,6 +511,25 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
hb_codepoint_t *glyph,
void *user_data);
/**
* hb_font_get_glyph_shape_func_t:
* @font: #hb_font_t to work upon
* @font_data: @font user data pointer
* @glyph: The glyph ID to query
* @draw_funcs: The draw functions to send the shape data to
* @draw_data: The data accompanying the draw functions
* @user_data: User data pointer passed by the caller
*
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
*
* Since: 4.0.0
*
**/
typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data);
/* func setters */
@ -770,6 +789,22 @@ 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);
/**
* hb_font_funcs_set_glyph_shape_func:
* @ffuncs: A font-function structure
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
* @user_data: Data to pass to @func
* @destroy: (nullable): The function to call when @user_data is not needed anymore
*
* Sets the implementation function for #hb_font_get_glyph_shape_func_t.
*
* Since: 4.0.0
**/
HB_EXTERN void
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_shape_func_t func,
void *user_data, hb_destroy_func_t destroy);
/* func dispatch */
HB_EXTERN hb_bool_t
@ -850,6 +885,11 @@ hb_font_get_glyph_from_name (hb_font_t *font,
const char *name, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph);
HB_EXTERN void
hb_font_get_glyph_shape (hb_font_t *font,
hb_codepoint_t glyph,
hb_draw_funcs_t *dfuncs, void *draw_data);
/* high-level funcs, with fallback */
@ -1056,11 +1096,6 @@ HB_EXTERN void
hb_font_set_var_named_instance (hb_font_t *font,
unsigned instance_index);
#ifdef HB_EXPERIMENTAL_API
HB_EXTERN hb_bool_t
hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
const hb_draw_funcs_t *funcs, void *user_data);
#endif
HB_END_DECLS

Просмотреть файл

@ -57,6 +57,7 @@
HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
HB_FONT_FUNC_IMPLEMENT (glyph_name) \
HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
HB_FONT_FUNC_IMPLEMENT (glyph_shape) \
/* ^--- Add new callbacks here */
struct hb_font_funcs_t
@ -140,6 +141,8 @@ struct hb_font_t
hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
float em_fscalef_x (float v) { return em_fscalef (v, x_scale); }
float em_fscalef_y (float v) { return em_fscalef (v, y_scale); }
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
{ return em_mult (v, dir_mult (direction)); }
@ -373,6 +376,15 @@ struct hb_font_t
klass->user_data.glyph_from_name);
}
void get_glyph_shape (hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data)
{
klass->get.f.glyph_shape (this, user_data,
glyph,
draw_funcs, draw_data,
klass->user_data.glyph_shape);
}
/* A bit higher-level, and with fallback */
@ -625,7 +637,9 @@ struct hb_font_t
hb_position_t em_mult (int16_t v, int64_t mult)
{ return (hb_position_t) ((v * mult + 32768) >> 16); }
hb_position_t em_scalef (float v, int scale)
{ return (hb_position_t) roundf (v * scale / face->get_upem ()); }
{ return (hb_position_t) roundf (em_fscalef (v, scale)); }
float em_fscalef (float v, int scale)
{ return v * scale / face->get_upem (); }
float em_fscale (int16_t v, int scale)
{ return (float) v * scale / face->get_upem (); }
};

Просмотреть файл

@ -33,12 +33,14 @@
#include "hb-ft.h"
#include "hb-draw.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-cache.hh"
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
#include FT_OUTLINE_H
#include FT_TRUETYPE_TABLES_H
@ -380,6 +382,7 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
/* 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;
}
#endif
@ -565,6 +568,82 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
return true;
}
#ifndef HB_NO_DRAW
static int
_hb_ft_move_to (const FT_Vector *to,
hb_draw_session_t *drawing)
{
drawing->move_to (to->x, to->y);
return FT_Err_Ok;
}
static int
_hb_ft_line_to (const FT_Vector *to,
hb_draw_session_t *drawing)
{
drawing->line_to (to->x, to->y);
return FT_Err_Ok;
}
static int
_hb_ft_conic_to (const FT_Vector *control,
const FT_Vector *to,
hb_draw_session_t *drawing)
{
drawing->quadratic_to (control->x, control->y,
to->x, to->y);
return FT_Err_Ok;
}
static int
_hb_ft_cubic_to (const FT_Vector *control1,
const FT_Vector *control2,
const FT_Vector *to,
hb_draw_session_t *drawing)
{
drawing->cubic_to (control1->x, control1->y,
control2->x, control2->y,
to->x, to->y);
return FT_Err_Ok;
}
static void
hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
void *font_data,
hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
if (unlikely (FT_Load_Glyph (ft_face, glyph,
FT_LOAD_NO_BITMAP | ft_font->load_flags)))
return;
if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
return;
const FT_Outline_Funcs outline_funcs = {
(FT_Outline_MoveToFunc) _hb_ft_move_to,
(FT_Outline_LineToFunc) _hb_ft_line_to,
(FT_Outline_ConicToFunc) _hb_ft_conic_to,
(FT_Outline_CubicToFunc) _hb_ft_cubic_to,
0, /* shift */
0, /* delta */
};
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
FT_Outline_Decompose (&ft_face->glyph->outline,
&outline_funcs,
&draw_session);
}
#endif
static inline void free_static_ft_funcs ();
static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
@ -596,6 +675,10 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
#ifndef HB_NO_DRAW
hb_font_funcs_set_glyph_shape_func (funcs, hb_ft_get_glyph_shape, nullptr, nullptr);
#endif
hb_font_funcs_make_immutable (funcs);
hb_atexit (free_static_ft_funcs);

Просмотреть файл

@ -90,6 +90,7 @@ hb_gobject_##name##_get_type () \
HB_DEFINE_OBJECT_TYPE (buffer)
HB_DEFINE_OBJECT_TYPE (blob)
HB_DEFINE_OBJECT_TYPE (draw_funcs)
HB_DEFINE_OBJECT_TYPE (face)
HB_DEFINE_OBJECT_TYPE (font)
HB_DEFINE_OBJECT_TYPE (font_funcs)

Просмотреть файл

@ -48,6 +48,10 @@ HB_EXTERN GType
hb_gobject_buffer_get_type (void);
#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
HB_EXTERN GType
hb_gobject_draw_funcs_get_type (void);
#define HB_GOBJECT_TYPE_DRAW_FUNCS (hb_gobject_draw_funcs_get_type ())
HB_EXTERN GType
hb_gobject_face_get_type (void);
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())

Просмотреть файл

@ -273,14 +273,19 @@ struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
hb_face_lazy_loader_t<T, WheresFace>,
hb_face_t, WheresFace> {};
template <typename T, unsigned int WheresFace>
template <typename T, unsigned int WheresFace, bool core=false>
struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
hb_table_lazy_loader_t<T, WheresFace>,
hb_table_lazy_loader_t<T, WheresFace, core>,
hb_face_t, WheresFace,
hb_blob_t>
{
static hb_blob_t *create (hb_face_t *face)
{ return hb_sanitize_context_t ().reference_table<T> (face); }
{
auto c = hb_sanitize_context_t ();
if (core)
c.set_num_glyphs (0); // So we don't recurse ad infinitum...
return c.reference_table<T> (face);
}
static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
static const hb_blob_t *get_null ()

Просмотреть файл

@ -442,13 +442,12 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
return true;
}
#ifdef HB_EXPERIMENTAL_API
struct cff1_path_param_t
{
cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
draw_helper_t &draw_helper_, point_t *delta_)
hb_draw_session_t &draw_session_, point_t *delta_)
{
draw_helper = &draw_helper_;
draw_session = &draw_session_;
cff = cff_;
font = font_;
delta = delta_;
@ -458,14 +457,14 @@ struct cff1_path_param_t
{
point_t point = p;
if (delta) point.move (*delta);
draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
}
void line_to (const point_t &p)
{
point_t point = p;
if (delta) point.move (*delta);
draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
}
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
@ -477,15 +476,15 @@ struct cff1_path_param_t
point2.move (*delta);
point3.move (*delta);
}
draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()),
font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()),
font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ()));
draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()),
font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()),
font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ()));
}
void end_path () { draw_helper->end_path (); }
void end_path () { draw_session->close_path (); }
hb_font_t *font;
draw_helper_t *draw_helper;
hb_draw_session_t *draw_session;
point_t *delta;
const OT::cff1::accelerator_t *cff;
@ -513,7 +512,7 @@ struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_int
};
static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr);
hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr);
struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
{
@ -530,14 +529,14 @@ struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_pa
hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
if (unlikely (!(!env.in_seac && base && accent
&& _get_path (param.cff, param.font, base, *param.draw_helper, true)
&& _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta))))
&& _get_path (param.cff, param.font, base, *param.draw_session, true)
&& _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta))))
env.set_error ();
}
};
bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
draw_helper_t &draw_helper, bool in_seac, point_t *delta)
hb_draw_session_t &draw_session, bool in_seac, point_t *delta)
{
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
@ -546,7 +545,7 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
const byte_str_t str = (*cff->charStrings)[glyph];
interp.env.init (str, *cff, fd);
interp.env.set_in_seac (in_seac);
cff1_path_param_t param (cff, font, draw_helper, delta);
cff1_path_param_t param (cff, font, draw_session, delta);
if (unlikely (!interp.interpret (param))) return false;
/* Let's end the path specially since it is called inside seac also */
@ -555,16 +554,15 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
return true;
}
bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
return true;
#endif
return _get_path (this, font, glyph, draw_helper);
return _get_path (this, font, glyph, draw_session);
}
#endif
struct get_seac_param_t
{

Просмотреть файл

@ -1347,9 +1347,7 @@ struct cff1
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
#ifdef HB_EXPERIMENTAL_API
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
#endif
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
private:
struct gname_t

Просмотреть файл

@ -143,30 +143,29 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
return true;
}
#ifdef HB_EXPERIMENTAL_API
struct cff2_path_param_t
{
cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_)
cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
{
draw_helper = &draw_helper_;
draw_session = &draw_session_;
font = font_;
}
void move_to (const point_t &p)
{ draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
{ draw_session->move_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
void line_to (const point_t &p)
{ draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
{ draw_session->line_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
{
draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()),
font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()),
font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ()));
draw_session->cubic_to (font->em_fscalef_x (p1.x.to_real ()), font->em_fscalef_y (p1.y.to_real ()),
font->em_fscalef_x (p2.x.to_real ()), font->em_fscalef_y (p2.y.to_real ()),
font->em_fscalef_x (p3.x.to_real ()), font->em_fscalef_y (p3.y.to_real ()));
}
protected:
draw_helper_t *draw_helper;
hb_draw_session_t *draw_session;
hb_font_t *font;
};
@ -193,7 +192,7 @@ struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_int
struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
@ -206,10 +205,9 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, d
cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
const byte_str_t str = (*charStrings)[glyph];
interp.env.init (str, *this, fd, font->coords, font->num_coords);
cff2_path_param_t param (font, draw_helper);
cff2_path_param_t param (font, draw_session);
if (unlikely (!interp.interpret (param))) return false;
return true;
}
#endif
#endif

Просмотреть файл

@ -515,9 +515,7 @@ struct cff2
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
#ifdef HB_EXPERIMENTAL_API
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
#endif
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
};
typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;

Просмотреть файл

@ -714,7 +714,7 @@ struct CmapSubtableLongSegmented
if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
end = start + (hb_codepoint_t) num_glyphs - gid;
out->add_range (start, end);
out->add_range (start, hb_min (end, 0x10FFFFu));
}
}
@ -883,7 +883,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
hb_codepoint_t first = arrayZ[i].startUnicodeValue;
hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
(hb_codepoint_t) HB_UNICODE_MAX);
out->add_range (first, last);
out->add_range (first, hb_min (last, 0x10FFFFu));
}
}

Просмотреть файл

@ -32,6 +32,11 @@
#define HB_OT_FACE_TABLE_LIST_HH
#endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */
#ifndef HB_OT_CORE_TABLE
#define HB_OT_CORE_TABLE(Namespace, Type) HB_OT_TABLE (Namespace, Type)
#define _HB_OT_CORE_TABLE_UNDEF
#endif
#ifndef HB_OT_ACCELERATOR
#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
#define _HB_OT_ACCELERATOR_UNDEF
@ -46,7 +51,8 @@
/* OpenType fundamentals. */
HB_OT_TABLE (OT, head)
HB_OT_CORE_TABLE (OT, head)
HB_OT_CORE_TABLE (OT, maxp)
#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
HB_OT_ACCELERATOR (OT, cmap)
#endif
@ -74,6 +80,7 @@ HB_OT_TABLE (OT, VORG)
#endif
/* TrueType outlines. */
HB_OT_CORE_TABLE (OT, loca) // Also used to determine number of glyphs
HB_OT_ACCELERATOR (OT, glyf)
/* CFF outlines. */
@ -138,3 +145,7 @@ HB_OT_TABLE (OT, MATH)
#ifdef _HB_OT_ACCELERATOR_UNDEF
#undef HB_OT_ACCELERATOR
#endif
#ifdef _HB_OT_CORE_TABLE_UNDEF
#undef HB_OT_CORE_TABLE
#endif

Просмотреть файл

@ -63,10 +63,13 @@ struct hb_ot_face_t
hb_face_t *face; /* MUST be JUST before the lazy loaders. */
#define HB_OT_TABLE(Namespace, Type) \
hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
#define HB_OT_CORE_TABLE(Namespace, Type) \
hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type), true> Type;
#define HB_OT_ACCELERATOR(Namespace, Type) \
hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
#include "hb-ot-face-table-list.hh"
#undef HB_OT_ACCELERATOR
#undef HB_OT_CORE_TABLE
#undef HB_OT_TABLE
};

Просмотреть файл

@ -131,11 +131,25 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
for (unsigned int i = 0; i < count; i++)
if (vmtx.has_data ())
for (unsigned int i = 0; i < count; i++)
{
*first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
else
{
*first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
hb_font_extents_t font_extents;
font->get_h_extents_with_fallback (&font_extents);
hb_position_t advance = -(font_extents.ascender - font_extents.descender);
for (unsigned int i = 0; i < count; i++)
{
*first_advance = advance;
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
}
}
#endif
@ -163,9 +177,19 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
hb_glyph_extents_t extents = {0};
if (ot_face->glyf->get_extents (font, glyph, &extents))
{
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
*y = extents.y_bearing + font->em_scale_y (tsb);
if (ot_face->vmtx->has_data ())
{
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
*y = extents.y_bearing + font->em_scale_y (tsb);
return true;
}
hb_font_extents_t font_extents;
font->get_h_extents_with_fallback (&font_extents);
hb_position_t advance = font_extents.ascender - font_extents.descender;
int diff = advance - -extents.height;
*y = extents.y_bearing + (diff >> 1);
return true;
}
@ -257,6 +281,23 @@ hb_ot_get_font_v_extents (hb_font_t *font,
}
#endif
#ifndef HB_NO_DRAW
static void
hb_ot_get_glyph_shape (hb_font_t *font,
void *font_data HB_UNUSED,
hb_codepoint_t glyph,
hb_draw_funcs_t *draw_funcs, void *draw_data,
void *user_data)
{
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
if (font->face->table.glyf->get_path (font, glyph, draw_session)) return;
#ifndef HB_NO_CFF
if (font->face->table.cff1->get_path (font, glyph, draw_session)) return;
if (font->face->table.cff2->get_path (font, glyph, draw_session)) return;
#endif
}
#endif
static inline void free_static_ot_funcs ();
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
@ -279,6 +320,10 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
#endif
#ifndef HB_NO_DRAW
hb_font_funcs_set_glyph_shape_func (funcs, hb_ot_get_glyph_shape, nullptr, nullptr);
#endif
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
//hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);

Просмотреть файл

@ -936,7 +936,7 @@ struct glyf
return;
short_offset = 0 == head.indexToLocFormat;
loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
loca_table = face->table.loca.get_blob (); // Needs no destruct!
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
#ifndef HB_NO_VAR
gvar = face->table.gvar;
@ -951,7 +951,6 @@ struct glyf
}
~accelerator_t ()
{
loca_table.destroy ();
glyf_table.destroy ();
}
@ -1152,11 +1151,10 @@ struct glyf
return operation_count;
}
#ifdef HB_EXPERIMENTAL_API
struct path_builder_t
{
hb_font_t *font;
draw_helper_t *draw_helper;
hb_draw_session_t *draw_session;
struct optional_point_t
{
@ -1171,10 +1169,10 @@ struct glyf
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
} first_oncurve, first_offcurve, last_offcurve;
path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_)
path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
{
font = font_;
draw_helper = &draw_helper_;
draw_session = &draw_session_;
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
}
@ -1184,10 +1182,6 @@ struct glyf
* https://stackoverflow.com/a/20772557 */
void consume_point (const contour_point_t &point)
{
/* Skip empty contours */
if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data))
return;
bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
optional_point_t p (point.x, point.y);
if (!first_oncurve.has_data)
@ -1195,7 +1189,7 @@ struct glyf
if (is_on_curve)
{
first_oncurve = p;
draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
draw_session->move_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
}
else
{
@ -1204,7 +1198,7 @@ struct glyf
optional_point_t mid = first_offcurve.lerp (p, .5f);
first_oncurve = mid;
last_offcurve = p;
draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
draw_session->move_to (font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
}
else
first_offcurve = p;
@ -1216,22 +1210,22 @@ struct glyf
{
if (is_on_curve)
{
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
font->em_scalef_x (p.x), font->em_scalef_y (p.y));
draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
last_offcurve = optional_point_t ();
}
else
{
optional_point_t mid = last_offcurve.lerp (p, .5f);
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
last_offcurve = p;
}
}
else
{
if (is_on_curve)
draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
draw_session->line_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
else
last_offcurve = p;
}
@ -1242,24 +1236,30 @@ struct glyf
if (first_offcurve.has_data && last_offcurve.has_data)
{
optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
last_offcurve = optional_point_t ();
/* now check the rest */
}
if (first_offcurve.has_data && first_oncurve.has_data)
draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y),
font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
draw_session->quadratic_to (font->em_fscalef_x (first_offcurve.x), font->em_fscalef_y (first_offcurve.y),
font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
else if (last_offcurve.has_data && first_oncurve.has_data)
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
else if (first_oncurve.has_data)
draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
draw_session->line_to (font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
else if (first_offcurve.has_data)
{
float x = font->em_fscalef_x (first_offcurve.x), y = font->em_fscalef_x (first_offcurve.y);
draw_session->move_to (x, y);
draw_session->quadratic_to (x, y, x, y);
}
/* Getting ready for the next contour */
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
draw_helper->end_path ();
draw_session->close_path ();
}
}
void points_end () {}
@ -1269,9 +1269,8 @@ struct glyf
};
bool
get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const
{ return get_points (font, gid, path_builder_t (font, draw_helper)); }
#endif
get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
{ return get_points (font, gid, path_builder_t (font, draw_session)); }
#ifndef HB_NO_VAR
const gvar_accelerator_t *gvar;

Просмотреть файл

@ -28,6 +28,7 @@
#define HB_OT_HMTX_TABLE_HH
#include "hb-open-type.hh"
#include "hb-ot-maxp-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-ot-metrics.hh"
@ -98,12 +99,12 @@ struct hmtxvmtx
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
unsigned num_advances)
unsigned num_long_metrics)
{
unsigned idx = 0;
for (auto _ : it)
{
if (idx < num_advances)
if (idx < num_long_metrics)
{
LongMetric lm;
lm.advance = _.first;
@ -128,17 +129,17 @@ struct hmtxvmtx
if (unlikely (!table_prime)) return_trace (false);
accelerator_t _mtx (c->plan->source);
unsigned num_advances;
unsigned num_long_metrics;
{
/* Determine num_advances to encode. */
/* Determine num_long_metrics to encode. */
auto& plan = c->plan;
num_advances = plan->num_output_glyphs ();
num_long_metrics = plan->num_output_glyphs ();
hb_codepoint_t old_gid = 0;
unsigned int last_advance = plan->old_gid_for_new_gid (num_advances - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0;
while (num_advances > 1 &&
last_advance == (plan->old_gid_for_new_gid (num_advances - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0))
unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0;
while (num_long_metrics > 1 &&
last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0))
{
num_advances--;
num_long_metrics--;
}
}
@ -153,13 +154,13 @@ struct hmtxvmtx
})
;
table_prime->serialize (c->serializer, it, num_advances);
table_prime->serialize (c->serializer, it, num_long_metrics);
if (unlikely (c->serializer->in_error ()))
return_trace (false);
// Amend header num hmetrics
if (unlikely (!subset_update_header (c->plan, num_advances)))
if (unlikely (!subset_update_header (c->plan, num_long_metrics)))
return_trace (false);
return_trace (true);
@ -169,38 +170,48 @@ struct hmtxvmtx
{
friend struct hmtxvmtx;
accelerator_t (hb_face_t *face,
unsigned int default_advance_ = 0)
accelerator_t (hb_face_t *face)
{
default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
num_advances = T::is_horizontal ?
face->table.hhea->numberOfLongMetrics :
#ifndef HB_NO_VERTICAL
face->table.vhea->numberOfLongMetrics
#else
0
#endif
;
table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
/* Cap num_metrics() and num_advances() based on table length. */
unsigned int len = table.get_length ();
if (unlikely (num_advances * 4 > len))
num_advances = len / 4;
num_metrics = num_advances + (len - 4 * num_advances) / 2;
/* We MUST set num_metrics to zero if num_advances is zero.
* Our get_advance() depends on that. */
if (unlikely (!num_advances))
{
num_metrics = num_advances = 0;
table.destroy ();
table = hb_blob_get_empty ();
}
var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face);
/* Populate count variables and sort them out as we go */
unsigned int len = table.get_length ();
if (len & 1)
len--;
num_long_metrics = T::is_horizontal ?
face->table.hhea->numberOfLongMetrics :
#ifndef HB_NO_VERTICAL
face->table.vhea->numberOfLongMetrics
#else
0
#endif
;
if (unlikely (num_long_metrics * 4 > len))
num_long_metrics = len / 4;
len -= num_long_metrics * 4;
num_bearings = face->table.maxp->get_num_glyphs ();
if (unlikely (num_bearings < num_long_metrics))
num_bearings = num_long_metrics;
if (unlikely ((num_bearings - num_long_metrics) * 2 > len))
num_bearings = num_long_metrics + len / 2;
len -= (num_bearings - num_long_metrics) * 2;
/* We MUST set num_bearings to zero if num_long_metrics is zero.
* Our get_advance() depends on that. */
if (unlikely (!num_long_metrics))
num_bearings = num_long_metrics = 0;
num_advances = num_bearings + len / 2;
num_glyphs = face->get_num_glyphs ();
if (num_glyphs < num_advances)
num_glyphs = num_advances;
}
~accelerator_t ()
{
@ -208,16 +219,18 @@ struct hmtxvmtx
var_table.destroy ();
}
bool has_data () const { return (bool) num_bearings; }
int get_side_bearing (hb_codepoint_t glyph) const
{
if (glyph < num_advances)
if (glyph < num_long_metrics)
return table->longMetricZ[glyph].sb;
if (unlikely (glyph >= num_metrics))
if (unlikely (glyph >= num_bearings))
return 0;
const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
return bearings[glyph - num_advances];
const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
return bearings[glyph - num_long_metrics];
}
int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const
@ -225,7 +238,7 @@ struct hmtxvmtx
int side_bearing = get_side_bearing (glyph);
#ifndef HB_NO_VAR
if (unlikely (glyph >= num_metrics) || !font->num_coords)
if (unlikely (glyph >= num_bearings) || !font->num_coords)
return side_bearing;
if (var_table.get_length ())
@ -239,18 +252,35 @@ struct hmtxvmtx
unsigned int get_advance (hb_codepoint_t glyph) const
{
if (unlikely (glyph >= num_metrics))
{
/* If num_metrics is zero, it means we don't have the metrics table
* for this direction: return default advance. Otherwise, it means that the
* glyph index is out of bound: return zero. */
if (num_metrics)
return 0;
else
return default_advance;
}
/* OpenType case. */
if (glyph < num_bearings)
return table->longMetricZ[hb_min (glyph, (uint32_t) num_long_metrics - 1)].advance;
return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance;
/* If num_advances is zero, it means we don't have the metrics table
* for this direction: return default advance. Otherwise, there's a
* well-defined answer. */
if (unlikely (!num_advances))
return default_advance;
#ifdef HB_NO_BORING_EXPANSION
return 0;
#endif
if (unlikely (glyph >= num_glyphs))
return 0;
/* num_bearings <= glyph < num_glyphs;
* num_bearings <= num_advances */
/* TODO Optimize */
if (num_bearings == num_advances)
return get_advance (num_bearings - 1);
const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics];
return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)];
}
unsigned int get_advance (hb_codepoint_t glyph,
@ -259,7 +289,7 @@ struct hmtxvmtx
unsigned int advance = get_advance (glyph);
#ifndef HB_NO_VAR
if (unlikely (glyph >= num_metrics) || !font->num_coords)
if (unlikely (glyph >= num_bearings) || !font->num_coords)
return advance;
if (var_table.get_length ())
@ -272,8 +302,12 @@ struct hmtxvmtx
}
protected:
unsigned int num_metrics;
unsigned int num_advances;
// 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs
unsigned num_long_metrics;
unsigned num_bearings;
unsigned num_advances;
unsigned num_glyphs;
unsigned int default_advance;
private:
@ -305,6 +339,8 @@ struct hmtxvmtx
* the end. This allows a monospaced
* font to vary the side bearing
* values for each glyph. */
/*UnsizedArrayOf<UFWORD>advancesX;*/
/* TODO Document. */
public:
DEFINE_SIZE_ARRAY (0, longMetricZ);
};

Просмотреть файл

@ -41,7 +41,10 @@ namespace OT {
struct BaseCoordFormat1
{
hb_position_t get_coord () const { return coordinate; }
hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const
{
return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
}
bool sanitize (hb_sanitize_context_t *c) const
{
@ -58,10 +61,10 @@ struct BaseCoordFormat1
struct BaseCoordFormat2
{
hb_position_t get_coord () const
hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const
{
/* TODO */
return coordinate;
return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
}
bool sanitize (hb_sanitize_context_t *c) const
@ -87,9 +90,10 @@ struct BaseCoordFormat3
hb_direction_t direction) const
{
const Device &device = this+deviceTable;
return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ?
device.get_y_delta (font, var_store) :
device.get_x_delta (font, var_store));
return HB_DIRECTION_IS_HORIZONTAL (direction)
? font->em_scale_y (coordinate) + device.get_y_delta (font, var_store)
: font->em_scale_x (coordinate) + device.get_x_delta (font, var_store);
}
@ -120,8 +124,8 @@ struct BaseCoord
hb_direction_t direction) const
{
switch (u.format) {
case 1: return u.format1.get_coord ();
case 2: return u.format2.get_coord ();
case 1: return u.format1.get_coord (font, direction);
case 2: return u.format2.get_coord (font, direction);
case 3: return u.format3.get_coord (font, var_store, direction);
default:return 0;
}

Просмотреть файл

@ -60,6 +60,10 @@
#define HB_MAX_LANGSYS 2000
#endif
#ifndef HB_MAX_LANGSYS_FEATURE_COUNT
#define HB_MAX_LANGSYS_FEATURE_COUNT 50000
#endif
#ifndef HB_MAX_FEATURES
#define HB_MAX_FEATURES 750
#endif
@ -105,34 +109,15 @@ struct hb_prune_langsys_context_t
script_langsys_map (script_langsys_map_),
duplicate_feature_map (duplicate_feature_map_),
new_feature_indexes (new_collected_feature_indexes_),
script_count (0),langsys_count (0) {}
script_count (0),langsys_feature_count (0) {}
bool visitedScript (const void *s)
bool visitScript ()
{ return script_count++ < HB_MAX_SCRIPTS; }
bool visitLangsys (unsigned feature_count)
{
if (script_count++ > HB_MAX_SCRIPTS)
return true;
return visited (s, visited_script);
}
bool visitedLangsys (const void *l)
{
if (langsys_count++ > HB_MAX_LANGSYS)
return true;
return visited (l, visited_langsys);
}
private:
template <typename T>
bool visited (const T *p, hb_set_t &visited_set)
{
hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) p - (uintptr_t) table);
if (visited_set.in_error () || visited_set.has (delta))
return true;
visited_set.add (delta);
return false;
langsys_feature_count += feature_count;
return langsys_feature_count < HB_MAX_LANGSYS_FEATURE_COUNT;
}
public:
@ -142,10 +127,8 @@ struct hb_prune_langsys_context_t
hb_set_t *new_feature_indexes;
private:
hb_set_t visited_script;
hb_set_t visited_langsys;
unsigned script_count;
unsigned langsys_count;
unsigned langsys_feature_count;
};
struct hb_subset_layout_context_t :
@ -643,11 +626,14 @@ struct LangSys
| hb_map (feature_index_map)
;
if (iter.len () != o_iter.len ())
return false;
for (; iter && o_iter; iter++, o_iter++)
{
unsigned a = *iter;
unsigned b = *o_iter;
if (a != b) return false;
}
for (const auto _ : + hb_zip (iter, o_iter))
if (_.first != _.second) return false;
if (iter || o_iter) return false;
return true;
}
@ -732,7 +718,7 @@ struct Script
unsigned script_index) const
{
if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
if (c->visitedScript (this)) return;
if (!c->visitScript ()) return;
if (!c->script_langsys_map->has (script_index))
{
@ -749,15 +735,14 @@ struct Script
{
//only collect features from non-redundant langsys
const LangSys& d = get_default_lang_sys ();
if (!c->visitedLangsys (&d)) {
if (c->visitLangsys (d.get_feature_count ())) {
d.collect_features (c);
}
for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
{
const LangSys& l = this+_.first.offset;
if (c->visitedLangsys (&l)) continue;
if (!c->visitLangsys (l.get_feature_count ())) continue;
if (l.compare (d, c->duplicate_feature_map)) continue;
l.collect_features (c);
@ -769,7 +754,7 @@ struct Script
for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
{
const LangSys& l = this+_.first.offset;
if (c->visitedLangsys (&l)) continue;
if (!c->visitLangsys (l.get_feature_count ())) continue;
l.collect_features (c);
c->script_langsys_map->get (script_index)->add (_.second);
}

Просмотреть файл

@ -361,6 +361,13 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
* Fetches a list of the caret positions defined for a ligature glyph in the GDEF
* table of the font. The list returned will begin at the offset provided.
*
* Note that a ligature that is formed from n characters will have n-1
* caret positions. The first character is not represented in the array,
* since its caret position is the glyph position.
*
* The positions returned by this function are 'unshaped', and will have to
* be fixed up for kerning that may be applied to the ligature glyph.
*
* Return value: Total number of ligature caret positions for @glyph.
*
**/
@ -999,7 +1006,7 @@ struct hb_collect_features_context_t
hb_collect_features_context_t (hb_face_t *face,
hb_tag_t table_tag,
hb_set_t *feature_indices_,
const hb_tag_t *features)
const hb_tag_t *features)
: g (get_gsubgpos_table (face, table_tag)),
feature_indices (feature_indices_),
@ -1026,7 +1033,7 @@ struct hb_collect_features_context_t
{
hb_tag_t tag = g.get_feature_tag (i);
if (features_set.has (tag))
feature_indices_filter.add(i);
feature_indices_filter.add(i);
}
}
@ -1959,6 +1966,77 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
}
#ifndef HB_NO_BASE
/**
* hb_ot_layout_get_horizontal_baseline_tag_for_script:
* @script: a script tag.
*
* Fetches the dominant horizontal baseline tag used by @script.
*
* Return value: dominant baseline tag for the @script.
*
* Since: 4.0.0
**/
hb_ot_layout_baseline_tag_t
hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script)
{
/* Keep in sync with hb_ot_layout_get_baseline_with_fallback */
switch ((int) script)
{
/* Unicode-1.1 additions */
case HB_SCRIPT_BENGALI:
case HB_SCRIPT_DEVANAGARI:
case HB_SCRIPT_GUJARATI:
case HB_SCRIPT_GURMUKHI:
/* Unicode-2.0 additions */
case HB_SCRIPT_TIBETAN:
/* Unicode-4.0 additions */
case HB_SCRIPT_LIMBU:
/* Unicode-4.1 additions */
case HB_SCRIPT_SYLOTI_NAGRI:
/* Unicode-5.0 additions */
case HB_SCRIPT_PHAGS_PA:
/* Unicode-5.2 additions */
case HB_SCRIPT_MEETEI_MAYEK:
/* Unicode-6.1 additions */
case HB_SCRIPT_SHARADA:
case HB_SCRIPT_TAKRI:
/* Unicode-7.0 additions */
case HB_SCRIPT_MODI:
case HB_SCRIPT_SIDDHAM:
case HB_SCRIPT_TIRHUTA:
/* Unicode-9.0 additions */
case HB_SCRIPT_MARCHEN:
case HB_SCRIPT_NEWA:
/* Unicode-10.0 additions */
case HB_SCRIPT_SOYOMBO:
case HB_SCRIPT_ZANABAZAR_SQUARE:
/* Unicode-11.0 additions */
case HB_SCRIPT_DOGRA:
case HB_SCRIPT_GUNJALA_GONDI:
/* Unicode-12.0 additions */
case HB_SCRIPT_NANDINAGARI:
return HB_OT_LAYOUT_BASELINE_TAG_HANGING;
/* Unicode-1.1 additions */
case HB_SCRIPT_HANGUL:
case HB_SCRIPT_HAN:
case HB_SCRIPT_HIRAGANA:
case HB_SCRIPT_KATAKANA:
/* Unicode-3.0 additions */
case HB_SCRIPT_BOPOMOFO:
/* Unicode-9.0 additions */
case HB_SCRIPT_TANGUT:
/* Unicode-10.0 additions */
case HB_SCRIPT_NUSHU:
/* Unicode-13.0 additions */
case HB_SCRIPT_KHITAN_SMALL_SCRIPT:
return HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT;
default:
return HB_OT_LAYOUT_BASELINE_TAG_ROMAN;
}
}
/**
* hb_ot_layout_get_baseline:
* @font: a font
@ -1966,7 +2044,7 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
* @direction: text direction.
* @script_tag: script tag.
* @language_tag: language tag, currently unused.
* @coord: (out): baseline value if found.
* @coord: (out) (nullable): baseline value if found.
*
* Fetches a baseline value from the face.
*
@ -1982,13 +2060,231 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */)
{
bool result = font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord);
if (result && coord)
*coord = HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (*coord) : font->em_scale_x (*coord);
return result;
return font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord);
}
/**
* hb_ot_layout_get_baseline_with_fallback:
* @font: a font
* @baseline_tag: a baseline tag
* @direction: text direction.
* @script_tag: script tag.
* @language_tag: language tag, currently unused.
* @coord: (out): baseline value if found.
*
* Fetches a baseline value from the face, and synthesizes
* it if the font does not have it.
*
* Since: 4.0.0
**/
void
hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
hb_ot_layout_baseline_tag_t baseline_tag,
hb_direction_t direction,
hb_tag_t script_tag,
hb_tag_t language_tag,
hb_position_t *coord /* OUT */)
{
if (hb_ot_layout_get_baseline (font,
baseline_tag,
direction,
script_tag,
language_tag,
coord))
return;
/* Synthesize missing baselines.
* See https://www.w3.org/TR/css-inline-3/#baseline-synthesis-fonts
*/
switch (baseline_tag)
{
case HB_OT_LAYOUT_BASELINE_TAG_ROMAN:
*coord = 0; // FIXME origin ?
break;
case HB_OT_LAYOUT_BASELINE_TAG_MATH:
{
hb_codepoint_t glyph;
hb_glyph_extents_t extents;
if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
(hb_font_get_nominal_glyph (font, 0x2212u, &glyph) ||
hb_font_get_nominal_glyph (font, '-', &glyph)) &&
hb_font_get_glyph_extents (font, glyph, &extents))
{
*coord = extents.y_bearing + extents.height / 2;
}
else
{
hb_position_t x_height = font->y_scale / 2;
#ifndef HB_NO_METRICS
hb_ot_metrics_get_position_with_fallback (font, HB_OT_METRICS_TAG_X_HEIGHT, &x_height);
#endif
*coord = x_height / 2;
}
}
break;
case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT:
case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT:
{
hb_position_t embox_top, embox_bottom;
hb_ot_layout_get_baseline_with_fallback (font,
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
direction,
script_tag,
language_tag,
&embox_top);
hb_ot_layout_get_baseline_with_fallback (font,
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
direction,
script_tag,
language_tag,
&embox_bottom);
if (baseline_tag == HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT)
*coord = embox_top + (embox_bottom - embox_top) / 10;
else
*coord = embox_bottom + (embox_top - embox_bottom) / 10;
}
break;
case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT:
if (hb_ot_layout_get_baseline (font,
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
direction,
script_tag,
language_tag,
coord))
*coord += HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
else
{
hb_font_extents_t font_extents;
hb_font_get_extents_for_direction (font, direction, &font_extents);
*coord = font_extents.ascender;
}
break;
case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT:
if (hb_ot_layout_get_baseline (font,
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
direction,
script_tag,
language_tag,
coord))
*coord -= HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
else
{
hb_font_extents_t font_extents;
hb_font_get_extents_for_direction (font, direction, &font_extents);
*coord = font_extents.descender;
}
break;
case HB_OT_LAYOUT_BASELINE_TAG_HANGING:
if (HB_DIRECTION_IS_HORIZONTAL (direction))
{
hb_codepoint_t ch;
hb_codepoint_t glyph;
hb_glyph_extents_t extents;
/* Keep in sync with hb_ot_layout_get_horizontal_baseline_for_script */
switch ((int) script_tag)
{
/* Unicode-1.1 additions */
case HB_SCRIPT_BENGALI: ch = 0x0995u; break;
case HB_SCRIPT_DEVANAGARI: ch = 0x0915u; break;
case HB_SCRIPT_GUJARATI: ch = 0x0a95u; break;
case HB_SCRIPT_GURMUKHI: ch = 0x0a15u; break;
/* Unicode-2.0 additions */
case HB_SCRIPT_TIBETAN: ch = 0x0f40u; break;
/* Unicode-4.0 additions */
case HB_SCRIPT_LIMBU: ch = 0x1901u; break;
/* Unicode-4.1 additions */
case HB_SCRIPT_SYLOTI_NAGRI: ch = 0xa807u; break;
/* Unicode-5.0 additions */
case HB_SCRIPT_PHAGS_PA: ch = 0xa840u; break;
/* Unicode-5.2 additions */
case HB_SCRIPT_MEETEI_MAYEK: ch = 0xabc0u; break;
/* Unicode-6.1 additions */
case HB_SCRIPT_SHARADA: ch = 0x11191u; break;
case HB_SCRIPT_TAKRI: ch = 0x1168cu; break;
/* Unicode-7.0 additions */
case HB_SCRIPT_MODI: ch = 0x1160eu;break;
case HB_SCRIPT_SIDDHAM: ch = 0x11590u; break;
case HB_SCRIPT_TIRHUTA: ch = 0x1148fu; break;
/* Unicode-9.0 additions */
case HB_SCRIPT_MARCHEN: ch = 0x11c72u; break;
case HB_SCRIPT_NEWA: ch = 0x1140eu; break;
/* Unicode-10.0 additions */
case HB_SCRIPT_SOYOMBO: ch = 0x11a5cu; break;
case HB_SCRIPT_ZANABAZAR_SQUARE: ch = 0x11a0bu; break;
/* Unicode-11.0 additions */
case HB_SCRIPT_DOGRA: ch = 0x1180au; break;
case HB_SCRIPT_GUNJALA_GONDI: ch = 0x11d6cu; break;
/* Unicode-12.0 additions */
case HB_SCRIPT_NANDINAGARI: ch = 0x119b0u; break;
default: ch = 0; break;
}
if (ch &&
hb_font_get_nominal_glyph (font, ch, &glyph) &&
hb_font_get_glyph_extents (font, glyph, &extents))
*coord = extents.y_bearing;
else
*coord = font->y_scale * 6 / 10; // FIXME makes assumptions about origin
}
else
*coord = font->x_scale * 6 / 10; // FIXME makes assumptions about origin
break;
case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL:
{
hb_position_t top, bottom;
hb_ot_layout_get_baseline_with_fallback (font,
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
direction,
script_tag,
language_tag,
&top);
hb_ot_layout_get_baseline_with_fallback (font,
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
direction,
script_tag,
language_tag,
&bottom);
*coord = (top + bottom) / 2;
}
break;
case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL:
{
hb_position_t top, bottom;
hb_ot_layout_get_baseline_with_fallback (font,
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT,
direction,
script_tag,
language_tag,
&top);
hb_ot_layout_get_baseline_with_fallback (font,
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT,
direction,
script_tag,
language_tag,
&bottom);
*coord = (top + bottom) / 2;
}
break;
case _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE:
default:
*coord = 0;
break;
}
}
#endif

Просмотреть файл

@ -332,31 +332,6 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
hb_set_t *glyphs_after, /* OUT. May be NULL */
hb_set_t *glyphs_output /* OUT. May be NULL */);
#ifdef HB_NOT_IMPLEMENTED
typedef struct
{
const hb_codepoint_t *before,
unsigned int before_length,
const hb_codepoint_t *input,
unsigned int input_length,
const hb_codepoint_t *after,
unsigned int after_length,
} hb_ot_layout_glyph_sequence_t;
typedef hb_bool_t
(*hb_ot_layout_glyph_sequence_func_t) (hb_font_t *font,
hb_tag_t table_tag,
unsigned int lookup_index,
const hb_ot_layout_glyph_sequence_t *sequence,
void *user_data);
HB_EXTERN void
Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face,
hb_tag_t table_tag,
unsigned int lookup_index,
hb_ot_layout_glyph_sequence_func_t callback,
void *user_data);
#endif
/* Variations support */
@ -411,19 +386,6 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs);
#ifdef HB_NOT_IMPLEMENTED
/* Note: You better have GDEF when using this API, or marks won't do much. */
HB_EXTERN hb_bool_t
Xhb_ot_layout_lookup_substitute (hb_font_t *font,
unsigned int lookup_index,
const hb_ot_layout_glyph_sequence_t *sequence,
unsigned int out_size,
hb_codepoint_t *glyphs_out, /* OUT */
unsigned int *clusters_out, /* OUT */
unsigned int *out_length /* OUT */);
#endif
/*
* GPOS
*/
@ -431,15 +393,6 @@ Xhb_ot_layout_lookup_substitute (hb_font_t *font,
HB_EXTERN hb_bool_t
hb_ot_layout_has_positioning (hb_face_t *face);
#ifdef HB_NOT_IMPLEMENTED
/* Note: You better have GDEF when using this API, or marks won't do much. */
HB_EXTERN hb_bool_t
Xhb_ot_layout_lookup_position (hb_font_t *font,
unsigned int lookup_index,
const hb_ot_layout_glyph_sequence_t *sequence,
hb_glyph_position_t *positions /* IN / OUT */);
#endif
/* Optical 'size' feature info. Returns true if found.
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
HB_EXTERN hb_bool_t
@ -487,9 +440,11 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT: Ideographic character face top or right edge,
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL: The center of the ideographic character face. Since: 4.0.0
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT: Ideographic em-box bottom or left edge,
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT: Ideographic em-box top or right edge baseline,
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL: The center of the ideographic em-box. Since: 4.0.0
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered.
* In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered.
@ -503,14 +458,19 @@ typedef enum {
HB_OT_LAYOUT_BASELINE_TAG_HANGING = HB_TAG ('h','a','n','g'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT = HB_TAG ('i','c','f','b'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT = HB_TAG ('i','c','f','t'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL = HB_TAG ('I','c','f','c'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT = HB_TAG ('i','d','e','o'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT = HB_TAG ('i','d','t','p'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL = HB_TAG ('I','d','c','e'),
HB_OT_LAYOUT_BASELINE_TAG_MATH = HB_TAG ('m','a','t','h'),
/*< private >*/
_HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_layout_baseline_tag_t;
HB_EXTERN hb_ot_layout_baseline_tag_t
hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script);
HB_EXTERN hb_bool_t
hb_ot_layout_get_baseline (hb_font_t *font,
hb_ot_layout_baseline_tag_t baseline_tag,
@ -519,6 +479,14 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */);
HB_EXTERN void
hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
hb_ot_layout_baseline_tag_t baseline_tag,
hb_direction_t direction,
hb_tag_t script_tag,
hb_tag_t language_tag,
hb_position_t *coord /* OUT */);
HB_END_DECLS
#endif /* HB_OT_LAYOUT_H */

Просмотреть файл

@ -485,6 +485,8 @@ static inline uint8_t
_hb_allocate_lig_id (hb_buffer_t *buffer)
{
uint8_t lig_id = buffer->next_serial () & 0x07;
if (unlikely (!lig_id))
lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
return lig_id;
}

Просмотреть файл

@ -238,6 +238,145 @@ hb_ot_metrics_get_position (hb_font_t *font,
}
}
/**
* hb_ot_metrics_get_position_with_fallback:
* @font: an #hb_font_t object.
* @metrics_tag: tag of metrics value you like to fetch.
* @position: (out) (optional): result of metrics value from the font.
*
* Fetches metrics value corresponding to @metrics_tag from @font,
* and synthesizes a value if it the value is missing in the font.
*
* Since: 4.0.0
**/
void
hb_ot_metrics_get_position_with_fallback (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT */)
{
hb_font_extents_t font_extents;
hb_codepoint_t glyph;
hb_glyph_extents_t extents;
if (hb_ot_metrics_get_position (font, metrics_tag, position))
{
if ((metrics_tag != HB_OT_METRICS_TAG_STRIKEOUT_SIZE &&
metrics_tag != HB_OT_METRICS_TAG_UNDERLINE_SIZE) ||
*position != 0)
return;
}
switch (metrics_tag)
{
case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT:
hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
*position = font_extents.ascender;
break;
case HB_OT_METRICS_TAG_VERTICAL_ASCENDER:
hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
*position = font_extents.ascender;
break;
case HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER:
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT:
hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
*position = font_extents.descender;
break;
case HB_OT_METRICS_TAG_VERTICAL_DESCENDER:
hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
*position = font_extents.ascender;
break;
case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP:
hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
*position = font_extents.line_gap;
break;
case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP:
hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
*position = font_extents.line_gap;
break;
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE:
case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE:
*position = 1;
break;
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN:
case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN:
*position = 0;
break;
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET:
case HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET:
*position = 0;
break;
case HB_OT_METRICS_TAG_X_HEIGHT:
if (hb_font_get_nominal_glyph (font, 'x', &glyph) &&
hb_font_get_glyph_extents (font, glyph, &extents))
*position = extents.y_bearing;
else
*position = font->y_scale / 2;
break;
case HB_OT_METRICS_TAG_CAP_HEIGHT:
if (hb_font_get_nominal_glyph (font, 'O', &glyph) &&
hb_font_get_glyph_extents (font, glyph, &extents))
*position = extents.height + 2 * extents.y_bearing;
else
*position = font->y_scale * 2 / 3;
break;
case HB_OT_METRICS_TAG_STRIKEOUT_SIZE:
case HB_OT_METRICS_TAG_UNDERLINE_SIZE:
*position = font->y_scale / 18;
break;
case HB_OT_METRICS_TAG_STRIKEOUT_OFFSET:
{
hb_position_t ascender;
hb_ot_metrics_get_position_with_fallback (font,
HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER,
&ascender);
*position = ascender / 2;
}
break;
case HB_OT_METRICS_TAG_UNDERLINE_OFFSET:
*position = - font->y_scale / 18;
break;
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE:
case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE:
*position = font->x_scale * 10 / 12;
break;
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE:
case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE:
*position = font->y_scale * 10 / 12;
break;
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET:
case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET:
*position = 0;
break;
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET:
case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET:
*position = font->y_scale / 5;
break;
case _HB_OT_METRICS_TAG_MAX_VALUE:
default:
*position = 0;
break;
}
}
#ifndef HB_NO_VAR
/**
* hb_ot_metrics_get_variation:

Просмотреть файл

@ -110,6 +110,11 @@ hb_ot_metrics_get_position (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */);
HB_EXTERN void
hb_ot_metrics_get_position_with_fallback (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT */);
HB_EXTERN float
hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);

Просмотреть файл

@ -198,11 +198,10 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
}
map->add_gsub_pause (final_reordering_indic);
map->add_gsub_pause (_hb_clear_syllables);
for (; i < INDIC_NUM_FEATURES; i++)
map->add_feature (indic_features[i]);
map->add_gsub_pause (_hb_clear_syllables);
}
static void

Просмотреть файл

@ -69,7 +69,7 @@ enum use_syllable_type_t {
#define use_syllable_machine_ex_GB 5u
#define use_syllable_machine_ex_H 12u
#define use_syllable_machine_ex_HN 13u
#define use_syllable_machine_ex_HVM 44u
#define use_syllable_machine_ex_IS 44u
#define use_syllable_machine_ex_J 50u
#define use_syllable_machine_ex_MAbv 27u
#define use_syllable_machine_ex_MBlw 28u
@ -92,234 +92,449 @@ enum use_syllable_type_t {
#define use_syllable_machine_ex_VMPst 39u
#define use_syllable_machine_ex_VPre 22u
#define use_syllable_machine_ex_VPst 35u
#define use_syllable_machine_ex_WJ 16u
#define use_syllable_machine_ex_ZWNJ 14u
#line 99 "hb-ot-shape-complex-use-machine.hh"
#line 100 "hb-ot-shape-complex-use-machine.hh"
static const unsigned char _use_syllable_machine_trans_keys[] = {
0u, 51u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u,
0u, 51u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u,
45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u,
23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u,
1u, 1u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u,
24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u,
11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u,
23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u,
24u, 48u, 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u,
22u, 48u, 11u, 48u, 1u, 48u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u, 41u, 42u,
42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0
1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u,
12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u,
1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 11u, 48u, 11u, 48u,
1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 4u, 4u, 13u, 13u,
1u, 48u, 11u, 48u, 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u,
0
};
static const char _use_syllable_machine_key_spans[] = {
52, 2, 1, 38, 38, 1, 27, 26,
52, 38, 38, 48, 26, 24, 23, 22,
2, 1, 25, 25, 25, 1, 25, 27,
26, 26, 26, 37, 37, 37, 37, 38,
1, 38, 2, 1, 38, 38, 48, 26,
24, 23, 22, 2, 1, 25, 25, 25,
1, 25, 26, 26, 26, 27, 27, 27,
38, 48, 1, 1, 38, 38, 1, 27,
26, 24, 23, 22, 2, 1, 25, 25,
25, 1, 25, 26, 26, 26, 27, 27,
27, 38, 48, 1, 1, 48, 38, 2,
1, 5, 3, 4, 3
1, 25, 27, 26, 26, 26, 37, 37,
37, 37, 38, 1, 1, 1, 38, 38,
48, 26, 24, 23, 22, 2, 1, 25,
25, 25, 1, 25, 27, 26, 26, 26,
37, 37, 37, 37, 38, 1, 38, 38,
48, 26, 24, 23, 22, 2, 1, 25,
25, 25, 1, 25, 27, 26, 26, 26,
37, 37, 37, 37, 38, 1, 1, 1,
48, 38, 2, 1, 5, 3, 4, 3
};
static const short _use_syllable_machine_index_offsets[] = {
0, 53, 56, 58, 97, 136, 138, 166,
193, 218, 242, 265, 268, 270, 296, 322,
348, 350, 376, 403, 430, 457, 485, 513,
541, 580, 629, 631, 633, 672, 711, 713,
741, 768, 793, 817, 840, 843, 845, 871,
897, 923, 925, 951, 978, 1005, 1032, 1060,
1088, 1116, 1155, 1204, 1206, 1208, 1257, 1296,
1299, 1301, 1307, 1311, 1316
0, 53, 92, 131, 180, 207, 232, 256,
279, 282, 284, 310, 336, 362, 364, 390,
418, 445, 472, 499, 537, 575, 613, 651,
690, 692, 731, 734, 736, 775, 814, 863,
890, 915, 939, 962, 965, 967, 993, 1019,
1045, 1047, 1073, 1101, 1128, 1155, 1182, 1220,
1258, 1296, 1334, 1373, 1375, 1377, 1379, 1418,
1457, 1506, 1533, 1558, 1582, 1605, 1608, 1610,
1636, 1662, 1688, 1690, 1716, 1744, 1771, 1798,
1825, 1863, 1901, 1939, 1977, 2016, 2018, 2057,
2096, 2145, 2172, 2197, 2221, 2244, 2247, 2249,
2275, 2301, 2327, 2329, 2355, 2383, 2410, 2437,
2464, 2502, 2540, 2578, 2616, 2655, 2657, 2659,
2661, 2710, 2749, 2752, 2754, 2760, 2764, 2769
};
static const char _use_syllable_machine_indicies[] = {
0, 1, 2, 2, 3, 4, 2, 2,
2, 2, 2, 5, 6, 7, 2, 2,
2, 2, 8, 2, 2, 2, 9, 10,
11, 12, 13, 14, 15, 9, 16, 17,
18, 19, 20, 21, 2, 22, 23, 24,
2, 25, 26, 27, 28, 29, 30, 31,
6, 32, 2, 33, 2, 0, 35, 34,
35, 34, 37, 38, 36, 36, 36, 36,
36, 36, 36, 36, 36, 39, 40, 41,
42, 43, 44, 45, 39, 46, 1, 47,
48, 49, 50, 36, 51, 52, 53, 36,
36, 36, 36, 54, 55, 56, 57, 38,
36, 37, 38, 36, 36, 36, 36, 36,
36, 36, 36, 36, 39, 40, 41, 42,
43, 44, 45, 39, 46, 47, 47, 48,
49, 50, 36, 51, 52, 53, 36, 36,
36, 36, 54, 55, 56, 57, 38, 36,
37, 58, 39, 40, 41, 42, 43, 36,
36, 36, 36, 36, 36, 48, 49, 50,
36, 51, 52, 53, 36, 36, 36, 36,
40, 55, 56, 57, 59, 36, 40, 41,
42, 43, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 51, 52, 53, 36,
36, 36, 36, 36, 55, 56, 57, 59,
36, 41, 42, 43, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 55, 56,
57, 36, 42, 43, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 55, 56,
57, 36, 43, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 55, 56, 57,
36, 55, 56, 36, 56, 36, 41, 42,
43, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 51, 52, 53, 36, 36,
36, 36, 36, 55, 56, 57, 59, 36,
41, 42, 43, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 52, 53,
36, 36, 36, 36, 36, 55, 56, 57,
59, 36, 41, 42, 43, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36,
36, 53, 36, 36, 36, 36, 36, 55,
56, 57, 59, 36, 61, 60, 41, 42,
43, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 55, 56, 57, 59, 36,
40, 41, 42, 43, 36, 36, 36, 36,
36, 36, 48, 49, 50, 36, 51, 52,
53, 36, 36, 36, 36, 40, 55, 56,
57, 59, 36, 40, 41, 42, 43, 36,
36, 36, 36, 36, 36, 36, 49, 50,
36, 51, 52, 53, 36, 36, 36, 36,
40, 55, 56, 57, 59, 36, 40, 41,
42, 43, 36, 36, 36, 36, 36, 36,
36, 36, 50, 36, 51, 52, 53, 36,
36, 36, 36, 40, 55, 56, 57, 59,
36, 39, 40, 41, 42, 43, 36, 45,
39, 36, 36, 36, 48, 49, 50, 36,
51, 52, 53, 36, 36, 36, 36, 40,
55, 56, 57, 59, 36, 39, 40, 41,
42, 43, 36, 36, 39, 36, 36, 36,
48, 49, 50, 36, 51, 52, 53, 36,
36, 36, 36, 40, 55, 56, 57, 59,
36, 39, 40, 41, 42, 43, 44, 45,
39, 36, 36, 36, 48, 49, 50, 36,
51, 52, 53, 36, 36, 36, 36, 40,
55, 56, 57, 59, 36, 37, 38, 36,
36, 36, 36, 36, 36, 36, 36, 36,
39, 40, 41, 42, 43, 44, 45, 39,
46, 36, 47, 48, 49, 50, 36, 51,
52, 53, 36, 36, 36, 36, 54, 55,
56, 57, 38, 36, 37, 58, 58, 58,
58, 58, 58, 58, 58, 58, 58, 58,
58, 58, 58, 58, 58, 58, 58, 58,
58, 58, 40, 41, 42, 43, 58, 58,
58, 58, 58, 58, 58, 58, 58, 58,
51, 52, 53, 58, 58, 58, 58, 58,
55, 56, 57, 59, 58, 63, 62, 3,
64, 37, 38, 36, 36, 36, 36, 36,
36, 36, 36, 36, 39, 40, 41, 42,
43, 44, 45, 39, 46, 1, 47, 48,
49, 50, 36, 51, 52, 53, 36, 0,
35, 36, 54, 55, 56, 57, 38, 36,
5, 6, 65, 65, 65, 65, 65, 65,
65, 65, 65, 9, 10, 11, 12, 13,
14, 15, 9, 16, 18, 18, 19, 20,
21, 65, 22, 23, 24, 65, 65, 65,
65, 28, 29, 30, 31, 6, 65, 5,
65, 9, 10, 11, 12, 13, 65, 65,
65, 65, 65, 65, 19, 20, 21, 65,
22, 23, 24, 65, 65, 65, 65, 10,
29, 30, 31, 66, 65, 10, 11, 12,
13, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 22, 23, 24, 65, 65,
65, 65, 65, 29, 30, 31, 66, 65,
11, 12, 13, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 29, 30, 31,
65, 12, 13, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 29, 30, 31,
65, 13, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 29, 30, 31, 65,
29, 30, 65, 30, 65, 11, 12, 13,
65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 22, 23, 24, 65, 65, 65,
65, 65, 29, 30, 31, 66, 65, 11,
12, 13, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 23, 24, 65,
65, 65, 65, 65, 29, 30, 31, 66,
65, 11, 12, 13, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65,
24, 65, 65, 65, 65, 65, 29, 30,
31, 66, 65, 67, 65, 11, 12, 13,
65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 29, 30, 31, 66, 65, 10,
11, 12, 13, 65, 65, 65, 65, 65,
65, 19, 20, 21, 65, 22, 23, 24,
65, 65, 65, 65, 10, 29, 30, 31,
66, 65, 10, 11, 12, 13, 65, 65,
65, 65, 65, 65, 65, 20, 21, 65,
22, 23, 24, 65, 65, 65, 65, 10,
29, 30, 31, 66, 65, 10, 11, 12,
13, 65, 65, 65, 65, 65, 65, 65,
65, 21, 65, 22, 23, 24, 65, 65,
65, 65, 10, 29, 30, 31, 66, 65,
9, 10, 11, 12, 13, 65, 15, 9,
65, 65, 65, 19, 20, 21, 65, 22,
23, 24, 65, 65, 65, 65, 10, 29,
30, 31, 66, 65, 9, 10, 11, 12,
13, 65, 65, 9, 65, 65, 65, 19,
20, 21, 65, 22, 23, 24, 65, 65,
65, 65, 10, 29, 30, 31, 66, 65,
9, 10, 11, 12, 13, 14, 15, 9,
65, 65, 65, 19, 20, 21, 65, 22,
23, 24, 65, 65, 65, 65, 10, 29,
30, 31, 66, 65, 5, 6, 65, 65,
65, 65, 65, 65, 65, 65, 65, 9,
10, 11, 12, 13, 14, 15, 9, 16,
65, 18, 19, 20, 21, 65, 22, 23,
24, 65, 65, 65, 65, 28, 29, 30,
31, 6, 65, 5, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65,
65, 10, 11, 12, 13, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 22,
23, 24, 65, 65, 65, 65, 65, 29,
30, 31, 66, 65, 68, 65, 7, 65,
1, 65, 65, 65, 1, 65, 65, 65,
65, 65, 5, 6, 7, 65, 65, 65,
65, 65, 65, 65, 65, 9, 10, 11,
12, 13, 14, 15, 9, 16, 17, 18,
19, 20, 21, 65, 22, 23, 24, 65,
25, 26, 65, 28, 29, 30, 31, 6,
65, 5, 6, 65, 65, 65, 65, 65,
65, 65, 65, 65, 9, 10, 11, 12,
13, 14, 15, 9, 16, 17, 18, 19,
20, 21, 65, 22, 23, 24, 65, 65,
65, 65, 28, 29, 30, 31, 6, 65,
25, 26, 65, 26, 65, 1, 69, 69,
69, 1, 69, 71, 70, 32, 70, 32,
71, 70, 71, 70, 32, 70, 33, 70,
0
11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 2, 23, 24, 25,
2, 26, 27, 28, 29, 30, 31, 32,
29, 33, 2, 34, 2, 36, 37, 35,
35, 35, 35, 35, 35, 35, 35, 35,
38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 35, 52,
53, 54, 35, 55, 56, 35, 57, 58,
59, 60, 57, 35, 36, 37, 35, 35,
35, 35, 35, 35, 35, 35, 35, 38,
39, 40, 41, 42, 43, 44, 45, 46,
48, 48, 49, 50, 51, 35, 52, 53,
54, 35, 35, 35, 35, 57, 58, 59,
60, 57, 35, 36, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35,
35, 39, 40, 41, 42, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 52,
53, 54, 35, 35, 35, 35, 35, 58,
59, 60, 61, 35, 39, 40, 41, 42,
35, 35, 35, 35, 35, 35, 35, 35,
35, 35, 52, 53, 54, 35, 35, 35,
35, 35, 58, 59, 60, 61, 35, 40,
41, 42, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 58, 59, 60, 35,
41, 42, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 58, 59, 60, 35,
42, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 58, 59, 60, 35, 58,
59, 35, 59, 35, 40, 41, 42, 35,
35, 35, 35, 35, 35, 35, 35, 35,
35, 52, 53, 54, 35, 35, 35, 35,
35, 58, 59, 60, 61, 35, 40, 41,
42, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 53, 54, 35, 35,
35, 35, 35, 58, 59, 60, 61, 35,
40, 41, 42, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 54,
35, 35, 35, 35, 35, 58, 59, 60,
61, 35, 62, 35, 40, 41, 42, 35,
35, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35,
35, 58, 59, 60, 61, 35, 38, 39,
40, 41, 42, 35, 35, 35, 35, 35,
35, 49, 50, 51, 35, 52, 53, 54,
35, 35, 35, 35, 35, 58, 59, 60,
61, 35, 39, 40, 41, 42, 35, 35,
35, 35, 35, 35, 49, 50, 51, 35,
52, 53, 54, 35, 35, 35, 35, 35,
58, 59, 60, 61, 35, 39, 40, 41,
42, 35, 35, 35, 35, 35, 35, 35,
50, 51, 35, 52, 53, 54, 35, 35,
35, 35, 35, 58, 59, 60, 61, 35,
39, 40, 41, 42, 35, 35, 35, 35,
35, 35, 35, 35, 51, 35, 52, 53,
54, 35, 35, 35, 35, 35, 58, 59,
60, 61, 35, 39, 35, 35, 35, 35,
35, 35, 35, 35, 35, 38, 39, 40,
41, 42, 35, 44, 45, 35, 35, 35,
49, 50, 51, 35, 52, 53, 54, 35,
35, 35, 35, 35, 58, 59, 60, 61,
35, 39, 35, 35, 35, 35, 35, 35,
35, 35, 35, 38, 39, 40, 41, 42,
35, 35, 45, 35, 35, 35, 49, 50,
51, 35, 52, 53, 54, 35, 35, 35,
35, 35, 58, 59, 60, 61, 35, 39,
35, 35, 35, 35, 35, 35, 35, 35,
35, 38, 39, 40, 41, 42, 35, 35,
35, 35, 35, 35, 49, 50, 51, 35,
52, 53, 54, 35, 35, 35, 35, 35,
58, 59, 60, 61, 35, 39, 35, 35,
35, 35, 35, 35, 35, 35, 35, 38,
39, 40, 41, 42, 43, 44, 45, 35,
35, 35, 49, 50, 51, 35, 52, 53,
54, 35, 35, 35, 35, 35, 58, 59,
60, 61, 35, 36, 37, 35, 35, 35,
35, 35, 35, 35, 35, 35, 38, 39,
40, 41, 42, 43, 44, 45, 46, 35,
48, 49, 50, 51, 35, 52, 53, 54,
35, 35, 35, 35, 57, 58, 59, 60,
57, 35, 36, 35, 36, 37, 35, 35,
35, 35, 35, 35, 35, 35, 35, 38,
39, 40, 41, 42, 43, 44, 45, 46,
47, 48, 49, 50, 51, 35, 52, 53,
54, 35, 35, 35, 35, 57, 58, 59,
60, 57, 35, 55, 56, 35, 56, 35,
64, 65, 63, 63, 63, 63, 63, 63,
63, 63, 63, 66, 67, 68, 69, 70,
71, 72, 73, 74, 1, 75, 76, 77,
78, 63, 79, 80, 81, 63, 63, 63,
63, 82, 83, 84, 85, 86, 63, 64,
65, 63, 63, 63, 63, 63, 63, 63,
63, 63, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 75, 76, 77, 78,
63, 79, 80, 81, 63, 63, 63, 63,
82, 83, 84, 85, 86, 63, 64, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 67, 68, 69, 70,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 79, 80, 81, 63, 63, 63,
63, 63, 83, 84, 85, 87, 63, 67,
68, 69, 70, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 79, 80, 81,
63, 63, 63, 63, 63, 83, 84, 85,
87, 63, 68, 69, 70, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 83,
84, 85, 63, 69, 70, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 83,
84, 85, 63, 70, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 83, 84,
85, 63, 83, 84, 63, 84, 63, 68,
69, 70, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 79, 80, 81, 63,
63, 63, 63, 63, 83, 84, 85, 87,
63, 68, 69, 70, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 80,
81, 63, 63, 63, 63, 63, 83, 84,
85, 87, 63, 68, 69, 70, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 81, 63, 63, 63, 63, 63,
83, 84, 85, 87, 63, 89, 88, 68,
69, 70, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 83, 84, 85, 87,
63, 66, 67, 68, 69, 70, 63, 63,
63, 63, 63, 63, 76, 77, 78, 63,
79, 80, 81, 63, 63, 63, 63, 63,
83, 84, 85, 87, 63, 67, 68, 69,
70, 63, 63, 63, 63, 63, 63, 76,
77, 78, 63, 79, 80, 81, 63, 63,
63, 63, 63, 83, 84, 85, 87, 63,
67, 68, 69, 70, 63, 63, 63, 63,
63, 63, 63, 77, 78, 63, 79, 80,
81, 63, 63, 63, 63, 63, 83, 84,
85, 87, 63, 67, 68, 69, 70, 63,
63, 63, 63, 63, 63, 63, 63, 78,
63, 79, 80, 81, 63, 63, 63, 63,
63, 83, 84, 85, 87, 63, 67, 63,
63, 63, 63, 63, 63, 63, 63, 63,
66, 67, 68, 69, 70, 63, 72, 73,
63, 63, 63, 76, 77, 78, 63, 79,
80, 81, 63, 63, 63, 63, 63, 83,
84, 85, 87, 63, 67, 63, 63, 63,
63, 63, 63, 63, 63, 63, 66, 67,
68, 69, 70, 63, 63, 73, 63, 63,
63, 76, 77, 78, 63, 79, 80, 81,
63, 63, 63, 63, 63, 83, 84, 85,
87, 63, 67, 63, 63, 63, 63, 63,
63, 63, 63, 63, 66, 67, 68, 69,
70, 63, 63, 63, 63, 63, 63, 76,
77, 78, 63, 79, 80, 81, 63, 63,
63, 63, 63, 83, 84, 85, 87, 63,
67, 63, 63, 63, 63, 63, 63, 63,
63, 63, 66, 67, 68, 69, 70, 71,
72, 73, 63, 63, 63, 76, 77, 78,
63, 79, 80, 81, 63, 63, 63, 63,
63, 83, 84, 85, 87, 63, 64, 65,
63, 63, 63, 63, 63, 63, 63, 63,
63, 66, 67, 68, 69, 70, 71, 72,
73, 74, 63, 75, 76, 77, 78, 63,
79, 80, 81, 63, 63, 63, 63, 82,
83, 84, 85, 86, 63, 64, 90, 92,
91, 3, 93, 94, 95, 63, 63, 63,
63, 63, 63, 63, 63, 63, 96, 97,
98, 99, 100, 101, 102, 103, 104, 105,
106, 107, 108, 109, 63, 110, 111, 112,
63, 55, 56, 63, 113, 114, 115, 85,
116, 63, 94, 95, 63, 63, 63, 63,
63, 63, 63, 63, 63, 96, 97, 98,
99, 100, 101, 102, 103, 104, 106, 106,
107, 108, 109, 63, 110, 111, 112, 63,
63, 63, 63, 113, 114, 115, 85, 116,
63, 94, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 97,
98, 99, 100, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 110, 111, 112,
63, 63, 63, 63, 63, 114, 115, 85,
117, 63, 97, 98, 99, 100, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
110, 111, 112, 63, 63, 63, 63, 63,
114, 115, 85, 117, 63, 98, 99, 100,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 114, 115, 85, 63, 99, 100,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 114, 115, 85, 63, 100, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 114, 115, 85, 63, 114, 115, 63,
115, 63, 98, 99, 100, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 110,
111, 112, 63, 63, 63, 63, 63, 114,
115, 85, 117, 63, 98, 99, 100, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 111, 112, 63, 63, 63, 63,
63, 114, 115, 85, 117, 63, 98, 99,
100, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 112, 63, 63,
63, 63, 63, 114, 115, 85, 117, 63,
118, 88, 98, 99, 100, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 114,
115, 85, 117, 63, 96, 97, 98, 99,
100, 63, 63, 63, 63, 63, 63, 107,
108, 109, 63, 110, 111, 112, 63, 63,
63, 63, 63, 114, 115, 85, 117, 63,
97, 98, 99, 100, 63, 63, 63, 63,
63, 63, 107, 108, 109, 63, 110, 111,
112, 63, 63, 63, 63, 63, 114, 115,
85, 117, 63, 97, 98, 99, 100, 63,
63, 63, 63, 63, 63, 63, 108, 109,
63, 110, 111, 112, 63, 63, 63, 63,
63, 114, 115, 85, 117, 63, 97, 98,
99, 100, 63, 63, 63, 63, 63, 63,
63, 63, 109, 63, 110, 111, 112, 63,
63, 63, 63, 63, 114, 115, 85, 117,
63, 97, 63, 63, 63, 63, 63, 63,
63, 63, 63, 96, 97, 98, 99, 100,
63, 102, 103, 63, 63, 63, 107, 108,
109, 63, 110, 111, 112, 63, 63, 63,
63, 63, 114, 115, 85, 117, 63, 97,
63, 63, 63, 63, 63, 63, 63, 63,
63, 96, 97, 98, 99, 100, 63, 63,
103, 63, 63, 63, 107, 108, 109, 63,
110, 111, 112, 63, 63, 63, 63, 63,
114, 115, 85, 117, 63, 97, 63, 63,
63, 63, 63, 63, 63, 63, 63, 96,
97, 98, 99, 100, 63, 63, 63, 63,
63, 63, 107, 108, 109, 63, 110, 111,
112, 63, 63, 63, 63, 63, 114, 115,
85, 117, 63, 97, 63, 63, 63, 63,
63, 63, 63, 63, 63, 96, 97, 98,
99, 100, 101, 102, 103, 63, 63, 63,
107, 108, 109, 63, 110, 111, 112, 63,
63, 63, 63, 63, 114, 115, 85, 117,
63, 94, 95, 63, 63, 63, 63, 63,
63, 63, 63, 63, 96, 97, 98, 99,
100, 101, 102, 103, 104, 63, 106, 107,
108, 109, 63, 110, 111, 112, 63, 63,
63, 63, 113, 114, 115, 85, 116, 63,
94, 90, 94, 95, 63, 63, 63, 63,
63, 63, 63, 63, 63, 96, 97, 98,
99, 100, 101, 102, 103, 104, 105, 106,
107, 108, 109, 63, 110, 111, 112, 63,
63, 63, 63, 113, 114, 115, 85, 116,
63, 5, 6, 119, 119, 119, 119, 119,
119, 119, 119, 119, 9, 10, 11, 12,
13, 14, 15, 16, 17, 19, 19, 20,
21, 22, 119, 23, 24, 25, 119, 119,
119, 119, 29, 30, 31, 32, 29, 119,
5, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 10, 11,
12, 13, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 23, 24, 25, 119,
119, 119, 119, 119, 30, 31, 32, 120,
119, 10, 11, 12, 13, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 23,
24, 25, 119, 119, 119, 119, 119, 30,
31, 32, 120, 119, 11, 12, 13, 119,
119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119,
119, 30, 31, 32, 119, 12, 13, 119,
119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119,
119, 30, 31, 32, 119, 13, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119,
30, 31, 32, 119, 30, 31, 119, 31,
119, 11, 12, 13, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 23, 24,
25, 119, 119, 119, 119, 119, 30, 31,
32, 120, 119, 11, 12, 13, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119,
119, 24, 25, 119, 119, 119, 119, 119,
30, 31, 32, 120, 119, 11, 12, 13,
119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 25, 119, 119, 119,
119, 119, 30, 31, 32, 120, 119, 121,
119, 11, 12, 13, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 30, 31,
32, 120, 119, 9, 10, 11, 12, 13,
119, 119, 119, 119, 119, 119, 20, 21,
22, 119, 23, 24, 25, 119, 119, 119,
119, 119, 30, 31, 32, 120, 119, 10,
11, 12, 13, 119, 119, 119, 119, 119,
119, 20, 21, 22, 119, 23, 24, 25,
119, 119, 119, 119, 119, 30, 31, 32,
120, 119, 10, 11, 12, 13, 119, 119,
119, 119, 119, 119, 119, 21, 22, 119,
23, 24, 25, 119, 119, 119, 119, 119,
30, 31, 32, 120, 119, 10, 11, 12,
13, 119, 119, 119, 119, 119, 119, 119,
119, 22, 119, 23, 24, 25, 119, 119,
119, 119, 119, 30, 31, 32, 120, 119,
10, 119, 119, 119, 119, 119, 119, 119,
119, 119, 9, 10, 11, 12, 13, 119,
15, 16, 119, 119, 119, 20, 21, 22,
119, 23, 24, 25, 119, 119, 119, 119,
119, 30, 31, 32, 120, 119, 10, 119,
119, 119, 119, 119, 119, 119, 119, 119,
9, 10, 11, 12, 13, 119, 119, 16,
119, 119, 119, 20, 21, 22, 119, 23,
24, 25, 119, 119, 119, 119, 119, 30,
31, 32, 120, 119, 10, 119, 119, 119,
119, 119, 119, 119, 119, 119, 9, 10,
11, 12, 13, 119, 119, 119, 119, 119,
119, 20, 21, 22, 119, 23, 24, 25,
119, 119, 119, 119, 119, 30, 31, 32,
120, 119, 10, 119, 119, 119, 119, 119,
119, 119, 119, 119, 9, 10, 11, 12,
13, 14, 15, 16, 119, 119, 119, 20,
21, 22, 119, 23, 24, 25, 119, 119,
119, 119, 119, 30, 31, 32, 120, 119,
5, 6, 119, 119, 119, 119, 119, 119,
119, 119, 119, 9, 10, 11, 12, 13,
14, 15, 16, 17, 119, 19, 20, 21,
22, 119, 23, 24, 25, 119, 119, 119,
119, 29, 30, 31, 32, 29, 119, 5,
119, 122, 119, 7, 119, 1, 119, 119,
119, 1, 119, 119, 119, 119, 119, 5,
6, 7, 119, 119, 119, 119, 119, 119,
119, 119, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22,
119, 23, 24, 25, 119, 26, 27, 119,
29, 30, 31, 32, 29, 119, 5, 6,
119, 119, 119, 119, 119, 119, 119, 119,
119, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 119,
23, 24, 25, 119, 119, 119, 119, 29,
30, 31, 32, 29, 119, 26, 27, 119,
27, 119, 1, 123, 123, 123, 1, 123,
125, 124, 33, 124, 33, 125, 124, 125,
124, 33, 124, 34, 124, 0
};
static const char _use_syllable_machine_trans_targs[] = {
1, 3, 0, 26, 28, 29, 30, 51,
53, 31, 32, 33, 34, 35, 46, 47,
48, 54, 49, 43, 44, 45, 38, 39,
40, 55, 56, 57, 50, 36, 37, 0,
58, 60, 0, 2, 0, 4, 5, 6,
7, 8, 9, 10, 21, 22, 23, 24,
18, 19, 20, 13, 14, 15, 25, 11,
12, 0, 0, 16, 0, 17, 0, 27,
0, 0, 41, 42, 52, 0, 0, 59
1, 28, 0, 52, 54, 79, 80, 102,
104, 92, 81, 82, 83, 84, 96, 97,
98, 99, 105, 100, 93, 94, 95, 87,
88, 89, 106, 107, 108, 101, 85, 86,
0, 109, 111, 0, 2, 3, 15, 4,
5, 6, 7, 19, 20, 21, 22, 25,
23, 16, 17, 18, 10, 11, 12, 26,
27, 24, 8, 9, 0, 13, 14, 0,
29, 30, 42, 31, 32, 33, 34, 46,
47, 48, 49, 50, 43, 44, 45, 37,
38, 39, 51, 35, 36, 0, 51, 40,
0, 41, 0, 0, 53, 0, 55, 56,
68, 57, 58, 59, 60, 72, 73, 74,
75, 78, 76, 69, 70, 71, 63, 64,
65, 77, 61, 62, 77, 66, 67, 0,
90, 91, 103, 0, 0, 110
};
static const char _use_syllable_machine_trans_actions[] = {
0, 0, 3, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 4,
0, 0, 5, 0, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
4, 0, 0, 5, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 7, 8, 0, 9, 0, 10, 0,
11, 12, 0, 0, 0, 13, 14, 0
0, 0, 0, 0, 6, 0, 0, 7,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 8, 0, 0, 9, 10, 0,
11, 0, 12, 13, 0, 14, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 8, 0, 0, 10, 0, 0, 15,
0, 0, 0, 16, 17, 0
};
static const char _use_syllable_machine_to_state_actions[] = {
@ -330,7 +545,13 @@ static const char _use_syllable_machine_to_state_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static const char _use_syllable_machine_from_state_actions[] = {
@ -341,18 +562,30 @@ static const char _use_syllable_machine_from_state_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static const short _use_syllable_machine_eof_trans[] = {
0, 35, 35, 37, 37, 59, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37,
61, 37, 37, 37, 37, 37, 37, 37,
37, 59, 63, 65, 37, 66, 66, 66,
66, 66, 66, 66, 66, 66, 66, 66,
66, 66, 66, 66, 66, 66, 66, 66,
66, 66, 66, 66, 66, 66, 66, 66,
66, 70, 71, 71, 71
0, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
89, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 91, 92, 94, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 89, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 91, 64, 120,
120, 120, 120, 120, 120, 120, 120, 120,
120, 120, 120, 120, 120, 120, 120, 120,
120, 120, 120, 120, 120, 120, 120, 120,
120, 120, 120, 120, 124, 125, 125, 125
};
static const int use_syllable_machine_start = 0;
@ -366,7 +599,7 @@ static const int use_syllable_machine_en_main = 0;
#line 179 "hb-ot-shape-complex-use-machine.rl"
#line 181 "hb-ot-shape-complex-use-machine.rl"
#define found_syllable(syllable_type) \
@ -385,7 +618,9 @@ struct machine_index_t :
typename Iter::item_t>
{
machine_index_t (const Iter& it) : it (it) {}
machine_index_t (const machine_index_t& o) : it (o.it) {}
machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
typename Iter::item_t> (),
it (o.it) {}
static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
@ -420,7 +655,7 @@ HB_FUNCOBJ (machine_index);
static bool
not_ccs_default_ignorable (const hb_glyph_info_t &i)
{ return !(i.use_category() == USE(CGJ) && _hb_glyph_info_is_default_ignorable (&i)); }
{ return i.use_category() != USE(CGJ); }
static inline void
find_syllables_use (hb_buffer_t *buffer)
@ -449,7 +684,7 @@ find_syllables_use (hb_buffer_t *buffer)
unsigned int act HB_UNUSED;
int cs;
#line 453 "hb-ot-shape-complex-use-machine.hh"
#line 688 "hb-ot-shape-complex-use-machine.hh"
{
cs = use_syllable_machine_start;
ts = 0;
@ -457,12 +692,12 @@ find_syllables_use (hb_buffer_t *buffer)
act = 0;
}
#line 263 "hb-ot-shape-complex-use-machine.rl"
#line 267 "hb-ot-shape-complex-use-machine.rl"
unsigned int syllable_serial = 1;
#line 466 "hb-ot-shape-complex-use-machine.hh"
#line 701 "hb-ot-shape-complex-use-machine.hh"
{
int _slen;
int _trans;
@ -476,7 +711,7 @@ _resume:
#line 1 "NONE"
{ts = p;}
break;
#line 480 "hb-ot-shape-complex-use-machine.hh"
#line 715 "hb-ot-shape-complex-use-machine.hh"
}
_keys = _use_syllable_machine_trans_keys + (cs<<1);
@ -494,55 +729,79 @@ _eof_trans:
goto _again;
switch ( _use_syllable_machine_trans_actions[_trans] ) {
case 7:
#line 169 "hb-ot-shape-complex-use-machine.rl"
case 9:
#line 171 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (use_standard_cluster); }}
break;
case 4:
case 6:
#line 174 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (use_symbol_cluster); }}
break;
case 4:
#line 176 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (use_broken_cluster); }}
break;
case 3:
#line 175 "hb-ot-shape-complex-use-machine.rl"
#line 177 "hb-ot-shape-complex-use-machine.rl"
{te = p+1;{ found_syllable (use_non_cluster); }}
break;
case 8:
#line 167 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_virama_terminated_cluster); }}
break;
case 9:
#line 168 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
break;
case 6:
#line 169 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_standard_cluster); }}
break;
case 11:
#line 170 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
break;
case 7:
#line 171 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_standard_cluster); }}
break;
case 14:
#line 172 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
break;
case 10:
#line 171 "hb-ot-shape-complex-use-machine.rl"
case 13:
#line 173 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_numeral_cluster); }}
break;
case 5:
#line 172 "hb-ot-shape-complex-use-machine.rl"
#line 174 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_symbol_cluster); }}
break;
case 14:
#line 173 "hb-ot-shape-complex-use-machine.rl"
case 17:
#line 175 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
break;
case 12:
#line 174 "hb-ot-shape-complex-use-machine.rl"
case 15:
#line 176 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_broken_cluster); }}
break;
case 13:
#line 175 "hb-ot-shape-complex-use-machine.rl"
case 16:
#line 177 "hb-ot-shape-complex-use-machine.rl"
{te = p;p--;{ found_syllable (use_non_cluster); }}
break;
#line 546 "hb-ot-shape-complex-use-machine.hh"
case 12:
#line 1 "NONE"
{ switch( act ) {
case 1:
{{p = ((te))-1;} found_syllable (use_virama_terminated_cluster); }
break;
case 2:
{{p = ((te))-1;} found_syllable (use_sakot_terminated_cluster); }
break;
}
}
break;
case 8:
#line 1 "NONE"
{te = p+1;}
#line 169 "hb-ot-shape-complex-use-machine.rl"
{act = 1;}
break;
case 10:
#line 1 "NONE"
{te = p+1;}
#line 170 "hb-ot-shape-complex-use-machine.rl"
{act = 2;}
break;
#line 805 "hb-ot-shape-complex-use-machine.hh"
}
_again:
@ -551,7 +810,7 @@ _again:
#line 1 "NONE"
{ts = 0;}
break;
#line 555 "hb-ot-shape-complex-use-machine.hh"
#line 814 "hb-ot-shape-complex-use-machine.hh"
}
if ( ++p != pe )
@ -567,7 +826,7 @@ _again:
}
#line 268 "hb-ot-shape-complex-use-machine.rl"
#line 272 "hb-ot-shape-complex-use-machine.rl"
}

Просмотреть файл

@ -73,9 +73,10 @@ export H = 12; # HALANT
export HN = 13; # HALANT_NUM
export ZWNJ = 14; # Zero width non-joiner
export WJ = 16; # Word joiner
export R = 18; # REPHA
export CS = 43; # CONS_WITH_STACKER
export HVM = 44; # HALANT_OR_VOWEL_MODIFIER
export IS = 44; # INVISIBLE_STACKER
export Sk = 48; # SAKOT
export G = 49; # HIEROGLYPH
export J = 50; # HIEROGLYPH_JOINER
@ -106,12 +107,12 @@ export FMBlw = 46; # CONS_FINAL_MOD UIPC = Bottom
export FMPst = 47; # CONS_FINAL_MOD UIPC = Not_Applicable
h = H | HVM | Sk;
h = H | IS | Sk;
consonant_modifiers = CMAbv* CMBlw* ((h B | SUB) CMAbv? CMBlw*)*;
medial_consonants = MPre? MAbv? MBlw? MPst?;
dependent_vowels = VPre* VAbv* VBlw* VPst*;
vowel_modifiers = HVM? VMPre* VMAbv* VMBlw* VMPst*;
dependent_vowels = VPre* VAbv* VBlw* VPst* | H;
vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*;
final_consonants = FAbv* FBlw* FPst*;
final_modifiers = FMAbv* FMBlw* | FMPst?;
@ -134,7 +135,7 @@ symbol_cluster_tail = SMAbv+ SMBlw* | SMBlw+;
virama_terminated_cluster_tail =
consonant_modifiers
h
IS
;
virama_terminated_cluster =
complex_syllable_start
@ -152,14 +153,15 @@ standard_cluster =
complex_syllable_start
complex_syllable_tail
;
tail = complex_syllable_tail | sakot_terminated_cluster_tail | symbol_cluster_tail | virama_terminated_cluster_tail;
broken_cluster =
R?
(complex_syllable_tail | number_joiner_terminated_cluster_tail | numeral_cluster_tail | symbol_cluster_tail | virama_terminated_cluster_tail | sakot_terminated_cluster_tail)
(tail | number_joiner_terminated_cluster_tail | numeral_cluster_tail)
;
number_joiner_terminated_cluster = N number_joiner_terminated_cluster_tail;
numeral_cluster = N numeral_cluster_tail?;
symbol_cluster = (O | GB) symbol_cluster_tail?;
symbol_cluster = (O | GB) tail?;
hieroglyph_cluster = SB+ | SB* G SE* (J SE* (G SE*)?)*;
other = any;
@ -194,7 +196,9 @@ struct machine_index_t :
typename Iter::item_t>
{
machine_index_t (const Iter& it) : it (it) {}
machine_index_t (const machine_index_t& o) : it (o.it) {}
machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
typename Iter::item_t> (),
it (o.it) {}
static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
@ -229,7 +233,7 @@ HB_FUNCOBJ (machine_index);
static bool
not_ccs_default_ignorable (const hb_glyph_info_t &i)
{ return !(i.use_category() == USE(CGJ) && _hb_glyph_info_is_default_ignorable (&i)); }
{ return i.use_category() != USE(CGJ); }
static inline void
find_syllables_use (hb_buffer_t *buffer)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -206,7 +206,7 @@ setup_masks_use (const hb_ot_shape_plan_t *plan,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
info[i].use_category() = hb_use_get_category (info[i].codepoint);
info[i].use_category() = hb_use_get_category (info[i]);
}
static void
@ -257,7 +257,6 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F);
switch (syllable_type)
{
case use_symbol_cluster:
case use_hieroglyph_cluster:
case use_non_cluster:
/* These don't join. Nothing to do. */
@ -269,6 +268,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
case use_standard_cluster:
case use_number_joiner_terminated_cluster:
case use_numeral_cluster:
case use_symbol_cluster:
case use_broken_cluster:
bool join = last_form == JOINING_FORM_FINA || last_form == JOINING_FORM_ISOL;
@ -350,7 +350,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
static inline bool
is_halant_use (const hb_glyph_info_t &info)
{
return (info.use_category() == USE(H) || info.use_category() == USE(HVM)) &&
return (info.use_category() == USE(H) || info.use_category() == USE(IS)) &&
!_hb_glyph_info_ligated (&info);
}
@ -363,6 +363,7 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
(FLAG (use_virama_terminated_cluster) |
FLAG (use_sakot_terminated_cluster) |
FLAG (use_standard_cluster) |
FLAG (use_symbol_cluster) |
FLAG (use_broken_cluster) |
0))))
return;

Просмотреть файл

@ -7,7 +7,7 @@
* on files with these headers:
*
* <meta name="updated_at" content="2022-01-28 10:00 PM" />
* File-Date: 2021-12-29
* File-Date: 2022-03-02
*/
#ifndef HB_OT_TAG_TABLE_HH
@ -54,6 +54,7 @@ static const LangTag ot_languages[] = {
/*{"aio", HB_TAG('A','I','O',' ')},*/ /* Aiton */
{"aiw", HB_TAG('A','R','I',' ')}, /* Aari */
{"ajp", HB_TAG('A','R','A',' ')}, /* South Levantine Arabic -> Arabic */
{"ajt", HB_TAG('A','R','A',' ')}, /* Judeo-Tunisian Arabic (retired code) -> Arabic */
{"ak", HB_TAG('A','K','A',' ')}, /* Akan [macrolanguage] */
{"akb", HB_TAG('A','K','B',' ')}, /* Batak Angkola */
{"akb", HB_TAG('B','T','K',' ')}, /* Batak Angkola -> Batak */
@ -809,7 +810,7 @@ static const LangTag ot_languages[] = {
{"lac", HB_TAG('M','Y','N',' ')}, /* Lacandon -> Mayan */
{"lad", HB_TAG('J','U','D',' ')}, /* Ladino */
{"lah", HB_TAG_NONE }, /* Lahnda [macrolanguage] != Lahuli */
{"lak", HB_TAG_NONE }, /* Laka (Nigeria) != Lak */
{"lak", HB_TAG_NONE }, /* Laka (Nigeria) (retired code) != Lak */
{"lam", HB_TAG_NONE }, /* Lamba != Lambani */
{"laz", HB_TAG_NONE }, /* Aribwatsa != Laz */
{"lb", HB_TAG('L','T','Z',' ')}, /* Luxembourgish */
@ -1339,12 +1340,14 @@ static const LangTag ot_languages[] = {
{"sla", HB_TAG_NONE }, /* Slavic [collection] != Slavey */
{"sm", HB_TAG('S','M','O',' ')}, /* Samoan */
{"sma", HB_TAG('S','S','M',' ')}, /* Southern Sami */
{"smd", HB_TAG('M','B','N',' ')}, /* Sama (retired code) -> Mbundu */
{"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */
{"sml", HB_TAG_NONE }, /* Central Sama != Somali */
{"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */
{"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */
{"smt", HB_TAG('Q','I','N',' ')}, /* Simte -> Chin */
{"sn", HB_TAG('S','N','A','0')}, /* Shona */
{"snb", HB_TAG('I','B','A',' ')}, /* Sebuyau (retired code) -> Iban */
{"snh", HB_TAG_NONE }, /* Shinabo (retired code) != Sinhala (Sinhalese) */
/*{"snk", HB_TAG('S','N','K',' ')},*/ /* Soninke */
{"so", HB_TAG('S','M','L',' ')}, /* Somali */

Просмотреть файл

@ -37,7 +37,6 @@
* For a detailed writeup on the overflow resolution algorithm see:
* docs/repacker.md
*/
struct graph_t
{
struct vertex_t
@ -140,7 +139,8 @@ struct graph_t
* the 'packed' object stack used internally in the
* serializer
*/
graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects)
template<typename T>
graph_t (const T& objects)
: parents_invalid (true),
distance_invalid (true),
positions_invalid (true),
@ -1098,8 +1098,9 @@ struct graph_t
hb_vector_t<unsigned> num_roots_for_space_;
};
static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
graph_t& sorted_graph)
static inline
bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
graph_t& sorted_graph)
{
unsigned space = 0;
hb_set_t roots_to_isolate;
@ -1147,9 +1148,10 @@ static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record
return true;
}
static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
hb_set_t& priority_bumped_parents,
graph_t& sorted_graph)
static inline
bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
hb_set_t& priority_bumped_parents,
graph_t& sorted_graph)
{
bool resolution_attempted = false;
@ -1207,8 +1209,9 @@ static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& o
* For a detailed writeup describing how the algorithm operates see:
* docs/repacker.md
*/
template<typename T>
inline hb_blob_t*
hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed,
hb_resolve_overflows (const T& packed,
hb_tag_t table_tag,
unsigned max_rounds = 20) {
// Kahn sort is ~twice as fast as shortest distance sort and works for many fonts

Просмотреть файл

@ -36,6 +36,9 @@
#include "hb-map.hh"
#include "hb-pool.hh"
#ifdef HB_EXPERIMENTAL_API
#include "hb-subset-repacker.h"
#endif
/*
* Serialize
@ -70,6 +73,24 @@ struct hb_serialize_context_t
virtual_links.fini ();
}
object_t () = default;
#ifdef HB_EXPERIMENTAL_API
object_t (const hb_object_t &o)
{
head = o.head;
tail = o.tail;
next = nullptr;
real_links.alloc (o.num_real_links);
for (unsigned i = 0 ; i < o.num_real_links; i++)
real_links.push (o.real_links[i]);
virtual_links.alloc (o.num_virtual_links);
for (unsigned i = 0; i < o.num_virtual_links; i++)
virtual_links.push (o.virtual_links[i]);
}
#endif
bool operator == (const object_t &o) const
{
// Virtual links aren't considered for equality since they don't affect the functionality
@ -95,6 +116,20 @@ struct hb_serialize_context_t
unsigned position: 28;
unsigned bias;
objidx_t objidx;
link_t () = default;
#ifdef HB_EXPERIMENTAL_API
link_t (const hb_link_t &o)
{
width = o.width;
is_signed = 0;
whence = 0;
position = o.position;
bias = 0;
objidx = o.objidx;
}
#endif
};
char *head;

Просмотреть файл

@ -256,6 +256,29 @@ hb_set_add (hb_set_t *set,
set->add (codepoint);
}
/**
* hb_set_add_sorted_array:
* @set: A set
* @sorted_codepoints: (array length=num_codepoints): Array of codepoints to add
* @num_codepoints: Length of @sorted_codepoints
*
* Adds @num_codepoints codepoints to a set at once.
* The codepoints array must be in increasing order,
* with size at least @num_codepoints.
*
* Since: 4.1.0
*/
HB_EXTERN void
hb_set_add_sorted_array (hb_set_t *set,
const hb_codepoint_t *sorted_codepoints,
unsigned int num_codepoints)
{
/* Immutible-safe. */
set->add_sorted_array (sorted_codepoints,
num_codepoints,
sizeof(hb_codepoint_t));
}
/**
* hb_set_add_range:
* @set: A set

Просмотреть файл

@ -110,6 +110,11 @@ hb_set_add_range (hb_set_t *set,
hb_codepoint_t first,
hb_codepoint_t last);
HB_EXTERN void
hb_set_add_sorted_array (hb_set_t *set,
const hb_codepoint_t *sorted_codepoints,
unsigned int num_codepoints);
HB_EXTERN void
hb_set_del (hb_set_t *set,
hb_codepoint_t codepoint);

Просмотреть файл

@ -33,6 +33,7 @@
#include "hb-aat-layout-feat-table.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
@ -55,17 +56,43 @@ const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
/* hb_face_t */
#ifndef HB_NO_BORING_EXPANSION
static inline unsigned
load_num_glyphs_from_loca (const hb_face_t *face)
{
unsigned ret = 0;
unsigned indexToLocFormat = face->table.head->indexToLocFormat;
if (indexToLocFormat <= 1)
{
bool short_offset = 0 == indexToLocFormat;
hb_blob_t *loca_blob = face->table.loca.get_blob ();
ret = hb_max (1u, loca_blob->length / (short_offset ? 2 : 4)) - 1;
}
return ret;
}
#endif
static inline unsigned
load_num_glyphs_from_maxp (const hb_face_t *face)
{
return face->table.maxp->get_num_glyphs ();
}
unsigned int
hb_face_t::load_num_glyphs () const
{
hb_sanitize_context_t c = hb_sanitize_context_t ();
c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */
hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this);
const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
unsigned ret = 0;
#ifndef HB_NO_BORING_EXPANSION
ret = hb_max (ret, load_num_glyphs_from_loca (this));
#endif
ret = hb_max (ret, load_num_glyphs_from_maxp (this));
unsigned int ret = maxp_table->get_num_glyphs ();
num_glyphs.set_relaxed (ret);
hb_blob_destroy (maxp_blob);
return ret;
}

Просмотреть файл

@ -46,13 +46,13 @@
static inline float
_hb_angle_to_ratio (float a)
{
return tanf (a * float (M_PI / 180.));
return tanf (a * float (-M_PI / 180.));
}
static inline float
_hb_ratio_to_angle (float r)
{
return atanf (r) * float (180. / M_PI);
return atanf (r) * float (-180. / M_PI);
}
/**
@ -72,8 +72,7 @@ float
hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag)
{
if (unlikely (style_tag == HB_STYLE_TAG_SLANT_RATIO))
return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE))
+ font->slant;
return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE));
hb_face_t *face = font->face;

Просмотреть файл

@ -43,8 +43,10 @@ HB_BEGIN_DECLS
* @HB_STYLE_TAG_SLANT_ANGLE: Used to vary between upright and slanted text. Values
* must be greater than -90 and less than +90. Values can be interpreted as
* the angle, in counter-clockwise degrees, of oblique slant from whatever the
* designer considers to be upright for that font design.
* designer considers to be upright for that font design. Typical right-leaning
* Italic fonts have a negative slant angle (typically around -12)
* @HB_STYLE_TAG_SLANT_RATIO: same as @HB_STYLE_TAG_SLANT_ANGLE expression as ratio.
* Typical right-leaning Italic fonts have a positive slant ratio (typically around 0.2)
* @HB_STYLE_TAG_WIDTH: Used to vary width of text from narrower to wider.
* Non-zero. Values can be interpreted as a percentage of whatever the font
* designer considers normal width for that font design.

Просмотреть файл

@ -111,7 +111,7 @@ static void _collect_layout_indices (hb_face_t *face,
retain_all_features = false;
continue;
}
if (visited_features.has (tag))
continue;
@ -249,9 +249,9 @@ static void _colr_closure (hb_face_t *face,
hb_set_t glyphset_colrv0;
for (hb_codepoint_t gid : glyphs_colred->iter ())
colr.closure_glyphs (gid, &glyphset_colrv0);
glyphs_colred->union_ (glyphset_colrv0);
//closure for COLRv1
colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
} while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
@ -458,7 +458,7 @@ _nameid_closure (hb_face_t *face,
}
/**
* hb_subset_plan_create:
* hb_subset_plan_create_or_fail:
* @face: font face to create the plan for.
* @input: a #hb_subset_input_t input.
*
@ -467,17 +467,18 @@ _nameid_closure (hb_face_t *face,
* which tables and glyphs should be retained.
*
* Return value: (transfer full): New subset plan. Destroy with
* hb_subset_plan_destroy().
* hb_subset_plan_destroy(). If there is a failure creating the plan
* nullptr will be returned.
*
* Since: 1.7.5
* Since: 4.0.0
**/
hb_subset_plan_t *
hb_subset_plan_create (hb_face_t *face,
const hb_subset_input_t *input)
hb_subset_plan_create_or_fail (hb_face_t *face,
const hb_subset_input_t *input)
{
hb_subset_plan_t *plan;
if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> ())))
return const_cast<hb_subset_plan_t *> (&Null (hb_subset_plan_t));
return nullptr;
plan->successful = true;
plan->flags = input->flags;
@ -514,8 +515,9 @@ hb_subset_plan_create (hb_face_t *face,
plan->layout_variation_indices = hb_set_create ();
plan->layout_variation_idx_map = hb_map_create ();
if (plan->in_error ()) {
return plan;
if (unlikely (plan->in_error ())) {
hb_subset_plan_destroy (plan);
return nullptr;
}
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
@ -532,6 +534,10 @@ hb_subset_plan_create (hb_face_t *face,
plan->reverse_glyph_map,
&plan->_num_output_glyphs);
if (unlikely (plan->in_error ())) {
hb_subset_plan_destroy (plan);
return nullptr;
}
return plan;
}
@ -542,7 +548,7 @@ hb_subset_plan_create (hb_face_t *face,
* Decreases the reference count on @plan, and if it reaches zero, destroys
* @plan, freeing all memory.
*
* Since: 1.7.5
* Since: 4.0.0
**/
void
hb_subset_plan_destroy (hb_subset_plan_t *plan)
@ -596,3 +602,116 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_free (plan);
}
/**
* hb_subset_plan_old_to_new_glyph_mapping:
* @plan: a subsetting plan.
*
* Returns the mapping between glyphs in the original font to glyphs in the
* subset that will be produced by @plan
*
* Return value: (transfer none):
* A pointer to the #hb_map_t of the mapping.
*
* Since: 4.0.0
**/
const hb_map_t*
hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan)
{
return plan->glyph_map;
}
/**
* hb_subset_plan_new_to_old_glyph_mapping:
* @plan: a subsetting plan.
*
* Returns the mapping between glyphs in the subset that will be produced by
* @plan and the glyph in the original font.
*
* Return value: (transfer none):
* A pointer to the #hb_map_t of the mapping.
*
* Since: 4.0.0
**/
const hb_map_t*
hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan)
{
return plan->reverse_glyph_map;
}
/**
* hb_subset_plan_unicode_to_old_glyph_mapping:
* @plan: a subsetting plan.
*
* Returns the mapping between codepoints in the original font and the
* associated glyph id in the original font.
*
* Return value: (transfer none):
* A pointer to the #hb_map_t of the mapping.
*
* Since: 4.0.0
**/
const hb_map_t*
hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan)
{
return plan->codepoint_to_glyph;
}
/**
* hb_subset_plan_reference: (skip)
* @plan: a #hb_subset_plan_t object.
*
* Increases the reference count on @plan.
*
* Return value: @plan.
*
* Since: 4.0.0
**/
hb_subset_plan_t *
hb_subset_plan_reference (hb_subset_plan_t *plan)
{
return hb_object_reference (plan);
}
/**
* hb_subset_plan_set_user_data: (skip)
* @plan: a #hb_subset_plan_t object.
* @key: The user-data key to set
* @data: A pointer to the user data
* @destroy: (nullable): A callback to call when @data is not needed anymore
* @replace: Whether to replace an existing data with the same key
*
* Attaches a user-data key/data pair to the given subset plan object.
*
* Return value: %true if success, %false otherwise
*
* Since: 4.0.0
**/
hb_bool_t
hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
hb_user_data_key_t *key,
void *data,
hb_destroy_func_t destroy,
hb_bool_t replace)
{
return hb_object_set_user_data (plan, key, data, destroy, replace);
}
/**
* hb_subset_plan_get_user_data: (skip)
* @plan: a #hb_subset_plan_t object.
* @key: The user-data key to query
*
* Fetches the user data associated with the specified key,
* attached to the specified subset plan object.
*
* Return value: (transfer none): A pointer to the user data
*
* Since: 4.0.0
**/
void *
hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (plan, key);
}

Просмотреть файл

@ -198,13 +198,4 @@ struct hb_subset_plan_t
}
};
typedef struct hb_subset_plan_t hb_subset_plan_t;
HB_INTERNAL hb_subset_plan_t *
hb_subset_plan_create (hb_face_t *face,
const hb_subset_input_t *input);
HB_INTERNAL void
hb_subset_plan_destroy (hb_subset_plan_t *plan);
#endif /* HB_SUBSET_PLAN_HH */

Просмотреть файл

@ -0,0 +1,49 @@
/*
* Copyright © 2022 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.
*
*/
#include "hb-repacker.hh"
#ifdef HB_EXPERIMENTAL_API
/**
* hb_subset_repack_or_fail:
* @hb_objects: raw array of struct hb_object_t, which provides
* object graph info
* @num_hb_objs: number of hb_object_t in the hb_objects array.
*
* Given the input object graph info, repack a table to eliminate
* offset overflows. A nullptr is returned if the repacking attempt fails.
*
* Since: EXPERIMENTAL
**/
hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_objs)
{
hb_vector_t<const hb_object_t *> packed;
packed.alloc (num_hb_objs + 1);
packed.push (nullptr);
for (unsigned i = 0 ; i < num_hb_objs ; i++)
packed.push (&(hb_objects[i]));
return hb_resolve_overflows (packed, HB_OT_TAG_GSUB);
}
#endif

Просмотреть файл

@ -0,0 +1,80 @@
/*
* Copyright © 2022 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
*/
#ifndef HB_SUBSET_REPACKER_H
#define HB_SUBSET_REPACKER_H
#include "hb.h"
HB_BEGIN_DECLS
#ifdef HB_EXPERIMENTAL_API
/**
* struct hb_link_t
* width: offsetSize in bytes
* position: position of the offset field in bytes
* from beginning of subtable
* objidx: index of subtable
**/
struct hb_link_t
{
unsigned width;
unsigned position;
unsigned objidx;
};
typedef struct hb_link_t hb_link_t;
/**
* struct hb_object_t
* head: start of object data
* tail: end of object data
* num_real_links: num of offset field in the object
* real_links: pointer to array of offset info
* num_virtual_links: num of objects that must be packed
* after current object in the final serialized order
* virtual_links: array of virtual link info
**/
struct hb_object_t
{
char *head;
char *tail;
unsigned num_real_links;
hb_link_t *real_links;
unsigned num_virtual_links;
hb_link_t *virtual_links;
};
typedef struct hb_object_t hb_object_t;
HB_EXTERN hb_blob_t*
hb_subset_repack_or_fail (hb_object_t* hb_objects,
unsigned num_hb_objs);
#endif
HB_END_DECLS
#endif /* HB_SUBSET_REPACKER_H */

Просмотреть файл

@ -343,9 +343,33 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
{
if (unlikely (!input || !source)) return hb_face_get_empty ();
hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
if (unlikely (plan->in_error ())) {
hb_subset_plan_destroy (plan);
hb_subset_plan_t *plan = hb_subset_plan_create_or_fail (source, input);
if (unlikely (!plan)) {
return nullptr;
}
hb_face_t * result = hb_subset_plan_execute_or_fail (plan);
hb_subset_plan_destroy (plan);
return result;
}
/**
* hb_subset_plan_execute_or_fail:
* @plan: a subsetting plan.
*
* Executes the provided subsetting @plan.
*
* Return value:
* on success returns a reference to generated font subset. If the subsetting operation fails
* returns nullptr.
*
* Since: 4.0.0
**/
hb_face_t *
hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
{
if (unlikely (!plan || plan->in_error ())) {
return nullptr;
}
@ -353,7 +377,7 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
bool success = true;
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
while ((hb_face_get_table_tags (plan->source, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
{
@ -367,8 +391,5 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
}
end:
hb_face_t *result = success ? hb_face_reference (plan->dest) : nullptr;
hb_subset_plan_destroy (plan);
return result;
return success ? hb_face_reference (plan->dest) : nullptr;
}

Просмотреть файл

@ -39,6 +39,15 @@ HB_BEGIN_DECLS
typedef struct hb_subset_input_t hb_subset_input_t;
/**
* hb_subset_plan_t:
*
* Contains information about how the subset operation will be executed.
* Such as mappings from the old glyph ids to the new ones in the subset.
*/
typedef struct hb_subset_plan_t hb_subset_plan_t;
/**
* hb_subset_flags_t:
* @HB_SUBSET_FLAGS_DEFAULT: all flags at their default value of false.
@ -124,7 +133,7 @@ hb_subset_input_set_user_data (hb_subset_input_t *input,
HB_EXTERN void *
hb_subset_input_get_user_data (const hb_subset_input_t *input,
hb_user_data_key_t *key);
hb_user_data_key_t *key);
HB_EXTERN hb_set_t *
hb_subset_input_unicode_set (hb_subset_input_t *input);
@ -145,6 +154,41 @@ hb_subset_input_set_flags (hb_subset_input_t *input,
HB_EXTERN hb_face_t *
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
HB_EXTERN hb_face_t *
hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan);
HB_EXTERN hb_subset_plan_t *
hb_subset_plan_create_or_fail (hb_face_t *face,
const hb_subset_input_t *input);
HB_EXTERN void
hb_subset_plan_destroy (hb_subset_plan_t *plan);
HB_EXTERN const hb_map_t*
hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan);
HB_EXTERN const hb_map_t*
hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan);
HB_EXTERN const hb_map_t*
hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan);
HB_EXTERN hb_subset_plan_t *
hb_subset_plan_reference (hb_subset_plan_t *plan);
HB_EXTERN hb_bool_t
hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
hb_user_data_key_t *key,
void *data,
hb_destroy_func_t destroy,
hb_bool_t replace);
HB_EXTERN void *
hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
hb_user_data_key_t *key);
HB_END_DECLS
#endif /* HB_SUBSET_H */

Просмотреть файл

@ -41,13 +41,13 @@ HB_BEGIN_DECLS
*
* The major component of the library version available at compile-time.
*/
#define HB_VERSION_MAJOR 3
#define HB_VERSION_MAJOR 4
/**
* HB_VERSION_MINOR:
*
* The minor component of the library version available at compile-time.
*/
#define HB_VERSION_MINOR 4
#define HB_VERSION_MINOR 1
/**
* HB_VERSION_MICRO:
*
@ -60,7 +60,7 @@ HB_BEGIN_DECLS
*
* A string literal containing the library version available at compile-time.
*/
#define HB_VERSION_STRING "3.4.0"
#define HB_VERSION_STRING "4.1.0"
/**
* HB_VERSION_ATLEAST:

Просмотреть файл

@ -42,7 +42,7 @@
#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty ()
#endif
#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API)
#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW)
static void
svg_dump (hb_face_t *face, unsigned face_index)
{
@ -129,48 +129,60 @@ png_dump (hb_face_t *face, unsigned face_index)
hb_font_destroy (font);
}
struct user_data_t
struct draw_data_t
{
FILE *f;
hb_position_t ascender;
};
static void
move_to (hb_position_t to_x, hb_position_t to_y, user_data_t &user_data)
move_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
hb_draw_state_t *st,
float to_x, float to_y,
void *)
{
fprintf (user_data.f, "M%d,%d", to_x, user_data.ascender - to_y);
fprintf (draw_data->f, "M%g,%g", to_x, draw_data->ascender - to_y);
}
static void
line_to (hb_position_t to_x, hb_position_t to_y, user_data_t &user_data)
line_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
hb_draw_state_t *st,
float to_x, float to_y,
void *)
{
fprintf (user_data.f, "L%d,%d", to_x, user_data.ascender - to_y);
fprintf (draw_data->f, "L%g,%g", to_x, draw_data->ascender - to_y);
}
static void
quadratic_to (hb_position_t control_x, hb_position_t control_y,
hb_position_t to_x, hb_position_t to_y,
user_data_t &user_data)
quadratic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
hb_draw_state_t *st,
float control_x, float control_y,
float to_x, float to_y,
void *)
{
fprintf (user_data.f, "Q%d,%d %d,%d", control_x, user_data.ascender - control_y,
to_x, user_data.ascender - to_y);
fprintf (draw_data->f, "Q%g,%g %g,%g", control_x, draw_data->ascender - control_y,
to_x, draw_data->ascender - to_y);
}
static void
cubic_to (hb_position_t control1_x, hb_position_t control1_y,
hb_position_t control2_x, hb_position_t control2_y,
hb_position_t to_x, hb_position_t to_y,
user_data_t &user_data)
cubic_to (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
hb_draw_state_t *st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y,
void *)
{
fprintf (user_data.f, "C%d,%d %d,%d %d,%d", control1_x, user_data.ascender - control1_y,
control2_x, user_data.ascender - control2_y,
to_x, user_data.ascender - to_y);
fprintf (draw_data->f, "C%g,%g %g,%g %g,%g", control1_x, draw_data->ascender - control1_y,
control2_x, draw_data->ascender - control2_y,
to_x, draw_data->ascender - to_y);
}
static void
close_path (user_data_t &user_data)
close_path (hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
hb_draw_state_t *st,
void *)
{
fprintf (user_data.f, "Z");
fprintf (draw_data->f, "Z");
}
static void
@ -218,9 +230,9 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index
" viewBox=\"%d %d %d %d\">\n",
extents.x_bearing, 0,
extents.x_bearing + extents.width, -extents.height);
user_data_t user_data;
user_data.ascender = extents.y_bearing;
user_data.f = f;
draw_data_t draw_data;
draw_data.ascender = extents.y_bearing;
draw_data.f = f;
for (unsigned layer = 0; layer < num_layers; ++layer)
{
@ -232,8 +244,7 @@ layered_glyph_dump (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index
if (hb_color_get_alpha (color) != 255)
fprintf (f, "fill-opacity=\"%.3f\"", (double) hb_color_get_alpha (color) / 255.);
fprintf (f, "d=\"");
if (!hb_font_draw_glyph (font, layers[layer].glyph, funcs, &user_data))
printf ("Failed to decompose layer %d while %d\n", layers[layer].glyph, gid);
hb_font_get_glyph_shape (font, layers[layer].glyph, funcs, &draw_data);
fprintf (f, "\"/>\n");
}
@ -269,11 +280,10 @@ dump_glyphs (hb_font_t *font, hb_draw_funcs_t *funcs, unsigned face_index)
" viewBox=\"%d %d %d %d\"><path d=\"",
extents.x_bearing, 0,
extents.x_bearing + extents.width, font_extents.ascender - font_extents.descender);
user_data_t user_data;
user_data.ascender = font_extents.ascender;
user_data.f = f;
if (!hb_font_draw_glyph (font, gid, funcs, &user_data))
printf ("Failed to decompose gid: %d\n", gid);
draw_data_t draw_data;
draw_data.ascender = font_extents.ascender;
draw_data.f = f;
hb_font_get_glyph_shape (font, gid, funcs, &draw_data);
fprintf (f, "\"/></svg>");
fclose (f);
}
@ -300,11 +310,11 @@ dump_glyphs (hb_blob_t *blob, const char *font_name)
fclose (font_name_file);
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to);
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to);
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to);
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to);
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path);
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, nullptr, nullptr);
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, nullptr, nullptr);
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, nullptr, nullptr);
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, nullptr, nullptr);
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, nullptr, nullptr);
unsigned num_faces = hb_face_count (blob);
for (unsigned face_index = 0; face_index < num_faces; ++face_index)
@ -512,7 +522,7 @@ main (int argc, char **argv)
#ifndef MAIN_CC_NO_PRIVATE_API
print_layout_info_using_private_api (blob);
#endif
#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API)
#if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW)
dump_glyphs (blob, argv[1]);
#endif
hb_blob_destroy (blob);

Просмотреть файл

@ -276,11 +276,15 @@ hb_subset_sources = files(
'hb-subset-input.hh',
'hb-subset-plan.cc',
'hb-subset-plan.hh',
'hb-subset-repacker.cc',
'hb-subset.cc',
'hb-subset.hh',
)
hb_subset_headers = files('hb-subset.h')
hb_subset_headers = files(
'hb-subset.h',
'hb-subset-repacker.h'
)
hb_gobject_sources = files(
'hb-gobject-structs.cc'

Просмотреть файл

@ -86,6 +86,7 @@ UNIFIED_SOURCES += [
'hb-subset-cff-common.cc',
'hb-subset-cff1.cc',
'hb-subset-cff2.cc',
'hb-subset-repacker.cc',
'hb-unicode.cc',
]

Просмотреть файл

@ -2,7 +2,7 @@
# Not derivable
# Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
# Updated for Unicode 10.0 by Andrew Glass 2017-07-25
# Amended for Unicode 10.0 by Andrew Glass 2018-09-21
# Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
# Updated for L2/19-083 by Andrew Glass 2019-05-06
# Updated for Unicode 12.1 by Andrew Glass 2019-05-30
# Updated for Unicode 13.0 by Andrew Glass 2020-07-28
@ -58,16 +58,16 @@ AA35   ; Top # Mn       CHAM CONSONANT SIGN
# Indic_Positional_Category=Bottom
0859..085B ; Bottom # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
18A9 ; Bottom # Mn MONGOLIAN LETTER ALI GALI DAGALGA
10AE5 ; Bottom # Mn MANICHAEAN ABBREVIATION MARK ABOVE # Overridden, ccc controls order
10AE5 ; Bottom # Mn MANICHAEAN ABBREVIATION MARK ABOVE # Overriden, ccc controls order
10AE6 ; Bottom # Mn MANICHAEAN ABBREVIATION MARK BELOW
10F46..10F47 ; Bottom # Mn [2] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING TWO DOTS BELOW
10F48..10F4A ; Bottom # Mn [3] SOGDIAN COMBINING DOT ABOVE..SOGDIAN COMBINING CURVE ABOVE # Overridden, ccc controls order
10F48..10F4A ; Bottom # Mn [3] SOGDIAN COMBINING DOT ABOVE..SOGDIAN COMBINING CURVE ABOVE # Overriden, ccc controls order
10F4B ; Bottom # Mn SOGDIAN COMBINING CURVE BELOW
10F4C ; Bottom # Mn SOGDIAN COMBINING HOOK ABOVE # Overridden, ccc controls order
10F4C ; Bottom # Mn SOGDIAN COMBINING HOOK ABOVE # Overriden, ccc controls order
10F4D..10F50 ; Bottom # Mn [4] SOGDIAN COMBINING HOOK BELOW..SOGDIAN COMBINING STROKE BELOW
10F82 ; Bottom # Mn OLD UYGHUR COMBINING DOT ABOVE # Overridden, ccc controls order
10F82 ; Bottom # Mn OLD UYGHUR COMBINING DOT ABOVE # Overriden, ccc controls order
10F83 ; Bottom # Mn OLD UYGHUR COMBINING DOT BELOW
10F84 ; Bottom # Mn OLD UYGHUR COMBINING TWO DOTS ABOVE # Overridden, ccc controls order
10F84 ; Bottom # Mn OLD UYGHUR COMBINING TWO DOTS ABOVE # Overriden, ccc controls order
10F85 ; Bottom # Mn OLD UYGHUR COMBINING TWO DOTS BELOW
16F4F ; Bottom # Mn MIAO SIGN CONSONANT MODIFIER BAR
16F51..16F87 ; Bottom # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI

Просмотреть файл

@ -5,7 +5,7 @@
MY_TEMP_DIR=`mktemp -d -t harfbuzz_update.XXXXXX` || exit 1
VERSION=3.4.0
VERSION=4.1.0
git clone https://github.com/harfbuzz/harfbuzz ${MY_TEMP_DIR}/harfbuzz
git -C ${MY_TEMP_DIR}/harfbuzz checkout ${VERSION}