зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1573841 - Update HarfBuzz to 2.6.0. r=jfkthame
Differential Revision: https://phabricator.services.mozilla.com/D42034 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
638d025a66
Коммит
943db786b5
|
@ -1,3 +1,26 @@
|
|||
Overview of changes leading to 2.6.0
|
||||
Tuesday, August 13, 2019
|
||||
====================================
|
||||
- New OpenType metrics, baseline, and metadata table access APIs.
|
||||
- New API to set font variations to a named-instance.
|
||||
- New hb-gdi.h header and API for creating hb_face_t from HFONT.
|
||||
- Amalgam: Provide a single-file harfbuzz.cc file for easier alternate building.
|
||||
- More size-reduction configurable options, enabled by HB_TINY.
|
||||
- New API:
|
||||
+hb_font_set_var_named_instance()
|
||||
+hb_gdi_face_create()
|
||||
+hb_ot_layout_baseline_tag_t
|
||||
+hb_ot_layout_get_baseline()
|
||||
+hb_ot_meta_tag_t
|
||||
+hb_ot_meta_get_entry_tags()
|
||||
+hb_ot_meta_reference_entry()
|
||||
+hb_ot_metrics_tag_t
|
||||
+hb_ot_metrics_get_position()
|
||||
+hb_ot_metrics_get_variation()
|
||||
+hb_ot_metrics_get_x_variation()
|
||||
+hb_ot_metrics_get_y_variation()
|
||||
|
||||
|
||||
Overview of changes leading to 2.5.3
|
||||
Wednesday, June 26, 2019
|
||||
====================================
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
This directory contains the HarfBuzz source from the upstream repo:
|
||||
https://github.com/harfbuzz/harfbuzz
|
||||
|
||||
Current version: 2.5.3 [commit b14e413fae8f14b75c5956e9b38e413c878ded0c]
|
||||
Current version: 2.6.0 [commit 6461143b44f81a4190d3f1cb02238750536f08e4]
|
||||
|
||||
UPDATING:
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AC_PREREQ([2.64])
|
||||
AC_INIT([HarfBuzz],
|
||||
[2.5.3],
|
||||
[2.6.0],
|
||||
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||
[harfbuzz],
|
||||
[http://harfbuzz.org/])
|
||||
|
@ -361,6 +361,28 @@ AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe)
|
|||
|
||||
dnl ===========================================================================
|
||||
|
||||
AC_ARG_WITH(gdi,
|
||||
[AS_HELP_STRING([--with-gdi=@<:@yes/no/auto@:>@],
|
||||
[Provide GDI integration helpers @<:@default=no@:>@])],,
|
||||
[with_gdi=no])
|
||||
have_gdi=false
|
||||
if test "x$with_gdi" = "xyes" -o "x$with_gdi" = "xauto"; then
|
||||
AC_CHECK_HEADERS(windows.h, have_gdi=true)
|
||||
fi
|
||||
if test "x$with_gdi" = "xyes" -a "x$have_gdi" != "xtrue"; then
|
||||
AC_MSG_ERROR([gdi support requested but not found])
|
||||
fi
|
||||
if $have_gdi; then
|
||||
GDI_CFLAGS=
|
||||
GDI_LIBS="-lgdi32"
|
||||
AC_SUBST(GDI_CFLAGS)
|
||||
AC_SUBST(GDI_LIBS)
|
||||
AC_DEFINE(HAVE_GDI, 1, [Have GDI library])
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_GDI, $have_gdi)
|
||||
|
||||
dnl ===========================================================================
|
||||
|
||||
AC_ARG_WITH(directwrite,
|
||||
[AS_HELP_STRING([--with-directwrite=@<:@yes/no/auto@:>@],
|
||||
[Use the DirectWrite library (experimental) @<:@default=no@:>@])],,
|
||||
|
@ -376,7 +398,7 @@ if test "x$with_directwrite" = "xyes" -a "x$have_directwrite" != "xtrue"; then
|
|||
fi
|
||||
if $have_directwrite; then
|
||||
DIRECTWRITE_CXXFLAGS=
|
||||
DIRECTWRITE_LIBS="-ldwrite"
|
||||
DIRECTWRITE_LIBS=
|
||||
AC_SUBST(DIRECTWRITE_CXXFLAGS)
|
||||
AC_SUBST(DIRECTWRITE_LIBS)
|
||||
AC_DEFINE(HAVE_DIRECTWRITE, 1, [Have DirectWrite library])
|
||||
|
@ -510,6 +532,7 @@ Additional shapers (the more the merrier):
|
|||
Platform shapers (not normally needed):
|
||||
CoreText: ${have_coretext}
|
||||
DirectWrite: ${have_directwrite}
|
||||
GDI: ${have_gdi}
|
||||
Uniscribe: ${have_uniscribe}
|
||||
|
||||
Other features:
|
||||
|
|
|
@ -12,9 +12,15 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
|
|||
TESTS =
|
||||
check_PROGRAMS =
|
||||
|
||||
EXTRA_DIST += harfbuzz.cc
|
||||
|
||||
# Convenience targets:
|
||||
lib: $(BUILT_SOURCES) libharfbuzz.la
|
||||
libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES)
|
||||
tiny:
|
||||
$(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Os -DHB_TINY $(CPPFLAGS)" libs
|
||||
tinyz:
|
||||
$(MAKE) $(AM_MAKEFLAGS) CPPFLAGS="-Oz -DHB_TINY $(CPPFLAGS)" libs
|
||||
|
||||
lib_LTLIBRARIES = libharfbuzz.la
|
||||
|
||||
|
@ -76,6 +82,13 @@ HBSOURCES += $(HB_DIRECTWRITE_sources)
|
|||
HBHEADERS += $(HB_DIRECTWRITE_headers)
|
||||
endif
|
||||
|
||||
if HAVE_GDI
|
||||
HBCFLAGS += $(GDI_CXXFLAGS)
|
||||
HBNONPCLIBS += $(GDI_LIBS)
|
||||
HBSOURCES += $(HB_GDI_sources)
|
||||
HBHEADERS += $(HB_GDI_headers)
|
||||
endif
|
||||
|
||||
if HAVE_CORETEXT
|
||||
HBCFLAGS += $(CORETEXT_CFLAGS)
|
||||
HBNONPCLIBS += $(CORETEXT_LIBS)
|
||||
|
@ -249,31 +262,38 @@ GENERATORS = \
|
|||
$(NULL)
|
||||
EXTRA_DIST += $(GENERATORS)
|
||||
|
||||
unicode-tables: arabic-table indic-table tag-table use-table emoji-table
|
||||
unicode-tables: \
|
||||
arabic-table \
|
||||
emoji-table \
|
||||
indic-table \
|
||||
tag-table \
|
||||
ucd-table \
|
||||
use-table \
|
||||
emoji-table \
|
||||
$(NULL)
|
||||
|
||||
arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-arabic-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-ot-shape-complex-arabic-table.hh; false)
|
||||
|
||||
emoji-table: gen-emoji-table.py emoji-data.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false)
|
||||
indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-indic-table.cc \
|
||||
|| ($(RM) $(srcdir)/hb-ot-shape-complex-indic-table.cc; false)
|
||||
|
||||
tag-table: gen-tag-table.py languagetags language-subtag-registry
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-tag-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-ot-tag-table.hh; false)
|
||||
|
||||
ucd-table: gen-ucd-table.py ucd.nounihan.grouped.zip hb-common.h
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ucd-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-ucd-table.hh; false)
|
||||
use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \
|
||||
|| ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false)
|
||||
|
||||
vowel-constraints: gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \
|
||||
|| ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false)
|
||||
|
||||
emoji-table: gen-emoji-table.py emoji-data.txt
|
||||
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \
|
||||
|| ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false)
|
||||
|
||||
built-sources: $(BUILT_SOURCES)
|
||||
|
||||
|
@ -292,10 +312,27 @@ $(srcdir)/%.hh: $(srcdir)/%.rl
|
|||
$(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \
|
||||
|| ($(RM) "$@"; false)
|
||||
|
||||
harfbuzz.cc: Makefile.sources
|
||||
$(AM_V_GEN) \
|
||||
for f in \
|
||||
$(HB_BASE_sources) \
|
||||
$(HB_GLIB_sources) \
|
||||
$(HB_FT_sources) \
|
||||
$(HB_GRAPHITE2_sources) \
|
||||
$(HB_UNISCRIBE_sources) \
|
||||
$(HB_GDI_sources) \
|
||||
$(HB_DIRECTWRITE_sources) \
|
||||
$(HB_CORETEXT_sources) \
|
||||
; do echo '#include "'$$f'"'; done | \
|
||||
grep '[.]cc"' > $(srcdir)/harfbuzz.cc \
|
||||
|| ($(RM) $(srcdir)/harfbuzz.cc; false)
|
||||
BUILT_SOURCES += harfbuzz.cc
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
main \
|
||||
test \
|
||||
test-buffer-serialize \
|
||||
test-ot-meta \
|
||||
test-ot-name \
|
||||
test-gpos-size-params \
|
||||
test-gsub-would-substitute \
|
||||
|
@ -314,6 +351,10 @@ test_buffer_serialize_SOURCES = test-buffer-serialize.cc
|
|||
test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
|
||||
test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_ot_meta_SOURCES = test-ot-meta.cc
|
||||
test_ot_meta_CPPFLAGS = $(HBCFLAGS)
|
||||
test_ot_meta_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_ot_name_SOURCES = test-ot-name.cc
|
||||
test_ot_name_CPPFLAGS = $(HBCFLAGS)
|
||||
test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
@ -370,7 +411,7 @@ dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
|
|||
dump_use_data_CPPFLAGS = $(HBCFLAGS)
|
||||
dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
COMPILED_TESTS = test-algs test-iter test-meta test-ot-tag test-unicode-ranges
|
||||
COMPILED_TESTS = test-algs test-iter test-meta test-ot-tag test-unicode-ranges test-bimap
|
||||
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
|
||||
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
check_PROGRAMS += $(COMPILED_TESTS)
|
||||
|
@ -396,6 +437,10 @@ test_unicode_ranges_SOURCES = test-unicode-ranges.cc
|
|||
test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
test_bimap_SOURCES = test-bimap.cc hb-static.cc
|
||||
test_bimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_bimap_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
TESTS_ENVIRONMENT = \
|
||||
srcdir="$(srcdir)" \
|
||||
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
|
||||
|
|
|
@ -10,6 +10,7 @@ HB_BASE_sources = \
|
|||
hb-aat-layout-kerx-table.hh \
|
||||
hb-aat-layout-lcar-table.hh \
|
||||
hb-aat-layout-morx-table.hh \
|
||||
hb-aat-layout-opbd-table.hh \
|
||||
hb-aat-layout-trak-table.hh \
|
||||
hb-aat-layout.cc \
|
||||
hb-aat-layout.hh \
|
||||
|
@ -88,6 +89,10 @@ HB_BASE_sources = \
|
|||
hb-ot-math-table.hh \
|
||||
hb-ot-math.cc \
|
||||
hb-ot-maxp-table.hh \
|
||||
hb-ot-meta-table.hh \
|
||||
hb-ot-meta.cc \
|
||||
hb-ot-metrics.cc \
|
||||
hb-ot-metrics.hh \
|
||||
hb-ot-name-language-static.hh \
|
||||
hb-ot-name-language.hh \
|
||||
hb-ot-name-table.hh \
|
||||
|
@ -191,6 +196,8 @@ HB_BASE_headers = \
|
|||
hb-ot-font.h \
|
||||
hb-ot-layout.h \
|
||||
hb-ot-math.h \
|
||||
hb-ot-meta.h \
|
||||
hb-ot-metrics.h \
|
||||
hb-ot-name.h \
|
||||
hb-ot-shape.h \
|
||||
hb-ot-var.h \
|
||||
|
@ -222,6 +229,9 @@ HB_CORETEXT_headers = hb-coretext.h
|
|||
HB_DIRECTWRITE_sources = hb-directwrite.cc
|
||||
HB_DIRECTWRITE_headers = hb-directwrite.h
|
||||
|
||||
HB_GDI_sources = hb-gdi.cc
|
||||
HB_GDI_headers = hb-gdi.h
|
||||
|
||||
HB_UNISCRIBE_sources = hb-uniscribe.cc
|
||||
HB_UNISCRIBE_headers = hb-uniscribe.h
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from __future__ import print_function, division, absolute_import
|
|||
import sys
|
||||
import os.path
|
||||
from collections import OrderedDict
|
||||
import packTab
|
||||
|
||||
if len (sys.argv) != 2:
|
||||
print("usage: ./gen-emoji-table.py emoji-data.txt", file=sys.stderr)
|
||||
|
@ -52,14 +53,19 @@ print ()
|
|||
print ('#include "hb-unicode.hh"')
|
||||
print ()
|
||||
|
||||
for typ,s in ranges.items():
|
||||
for typ, s in ranges.items():
|
||||
if typ != "Extended_Pictographic": continue
|
||||
|
||||
arr = dict()
|
||||
for start,end in s:
|
||||
for i in range(start,end):
|
||||
arr[i] = 1
|
||||
|
||||
sol = packTab.pack_table(arr, 0, compression=3)
|
||||
code = packTab.Code('_hb_emoji')
|
||||
sol.genCode(code, 'is_'+typ)
|
||||
code.print_c(linkage='static inline')
|
||||
print()
|
||||
print("static const struct hb_unicode_range_t _hb_unicode_emoji_%s_table[] =" % typ)
|
||||
print("{")
|
||||
for pair in sorted(s):
|
||||
print(" {0x%04X, 0x%04X}," % pair)
|
||||
print("};")
|
||||
|
||||
print ()
|
||||
print ("#endif /* HB_UNICODE_EMOJI_TABLE_HH */")
|
||||
|
|
|
@ -98,6 +98,10 @@ for h in headers:
|
|||
print (" * %s" % (l.strip()))
|
||||
print (" */")
|
||||
print ()
|
||||
print ('#include "hb.hh"')
|
||||
print ()
|
||||
print ('#ifndef HB_NO_OT_SHAPE')
|
||||
print ()
|
||||
print ('#include "hb-ot-shape-complex-indic.hh"')
|
||||
print ()
|
||||
|
||||
|
@ -245,12 +249,14 @@ print ("}")
|
|||
print ()
|
||||
print ("#undef _")
|
||||
for i in range (2):
|
||||
print()
|
||||
print
|
||||
vv = sorted (values[i].keys ())
|
||||
for v in vv:
|
||||
print ("#undef %s_%s" %
|
||||
(what_short[i], short[i][v]))
|
||||
print ()
|
||||
print ()
|
||||
print ('#endif')
|
||||
print ("/* == End of generated table == */")
|
||||
|
||||
# Maintain at least 30% occupancy in the table */
|
||||
|
|
|
@ -6,8 +6,8 @@ import io, os.path, sys, re
|
|||
import logging
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
|
||||
|
||||
if len (sys.argv) != 2:
|
||||
print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml", file=sys.stderr)
|
||||
if len (sys.argv) not in (2, 3):
|
||||
print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml [/path/to/hb-common.h]", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# https://github.com/harfbuzz/packtab
|
||||
|
@ -18,6 +18,8 @@ logging.info('Loading UCDXML...')
|
|||
ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1])
|
||||
ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml)
|
||||
|
||||
hb_common_h = 'hb-common.h' if len (sys.argv) < 3 else sys.argv[2]
|
||||
|
||||
logging.info('Preparing data tables...')
|
||||
|
||||
gc = [u['gc'] for u in ucd]
|
||||
|
@ -68,7 +70,7 @@ for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu'
|
|||
sc_order = dict()
|
||||
sc_array = []
|
||||
sc_re = re.compile(r"\b(HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]")
|
||||
for line in open('hb-common.h'):
|
||||
for line in open(hb_common_h):
|
||||
m = sc_re.search (line)
|
||||
if not m: continue
|
||||
name = m.group(1)
|
||||
|
|
|
@ -419,6 +419,10 @@ for h in headers:
|
|||
print (" * %s" % (l.strip()))
|
||||
print (" */")
|
||||
print ()
|
||||
print ('#include "hb.hh"')
|
||||
print ()
|
||||
print ('#ifndef HB_NO_OT_SHAPE')
|
||||
print ()
|
||||
print ('#include "hb-ot-shape-complex-use.hh"')
|
||||
print ()
|
||||
|
||||
|
@ -533,6 +537,8 @@ for k,v in sorted(use_positions.items()):
|
|||
tag = k + suf
|
||||
print ("#undef %s" % tag)
|
||||
print ()
|
||||
print ()
|
||||
print ('#endif')
|
||||
print ("/* == End of generated table == */")
|
||||
|
||||
# Maintain at least 50% occupancy in the table */
|
||||
|
|
|
@ -157,6 +157,11 @@ print (' *')
|
|||
for line in scripts_header:
|
||||
print (' * %s' % line.strip ())
|
||||
print (' */')
|
||||
|
||||
print ()
|
||||
print ('#include "hb.hh"')
|
||||
print ()
|
||||
print ('#ifndef HB_NO_OT_SHAPE')
|
||||
print ()
|
||||
print ('#include "hb-ot-shape-complex-vowel-constraints.hh"')
|
||||
print ()
|
||||
|
@ -223,4 +228,6 @@ print (' }')
|
|||
print ('}')
|
||||
|
||||
print ()
|
||||
print ()
|
||||
print ('#endif')
|
||||
print ('/* == End of generated functions == */')
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
#include "hb-aat-layout.cc"
|
||||
#include "hb-aat-map.cc"
|
||||
#include "hb-blob.cc"
|
||||
#include "hb-buffer-serialize.cc"
|
||||
#include "hb-buffer.cc"
|
||||
#include "hb-common.cc"
|
||||
#include "hb-face.cc"
|
||||
#include "hb-fallback-shape.cc"
|
||||
#include "hb-font.cc"
|
||||
#include "hb-map.cc"
|
||||
#include "hb-ot-cff1-table.cc"
|
||||
#include "hb-ot-cff2-table.cc"
|
||||
#include "hb-ot-color.cc"
|
||||
#include "hb-ot-face.cc"
|
||||
#include "hb-ot-font.cc"
|
||||
#include "hb-ot-layout.cc"
|
||||
#include "hb-ot-map.cc"
|
||||
#include "hb-ot-math.cc"
|
||||
#include "hb-ot-meta.cc"
|
||||
#include "hb-ot-metrics.cc"
|
||||
#include "hb-ot-name.cc"
|
||||
#include "hb-ot-shape-complex-arabic.cc"
|
||||
#include "hb-ot-shape-complex-default.cc"
|
||||
#include "hb-ot-shape-complex-hangul.cc"
|
||||
#include "hb-ot-shape-complex-hebrew.cc"
|
||||
#include "hb-ot-shape-complex-indic-table.cc"
|
||||
#include "hb-ot-shape-complex-indic.cc"
|
||||
#include "hb-ot-shape-complex-khmer.cc"
|
||||
#include "hb-ot-shape-complex-myanmar.cc"
|
||||
#include "hb-ot-shape-complex-thai.cc"
|
||||
#include "hb-ot-shape-complex-use-table.cc"
|
||||
#include "hb-ot-shape-complex-use.cc"
|
||||
#include "hb-ot-shape-complex-vowel-constraints.cc"
|
||||
#include "hb-ot-shape-fallback.cc"
|
||||
#include "hb-ot-shape-normalize.cc"
|
||||
#include "hb-ot-shape.cc"
|
||||
#include "hb-ot-tag.cc"
|
||||
#include "hb-ot-var.cc"
|
||||
#include "hb-set.cc"
|
||||
#include "hb-shape-plan.cc"
|
||||
#include "hb-shape.cc"
|
||||
#include "hb-shaper.cc"
|
||||
#include "hb-static.cc"
|
||||
#include "hb-ucd.cc"
|
||||
#include "hb-unicode.cc"
|
||||
#include "hb-warning.cc"
|
||||
#include "hb-glib.cc"
|
||||
#include "hb-ft.cc"
|
||||
#include "hb-graphite2.cc"
|
||||
#include "hb-uniscribe.cc"
|
||||
#include "hb-gdi.cc"
|
||||
#include "hb-directwrite.cc"
|
||||
#include "hb-coretext.cc"
|
|
@ -47,17 +47,16 @@ struct SettingName
|
|||
hb_aat_layout_feature_selector_t get_selector () const
|
||||
{ return (hb_aat_layout_feature_selector_t) (unsigned) setting; }
|
||||
|
||||
void get_info (hb_aat_layout_feature_selector_info_t *s,
|
||||
hb_aat_layout_feature_selector_t default_selector) const
|
||||
hb_aat_layout_feature_selector_info_t get_info (hb_aat_layout_feature_selector_t default_selector) const
|
||||
{
|
||||
s->name_id = nameIndex;
|
||||
|
||||
s->enable = (hb_aat_layout_feature_selector_t) (unsigned int) setting;
|
||||
s->disable = default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID ?
|
||||
(hb_aat_layout_feature_selector_t) (s->enable + 1) :
|
||||
default_selector;
|
||||
|
||||
s->reserved = 0;
|
||||
return {
|
||||
nameIndex,
|
||||
(hb_aat_layout_feature_selector_t) (unsigned int) setting,
|
||||
default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID
|
||||
? (hb_aat_layout_feature_selector_t) (setting + 1)
|
||||
: default_selector,
|
||||
0
|
||||
};
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -117,9 +116,10 @@ struct FeatureName
|
|||
|
||||
if (selectors_count)
|
||||
{
|
||||
hb_array_t<const SettingName> arr = settings_table.sub_array (start_offset, selectors_count);
|
||||
for (unsigned int i = 0; i < arr.length; i++)
|
||||
settings_table[start_offset + i].get_info (&selectors[i], default_selector);
|
||||
+ settings_table.sub_array (start_offset, selectors_count)
|
||||
| hb_map ([=] (const SettingName& setting) { return setting.get_info (default_selector); })
|
||||
| hb_sink (hb_array (selectors, *selectors_count))
|
||||
;
|
||||
}
|
||||
return settings_table.length;
|
||||
}
|
||||
|
@ -162,21 +162,18 @@ struct feat
|
|||
unsigned int *count,
|
||||
hb_aat_layout_feature_type_t *features) const
|
||||
{
|
||||
unsigned int feature_count = featureNameCount;
|
||||
if (count && *count)
|
||||
if (count)
|
||||
{
|
||||
unsigned int len = hb_min (feature_count - start_offset, *count);
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
features[i] = namesZ[i + start_offset].get_feature_type ();
|
||||
*count = len;
|
||||
+ namesZ.as_array (featureNameCount).sub_array (start_offset, count)
|
||||
| hb_map (&FeatureName::get_feature_type)
|
||||
| hb_sink (hb_array (features, *count))
|
||||
;
|
||||
}
|
||||
return featureNameCount;
|
||||
}
|
||||
|
||||
const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
|
||||
{
|
||||
return namesZ.bsearch (featureNameCount, feature_type);
|
||||
}
|
||||
{ return namesZ.bsearch (featureNameCount, feature_type); }
|
||||
|
||||
hb_ot_name_id_t get_feature_name_id (hb_aat_layout_feature_type_t feature) const
|
||||
{ return get_feature (feature).get_feature_name_id (); }
|
||||
|
|
|
@ -55,17 +55,21 @@ struct lcar
|
|||
if (caret_count)
|
||||
{
|
||||
hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
|
||||
unsigned int count = arr.length;
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
switch (format)
|
||||
switch (format)
|
||||
{
|
||||
case 0:
|
||||
for (unsigned int i = 0; i < arr.length; ++i)
|
||||
caret_array[i] = font->em_scale_dir (arr[i], direction);
|
||||
break;
|
||||
case 1:
|
||||
for (unsigned int i = 0; i < arr.length; ++i)
|
||||
{
|
||||
case 0: caret_array[i] = font->em_scale_dir (arr[i], direction); break;
|
||||
case 1:
|
||||
hb_position_t x, y;
|
||||
font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
|
||||
caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return array.len;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright © 2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef HB_AAT_LAYOUT_OPBD_TABLE_HH
|
||||
#define HB_AAT_LAYOUT_OPBD_TABLE_HH
|
||||
|
||||
#include "hb-aat-layout-common.hh"
|
||||
#include "hb-open-type.hh"
|
||||
|
||||
/*
|
||||
* opbd -- Optical Bounds
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6opbd.html
|
||||
*/
|
||||
#define HB_AAT_TAG_opbd HB_TAG('o','p','b','d')
|
||||
|
||||
|
||||
namespace AAT {
|
||||
|
||||
struct OpticalBounds
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
HBINT16 leftSide;
|
||||
HBINT16 topSide;
|
||||
HBINT16 rightSide;
|
||||
HBINT16 bottomSide;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
struct opbd
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_AAT_TAG_opbd;
|
||||
|
||||
bool get_optical_bounds (hb_font_t *font, hb_codepoint_t glyph_id,
|
||||
hb_position_t *left, hb_position_t *top,
|
||||
hb_position_t *right, hb_position_t *bottom) const
|
||||
{
|
||||
const OffsetTo<OpticalBounds> *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ());
|
||||
if (!bounds_offset) return false;
|
||||
const OpticalBounds &bounds = this+*bounds_offset;
|
||||
switch (format)
|
||||
{
|
||||
case 0:
|
||||
*left = font->em_scale_x (bounds.leftSide);
|
||||
*top = font->em_scale_y (bounds.topSide);
|
||||
*right = font->em_scale_x (bounds.rightSide);
|
||||
*bottom = font->em_scale_y (bounds.bottomSide);
|
||||
return true;
|
||||
case 1:
|
||||
hb_position_t ignore;
|
||||
return font->get_glyph_contour_point (glyph_id, bounds.leftSide, left, &ignore) &&
|
||||
font->get_glyph_contour_point (glyph_id, bounds.topSide, &ignore, top) &&
|
||||
font->get_glyph_contour_point (glyph_id, bounds.rightSide, right, &ignore) &&
|
||||
font->get_glyph_contour_point (glyph_id, bounds.bottomSide, &ignore, bottom);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
version.major == 1 &&
|
||||
lookupTable.sanitize (c, this)));
|
||||
}
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version number of the optical bounds
|
||||
* table (0x00010000 for the current version). */
|
||||
HBUINT16 format; /* Format of the optical bounds table.
|
||||
* Format 0 indicates distance and Format 1 indicates
|
||||
* control point. */
|
||||
Lookup<OffsetTo<OpticalBounds>>
|
||||
lookupTable; /* Lookup table associating glyphs with the four
|
||||
* int16 values for the left-side, top-side,
|
||||
* right-side, and bottom-side optical bounds. */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (8);
|
||||
};
|
||||
|
||||
} /* namespace AAT */
|
||||
|
||||
|
||||
#endif /* HB_AAT_LAYOUT_OPBD_TABLE_HH */
|
|
@ -75,9 +75,6 @@ AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
|
|||
#endif
|
||||
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-aat-layout
|
||||
* @title: hb-aat-layout
|
||||
|
@ -88,6 +85,8 @@ AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
|
|||
**/
|
||||
|
||||
|
||||
#if !defined(HB_NO_AAT) || defined(HAVE_CORETEXT)
|
||||
|
||||
/* Table data courtesy of Apple. Converted from mnemonics to integers
|
||||
* when moving to this file. */
|
||||
static const hb_aat_feature_mapping_t feature_mappings[] =
|
||||
|
@ -179,8 +178,11 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag)
|
|||
sizeof (feature_mappings[0]),
|
||||
hb_aat_feature_mapping_t::cmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HB_NO_AAT
|
||||
|
||||
/*
|
||||
* mort/morx/kerx/trak
|
||||
*/
|
||||
|
|
|
@ -85,7 +85,7 @@ typedef enum
|
|||
HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE = 39,
|
||||
HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE = 103,
|
||||
|
||||
_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
|
||||
_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_aat_layout_feature_type_t;
|
||||
|
||||
/**
|
||||
|
@ -424,7 +424,7 @@ typedef enum
|
|||
HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN = 2,
|
||||
HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN = 3,
|
||||
|
||||
_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
|
||||
_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_aat_layout_feature_selector_t;
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
|
||||
#include "hb-aat-map.hh"
|
||||
|
||||
|
|
|
@ -50,31 +50,31 @@
|
|||
struct
|
||||
{
|
||||
/* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )
|
||||
}
|
||||
HB_FUNCOBJ (hb_identity);
|
||||
struct
|
||||
{
|
||||
/* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */
|
||||
template <typename T> T&
|
||||
template <typename T> constexpr T&
|
||||
operator () (T& v) const { return v; }
|
||||
|
||||
template <typename T> hb_remove_reference<T>
|
||||
template <typename T> constexpr hb_remove_reference<T>
|
||||
operator () (T&& v) const { return v; }
|
||||
}
|
||||
HB_FUNCOBJ (hb_lidentity);
|
||||
struct
|
||||
{
|
||||
/* Like identity(), but always returns rvalue. */
|
||||
template <typename T> hb_remove_reference<T>
|
||||
template <typename T> constexpr hb_remove_reference<T>
|
||||
operator () (T&& v) const { return v; }
|
||||
}
|
||||
HB_FUNCOBJ (hb_ridentity);
|
||||
|
||||
struct
|
||||
{
|
||||
template <typename T> bool
|
||||
template <typename T> constexpr bool
|
||||
operator () (T&& v) const { return bool (hb_forward<T> (v)); }
|
||||
}
|
||||
HB_FUNCOBJ (hb_bool);
|
||||
|
@ -82,11 +82,11 @@ HB_FUNCOBJ (hb_bool);
|
|||
struct
|
||||
{
|
||||
private:
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
|
||||
|
||||
template <typename T,
|
||||
hb_enable_if (hb_is_integral (T))> auto
|
||||
hb_enable_if (hb_is_integral (T))> constexpr auto
|
||||
impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
|
||||
(
|
||||
/* Knuth's multiplicative method: */
|
||||
|
@ -95,7 +95,7 @@ struct
|
|||
|
||||
public:
|
||||
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))
|
||||
}
|
||||
HB_FUNCOBJ (hb_hash);
|
||||
|
@ -328,14 +328,14 @@ hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
|
|||
|
||||
struct
|
||||
{
|
||||
template <typename Pair> typename Pair::first_t
|
||||
template <typename Pair> constexpr typename Pair::first_t
|
||||
operator () (const Pair& pair) const { return pair.first; }
|
||||
}
|
||||
HB_FUNCOBJ (hb_first);
|
||||
|
||||
struct
|
||||
{
|
||||
template <typename Pair> typename Pair::second_t
|
||||
template <typename Pair> constexpr typename Pair::second_t
|
||||
operator () (const Pair& pair) const { return pair.second; }
|
||||
}
|
||||
HB_FUNCOBJ (hb_second);
|
||||
|
@ -346,14 +346,14 @@ HB_FUNCOBJ (hb_second);
|
|||
* comparing integers of different signedness. */
|
||||
struct
|
||||
{
|
||||
template <typename T, typename T2> auto
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
|
||||
(hb_forward<T> (a) <= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
|
||||
}
|
||||
HB_FUNCOBJ (hb_min);
|
||||
struct
|
||||
{
|
||||
template <typename T, typename T2> auto
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
|
||||
(hb_forward<T> (a) >= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
|
||||
}
|
||||
|
@ -917,7 +917,7 @@ struct hb_bitwise_and
|
|||
{ HB_PARTIALIZE(2);
|
||||
static constexpr bool passthru_left = false;
|
||||
static constexpr bool passthru_right = false;
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_and);
|
||||
|
@ -925,7 +925,7 @@ struct hb_bitwise_or
|
|||
{ HB_PARTIALIZE(2);
|
||||
static constexpr bool passthru_left = true;
|
||||
static constexpr bool passthru_right = true;
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_or);
|
||||
|
@ -933,7 +933,7 @@ struct hb_bitwise_xor
|
|||
{ HB_PARTIALIZE(2);
|
||||
static constexpr bool passthru_left = true;
|
||||
static constexpr bool passthru_right = true;
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_xor);
|
||||
|
@ -941,56 +941,56 @@ struct hb_bitwise_sub
|
|||
{ HB_PARTIALIZE(2);
|
||||
static constexpr bool passthru_left = true;
|
||||
static constexpr bool passthru_right = false;
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_sub);
|
||||
struct
|
||||
{
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a) const HB_AUTO_RETURN (~a)
|
||||
}
|
||||
HB_FUNCOBJ (hb_bitwise_neg);
|
||||
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T, typename T2> auto
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_add);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T, typename T2> auto
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_sub);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T, typename T2> auto
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_mul);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T, typename T2> auto
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_div);
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename T, typename T2> auto
|
||||
template <typename T, typename T2> constexpr auto
|
||||
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)
|
||||
}
|
||||
HB_FUNCOBJ (hb_mod);
|
||||
struct
|
||||
{
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a) const HB_AUTO_RETURN (+a)
|
||||
}
|
||||
HB_FUNCOBJ (hb_pos);
|
||||
struct
|
||||
{
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (const T &a) const HB_AUTO_RETURN (-a)
|
||||
}
|
||||
HB_FUNCOBJ (hb_neg);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define HB_BIMAP_HH
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-map.hh"
|
||||
|
||||
/* Bi-directional map */
|
||||
struct hb_bimap_t
|
||||
|
@ -57,6 +58,8 @@ struct hb_bimap_t
|
|||
|
||||
void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
|
||||
{
|
||||
if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return;
|
||||
if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
|
||||
forw_map.set (lhs, rhs);
|
||||
back_map.set (rhs, lhs);
|
||||
}
|
||||
|
@ -131,6 +134,7 @@ struct hb_inc_bimap_t : hb_bimap_t
|
|||
|
||||
work.qsort (cmp_id);
|
||||
|
||||
clear ();
|
||||
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
|
||||
set (work[rhs], rhs);
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ struct number_t
|
|||
void set_fixed (int32_t v) { value = v / 65536.0; }
|
||||
int32_t to_fixed () const { return (int32_t) (value * 65536.0); }
|
||||
|
||||
void set_real (double v) { value = v; }
|
||||
void set_real (double v) { value = v; }
|
||||
double to_real () const { return value; }
|
||||
|
||||
int ceil () const { return (int) ::ceil (value); }
|
||||
|
@ -235,17 +235,10 @@ struct number_t
|
|||
bool in_int_range () const
|
||||
{ return ((double) (int16_t) to_int () == value); }
|
||||
|
||||
bool operator > (const number_t &n) const
|
||||
{ return value > n.to_real (); }
|
||||
|
||||
bool operator < (const number_t &n) const
|
||||
{ return n > *this; }
|
||||
|
||||
bool operator >= (const number_t &n) const
|
||||
{ return !(*this < n); }
|
||||
|
||||
bool operator <= (const number_t &n) const
|
||||
{ return !(*this > n); }
|
||||
bool operator > (const number_t &n) const { return value > n.to_real (); }
|
||||
bool operator < (const number_t &n) const { return n > *this; }
|
||||
bool operator >= (const number_t &n) const { return !(*this < n); }
|
||||
bool operator <= (const number_t &n) const { return !(*this > n); }
|
||||
|
||||
const number_t &operator += (const number_t &n)
|
||||
{
|
||||
|
@ -255,7 +248,7 @@ struct number_t
|
|||
}
|
||||
|
||||
protected:
|
||||
double value;
|
||||
double value;
|
||||
};
|
||||
|
||||
/* byte string */
|
||||
|
@ -320,8 +313,7 @@ struct byte_str_t : hb_ubytes_t
|
|||
/* A byte string associated with the current offset and an error condition */
|
||||
struct byte_str_ref_t
|
||||
{
|
||||
byte_str_ref_t ()
|
||||
{ init (); }
|
||||
byte_str_ref_t () { init (); }
|
||||
|
||||
void init ()
|
||||
{
|
||||
|
@ -343,13 +335,12 @@ struct byte_str_ref_t
|
|||
}
|
||||
|
||||
const unsigned char& operator [] (int i) {
|
||||
if (unlikely ((unsigned int)(offset + i) >= str.length))
|
||||
if (unlikely ((unsigned int) (offset + i) >= str.length))
|
||||
{
|
||||
set_error ();
|
||||
return Null(unsigned char);
|
||||
return Null (unsigned char);
|
||||
}
|
||||
else
|
||||
return str[offset + i];
|
||||
return str[offset + i];
|
||||
}
|
||||
|
||||
/* Conversion to byte_str_t */
|
||||
|
@ -359,9 +350,7 @@ struct byte_str_ref_t
|
|||
{ return str.sub_str (offset_, len_); }
|
||||
|
||||
bool avail (unsigned int count=1) const
|
||||
{
|
||||
return (!in_error () && str.check_limit (offset, count));
|
||||
}
|
||||
{ return (!in_error () && str.check_limit (offset, count)); }
|
||||
void inc (unsigned int count=1)
|
||||
{
|
||||
if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
|
||||
|
@ -389,7 +378,7 @@ typedef hb_vector_t<byte_str_t> byte_str_array_t;
|
|||
|
||||
/* stack */
|
||||
template <typename ELEM, int LIMIT>
|
||||
struct stack_t
|
||||
struct cff_stack_t
|
||||
{
|
||||
void init ()
|
||||
{
|
||||
|
@ -400,11 +389,7 @@ struct stack_t
|
|||
for (unsigned int i = 0; i < elements.length; i++)
|
||||
elements[i].init ();
|
||||
}
|
||||
|
||||
void fini ()
|
||||
{
|
||||
elements.fini_deep ();
|
||||
}
|
||||
void fini () { elements.fini_deep (); }
|
||||
|
||||
ELEM& operator [] (unsigned int i)
|
||||
{
|
||||
|
@ -419,7 +404,6 @@ struct stack_t
|
|||
else
|
||||
set_error ();
|
||||
}
|
||||
|
||||
ELEM &push ()
|
||||
{
|
||||
if (likely (count < elements.length))
|
||||
|
@ -441,7 +425,6 @@ struct stack_t
|
|||
return Crap(ELEM);
|
||||
}
|
||||
}
|
||||
|
||||
void pop (unsigned int n)
|
||||
{
|
||||
if (likely (count >= n))
|
||||
|
@ -452,13 +435,12 @@ struct stack_t
|
|||
|
||||
const ELEM& peek ()
|
||||
{
|
||||
if (likely (count > 0))
|
||||
return elements[count-1];
|
||||
else
|
||||
if (unlikely (count < 0))
|
||||
{
|
||||
set_error ();
|
||||
return Null(ELEM);
|
||||
}
|
||||
return elements[count - 1];
|
||||
}
|
||||
|
||||
void unpop ()
|
||||
|
@ -475,7 +457,7 @@ struct stack_t
|
|||
void set_error () { error = true; }
|
||||
|
||||
unsigned int get_count () const { return count; }
|
||||
bool is_empty () const { return count == 0; }
|
||||
bool is_empty () const { return !count; }
|
||||
|
||||
static constexpr unsigned kSizeLimit = LIMIT;
|
||||
|
||||
|
@ -487,7 +469,7 @@ struct stack_t
|
|||
|
||||
/* argument stack */
|
||||
template <typename ARG=number_t>
|
||||
struct arg_stack_t : stack_t<ARG, 513>
|
||||
struct arg_stack_t : cff_stack_t<ARG, 513>
|
||||
{
|
||||
void push_int (int v)
|
||||
{
|
||||
|
@ -519,7 +501,7 @@ struct arg_stack_t : stack_t<ARG, 513>
|
|||
i = 0;
|
||||
S::set_error ();
|
||||
}
|
||||
return (unsigned)i;
|
||||
return (unsigned) i;
|
||||
}
|
||||
|
||||
void push_longint_from_substr (byte_str_ref_t& str_ref)
|
||||
|
@ -538,12 +520,10 @@ struct arg_stack_t : stack_t<ARG, 513>
|
|||
}
|
||||
|
||||
hb_array_t<const ARG> get_subarray (unsigned int start) const
|
||||
{
|
||||
return S::elements.sub_array (start);
|
||||
}
|
||||
{ return S::elements.sub_array (start); }
|
||||
|
||||
private:
|
||||
typedef stack_t<ARG, 513> S;
|
||||
typedef cff_stack_t<ARG, 513> S;
|
||||
};
|
||||
|
||||
/* an operator prefixed by its operands in a byte string */
|
||||
|
@ -605,7 +585,7 @@ struct parsed_values_t
|
|||
}
|
||||
|
||||
unsigned get_count () const { return values.length; }
|
||||
const VAL &get_value (unsigned int i) const { return values[i]; }
|
||||
const VAL &get_value (unsigned int i) const { return values[i]; }
|
||||
const VAL &operator [] (unsigned int i) const { return get_value (i); }
|
||||
|
||||
unsigned int opStart;
|
||||
|
@ -644,30 +624,19 @@ struct interp_env_t
|
|||
return op;
|
||||
}
|
||||
|
||||
const ARG& eval_arg (unsigned int i)
|
||||
{
|
||||
return argStack[i];
|
||||
}
|
||||
const ARG& eval_arg (unsigned int i) { return argStack[i]; }
|
||||
|
||||
ARG& pop_arg ()
|
||||
{
|
||||
return argStack.pop ();
|
||||
}
|
||||
ARG& pop_arg () { return argStack.pop (); }
|
||||
void pop_n_args (unsigned int n) { argStack.pop (n); }
|
||||
|
||||
void pop_n_args (unsigned int n)
|
||||
{
|
||||
argStack.pop (n);
|
||||
}
|
||||
void clear_args () { pop_n_args (argStack.get_count ()); }
|
||||
|
||||
void clear_args ()
|
||||
{
|
||||
pop_n_args (argStack.get_count ());
|
||||
}
|
||||
|
||||
byte_str_ref_t str_ref;
|
||||
arg_stack_t<ARG> argStack;
|
||||
byte_str_ref_t
|
||||
str_ref;
|
||||
arg_stack_t<ARG>
|
||||
argStack;
|
||||
protected:
|
||||
bool error;
|
||||
bool error;
|
||||
};
|
||||
|
||||
typedef interp_env_t<> num_interp_env_t;
|
||||
|
@ -711,8 +680,8 @@ struct opset_t
|
|||
};
|
||||
|
||||
template <typename ENV>
|
||||
struct interpreter_t {
|
||||
|
||||
struct interpreter_t
|
||||
{
|
||||
~interpreter_t() { fini (); }
|
||||
|
||||
void fini () { env.fini (); }
|
||||
|
|
|
@ -57,14 +57,14 @@ struct call_context_t
|
|||
|
||||
/* call stack */
|
||||
const unsigned int kMaxCallLimit = 10;
|
||||
struct call_stack_t : stack_t<call_context_t, kMaxCallLimit> {};
|
||||
struct call_stack_t : cff_stack_t<call_context_t, kMaxCallLimit> {};
|
||||
|
||||
template <typename SUBRS>
|
||||
struct biased_subrs_t
|
||||
{
|
||||
void init (const SUBRS &subrs_)
|
||||
void init (const SUBRS *subrs_)
|
||||
{
|
||||
subrs = &subrs_;
|
||||
subrs = subrs_;
|
||||
unsigned int nSubrs = get_count ();
|
||||
if (nSubrs < 1240)
|
||||
bias = 107;
|
||||
|
@ -118,7 +118,7 @@ struct point_t
|
|||
template <typename ARG, typename SUBRS>
|
||||
struct cs_interp_env_t : interp_env_t<ARG>
|
||||
{
|
||||
void init (const byte_str_t &str, const SUBRS &globalSubrs_, const SUBRS &localSubrs_)
|
||||
void init (const byte_str_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_)
|
||||
{
|
||||
interp_env_t<ARG>::init (str);
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
|
|||
template <typename ACC>
|
||||
void init (const byte_str_t &str, ACC &acc, unsigned int fd)
|
||||
{
|
||||
SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
||||
SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
|
||||
processed_width = false;
|
||||
has_width = false;
|
||||
arg_start = 0;
|
||||
|
|
|
@ -82,7 +82,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
|
|||
void init (const byte_str_t &str, ACC &acc, unsigned int fd,
|
||||
const int *coords_=nullptr, unsigned int num_coords_=0)
|
||||
{
|
||||
SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
||||
SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
|
||||
|
||||
coords = coords_;
|
||||
num_coords = num_coords_;
|
||||
|
|
|
@ -66,6 +66,8 @@
|
|||
#define HB_NO_LAYOUT_COLLECT_GLYPHS
|
||||
#define HB_NO_LAYOUT_UNUSED
|
||||
#define HB_NO_MATH
|
||||
#define HB_NO_META
|
||||
#define HB_NO_METRICS
|
||||
#define HB_NO_MMAP
|
||||
#define HB_NO_NAME
|
||||
#define HB_NO_OPEN
|
||||
|
@ -93,7 +95,7 @@
|
|||
|
||||
#ifdef HB_NO_AAT
|
||||
#define HB_NO_OT_NAME_LANGUAGE_AAT
|
||||
#define HB_NO_SHAPE_AAT
|
||||
#define HB_NO_AAT_SHAPE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_BITMAP
|
||||
|
@ -121,6 +123,17 @@
|
|||
#define HB_NO_OT_NAME_LANGUAGE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_OT
|
||||
#define HB_NO_OT_FONT
|
||||
#define HB_NO_OT_LAYOUT
|
||||
#define HB_NO_OT_TAG
|
||||
#define HB_NO_OT_SHAPE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_OT_SHAPE
|
||||
#define HB_NO_AAT_SHAPE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_OT_SHAPE_FALLBACK
|
||||
#define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
|
||||
#define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
|
||||
|
|
|
@ -75,7 +75,7 @@ release_table_data (void *user_data)
|
|||
}
|
||||
|
||||
static hb_blob_t *
|
||||
reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
_hb_cg_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
|
||||
CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
|
||||
|
@ -299,7 +299,7 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
|
|||
hb_face_t *
|
||||
hb_coretext_face_create (CGFontRef cg_font)
|
||||
{
|
||||
return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
|
||||
return hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -28,11 +28,18 @@
|
|||
|
||||
#include "hb-shaper-impl.hh"
|
||||
|
||||
#include <DWrite_1.h>
|
||||
#include <dwrite_1.h>
|
||||
|
||||
#include "hb-directwrite.h"
|
||||
|
||||
|
||||
/* Declare object creator for dynamic support of DWRITE */
|
||||
typedef HRESULT (* WINAPI t_DWriteCreateFactory)(
|
||||
DWRITE_FACTORY_TYPE factoryType,
|
||||
REFIID iid,
|
||||
IUnknown **factory
|
||||
);
|
||||
|
||||
/*
|
||||
* hb-directwrite uses new/delete syntatically but as we let users
|
||||
* to override malloc/free, we will redefine new/delete so users
|
||||
|
@ -138,6 +145,7 @@ public:
|
|||
|
||||
struct hb_directwrite_face_data_t
|
||||
{
|
||||
HMODULE dwrite_dll;
|
||||
IDWriteFactory *dwriteFactory;
|
||||
IDWriteFontFile *fontFile;
|
||||
DWriteFontFileStream *fontFileStream;
|
||||
|
@ -153,12 +161,43 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
|
|||
if (unlikely (!data))
|
||||
return nullptr;
|
||||
|
||||
// TODO: factory and fontFileLoader should be cached separately
|
||||
IDWriteFactory* dwriteFactory;
|
||||
DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
|
||||
(IUnknown**) &dwriteFactory);
|
||||
#define FAIL(...) \
|
||||
HB_STMT_START { \
|
||||
DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
|
||||
return nullptr; \
|
||||
} HB_STMT_END
|
||||
|
||||
data->dwrite_dll = LoadLibrary (TEXT ("DWRITE"));
|
||||
if (unlikely (!data->dwrite_dll))
|
||||
FAIL ("Cannot find DWrite.DLL");
|
||||
|
||||
t_DWriteCreateFactory p_DWriteCreateFactory;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
#endif
|
||||
|
||||
p_DWriteCreateFactory = (t_DWriteCreateFactory)
|
||||
GetProcAddress (data->dwrite_dll, "DWriteCreateFactory");
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
if (unlikely (!p_DWriteCreateFactory))
|
||||
FAIL ("Cannot find DWriteCreateFactory().");
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
// TODO: factory and fontFileLoader should be cached separately
|
||||
IDWriteFactory* dwriteFactory;
|
||||
hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
|
||||
(IUnknown**) &dwriteFactory);
|
||||
|
||||
if (unlikely (hr != S_OK))
|
||||
FAIL ("Failed to run DWriteCreateFactory().");
|
||||
|
||||
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||
DWriteFontFileStream *fontFileStream;
|
||||
fontFileStream = new DWriteFontFileStream ((uint8_t *) hb_blob_get_data (blob, nullptr),
|
||||
|
@ -172,12 +211,6 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
|
|||
hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey),
|
||||
fontFileLoader, &fontFile);
|
||||
|
||||
#define FAIL(...) \
|
||||
HB_STMT_START { \
|
||||
DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
|
||||
return nullptr; \
|
||||
} HB_STMT_END
|
||||
|
||||
if (FAILED (hr))
|
||||
FAIL ("Failed to load font file from data!");
|
||||
|
||||
|
@ -224,6 +257,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
|
|||
delete data->fontFileStream;
|
||||
if (data->faceBlob)
|
||||
hb_blob_destroy (data->faceBlob);
|
||||
if (data->dwrite_dll)
|
||||
FreeLibrary (data->dwrite_dll);
|
||||
if (data)
|
||||
delete data;
|
||||
}
|
||||
|
@ -504,11 +539,6 @@ protected:
|
|||
Run mRunHead;
|
||||
};
|
||||
|
||||
static inline uint16_t hb_uint16_swap (const uint16_t v)
|
||||
{ return (v >> 8) | (v << 8); }
|
||||
static inline uint32_t hb_uint32_swap (const uint32_t v)
|
||||
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
|
||||
|
||||
/*
|
||||
* shaper
|
||||
*/
|
||||
|
@ -899,7 +929,7 @@ _hb_directwrite_table_data_release (void *data)
|
|||
}
|
||||
|
||||
static hb_blob_t *
|
||||
reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
_hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
IDWriteFontFace *dw_face = ((IDWriteFontFace *) user_data);
|
||||
const void *data;
|
||||
|
@ -944,7 +974,7 @@ hb_directwrite_face_create (IDWriteFontFace *font_face)
|
|||
{
|
||||
if (font_face)
|
||||
font_face->AddRef ();
|
||||
return hb_face_create_for_tables (reference_table, font_face,
|
||||
return hb_face_create_for_tables (_hb_directwrite_reference_table, font_face,
|
||||
_hb_directwrite_font_release);
|
||||
}
|
||||
|
||||
|
|
|
@ -1300,6 +1300,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
|
|||
|
||||
1000, /* x_scale */
|
||||
1000, /* y_scale */
|
||||
1<<16, /* x_mult */
|
||||
1<<16, /* y_mult */
|
||||
|
||||
0, /* x_ppem */
|
||||
0, /* y_ppem */
|
||||
|
@ -1330,6 +1332,7 @@ _hb_font_create (hb_face_t *face)
|
|||
font->klass = hb_font_funcs_get_empty ();
|
||||
font->data.init0 (font);
|
||||
font->x_scale = font->y_scale = hb_face_get_upem (face);
|
||||
font->x_mult = font->y_mult = 1 << 16;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -1601,7 +1604,9 @@ hb_font_set_face (hb_font_t *font,
|
|||
|
||||
hb_face_t *old = font->face;
|
||||
|
||||
hb_face_make_immutable (face);
|
||||
font->face = hb_face_reference (face);
|
||||
font->mults_changed ();
|
||||
|
||||
hb_face_destroy (old);
|
||||
}
|
||||
|
@ -1711,6 +1716,7 @@ hb_font_set_scale (hb_font_t *font,
|
|||
|
||||
font->x_scale = x_scale;
|
||||
font->y_scale = y_scale;
|
||||
font->mults_changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1855,6 +1861,7 @@ hb_font_set_variations (hb_font_t *font,
|
|||
normalized, coords_length);
|
||||
_hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_var_coords_design:
|
||||
*
|
||||
|
@ -1875,6 +1882,33 @@ hb_font_set_var_coords_design (hb_font_t *font,
|
|||
hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
|
||||
_hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_var_named_instance:
|
||||
* @font: a font.
|
||||
* @instance_index: named instance index.
|
||||
*
|
||||
* Sets design coords of a font from a named instance index.
|
||||
*
|
||||
* Since: 2.6.0
|
||||
*/
|
||||
void
|
||||
hb_font_set_var_named_instance (hb_font_t *font,
|
||||
unsigned instance_index)
|
||||
{
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
|
||||
|
||||
float *coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
|
||||
if (unlikely (coords_length && !coords))
|
||||
return;
|
||||
|
||||
hb_ot_var_named_instance_get_design_coords (font->face, instance_index, &coords_length, coords);
|
||||
hb_font_set_var_coords_design (font, coords, coords_length);
|
||||
free (coords);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -705,6 +705,10 @@ HB_EXTERN const int *
|
|||
hb_font_get_var_coords_normalized (hb_font_t *font,
|
||||
unsigned int *length);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_var_named_instance (hb_font_t *font,
|
||||
unsigned instance_index);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_FONT_H */
|
||||
|
|
|
@ -107,8 +107,10 @@ struct hb_font_t
|
|||
hb_font_t *parent;
|
||||
hb_face_t *face;
|
||||
|
||||
int x_scale;
|
||||
int y_scale;
|
||||
int32_t x_scale;
|
||||
int32_t y_scale;
|
||||
int64_t x_mult;
|
||||
int64_t y_mult;
|
||||
|
||||
unsigned int x_ppem;
|
||||
unsigned int y_ppem;
|
||||
|
@ -127,16 +129,16 @@ struct hb_font_t
|
|||
|
||||
|
||||
/* Convert from font-space to user-space */
|
||||
int dir_scale (hb_direction_t direction)
|
||||
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
|
||||
hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
|
||||
hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
|
||||
hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
|
||||
hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
|
||||
int64_t dir_mult (hb_direction_t direction)
|
||||
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
|
||||
hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
|
||||
hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
|
||||
hb_position_t em_scalef_x (float v) { return em_scalef (v, x_scale); }
|
||||
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); }
|
||||
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
|
||||
{ return em_scale (v, dir_scale (direction)); }
|
||||
{ return em_mult (v, dir_mult (direction)); }
|
||||
|
||||
/* Convert from parent-font user-space to our user-space */
|
||||
hb_position_t parent_scale_x_distance (hb_position_t v)
|
||||
|
@ -607,12 +609,16 @@ struct hb_font_t
|
|||
return false;
|
||||
}
|
||||
|
||||
hb_position_t em_scale (int16_t v, int scale)
|
||||
void mults_changed ()
|
||||
{
|
||||
int upem = face->get_upem ();
|
||||
int64_t scaled = v * (int64_t) scale;
|
||||
scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
|
||||
return (hb_position_t) (scaled / upem);
|
||||
signed upem = face->get_upem ();
|
||||
x_mult = ((int64_t) x_scale << 16) / upem;
|
||||
y_mult = ((int64_t) y_scale << 16) / upem;
|
||||
}
|
||||
|
||||
hb_position_t em_mult (int16_t v, int64_t mult)
|
||||
{
|
||||
return (hb_position_t) ((v * mult) >> 16);
|
||||
}
|
||||
hb_position_t em_scalef (float v, int scale)
|
||||
{ return (hb_position_t) roundf (v * scale / face->get_upem ()); }
|
||||
|
|
|
@ -564,7 +564,7 @@ _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
|
|||
|
||||
|
||||
static hb_blob_t *
|
||||
reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
_hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
FT_Face ft_face = (FT_Face) user_data;
|
||||
FT_Byte *buffer;
|
||||
|
@ -619,7 +619,7 @@ hb_ft_face_create (FT_Face ft_face,
|
|||
face = hb_face_create (blob, ft_face->face_index);
|
||||
hb_blob_destroy (blob);
|
||||
} else {
|
||||
face = hb_face_create_for_tables (reference_table, ft_face, destroy);
|
||||
face = hb_face_create_for_tables (_hb_ft_reference_table, ft_face, destroy);
|
||||
}
|
||||
|
||||
hb_face_set_index (face, ft_face->face_index);
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright © 2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifdef HAVE_GDI
|
||||
|
||||
#include "hb-gdi.h"
|
||||
|
||||
static hb_blob_t *
|
||||
_hb_gdi_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
char *buffer = nullptr;
|
||||
DWORD length = 0;
|
||||
|
||||
HDC hdc = GetDC (nullptr);
|
||||
if (unlikely (!SelectObject (hdc, (HFONT) user_data))) goto fail;
|
||||
|
||||
length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
|
||||
if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc;
|
||||
|
||||
buffer = (char *) malloc (length);
|
||||
if (unlikely (!buffer)) goto fail_with_releasedc;
|
||||
length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
|
||||
if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc_and_free;
|
||||
ReleaseDC (nullptr, hdc);
|
||||
|
||||
return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, free);
|
||||
|
||||
fail_with_releasedc_and_free:
|
||||
free (buffer);
|
||||
fail_with_releasedc:
|
||||
ReleaseDC (nullptr, hdc);
|
||||
fail:
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_gdi_face_create:
|
||||
* @hdc: a HFONT object.
|
||||
*
|
||||
* Return value: #hb_face_t object corresponding to the given input
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
hb_face_t *
|
||||
hb_gdi_face_create (HFONT hfont)
|
||||
{
|
||||
return hb_face_create_for_tables (_hb_gdi_reference_table, (void *) hfont, nullptr);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright © 2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef HB_GDI_H
|
||||
#define HB_GDI_H
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_gdi_face_create (HFONT hfont);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_GDI_H */
|
|
@ -106,32 +106,6 @@ retry:
|
|||
return d;
|
||||
}
|
||||
|
||||
static void hb_graphite2_release_table(const void *data, const void *table_buffer)
|
||||
{
|
||||
hb_graphite2_face_data_t *face_data = (hb_graphite2_face_data_t *) data;
|
||||
hb_graphite2_tablelist_t *tlist = face_data->tlist;
|
||||
|
||||
hb_graphite2_tablelist_t *prev = nullptr;
|
||||
hb_graphite2_tablelist_t *curr = tlist;
|
||||
while (curr)
|
||||
{
|
||||
if (hb_blob_get_data(curr->blob, nullptr) == table_buffer)
|
||||
{
|
||||
if (prev == nullptr)
|
||||
face_data->tlist.cmpexch(tlist, curr->next);
|
||||
else
|
||||
prev->next = curr->next;
|
||||
hb_blob_destroy(curr->blob);
|
||||
free(curr);
|
||||
break;
|
||||
}
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
static gr_face_ops hb_graphite2_face_ops = { sizeof(gr_face_ops), hb_graphite2_get_table, hb_graphite2_release_table };
|
||||
|
||||
hb_graphite2_face_data_t *
|
||||
_hb_graphite2_shaper_face_data_create (hb_face_t *face)
|
||||
{
|
||||
|
@ -150,7 +124,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
|
|||
return nullptr;
|
||||
|
||||
data->face = face;
|
||||
data->grface = gr_make_face_with_ops (data, &hb_graphite2_face_ops, gr_face_preloadAll);
|
||||
data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
|
||||
|
||||
if (unlikely (!data->grface)) {
|
||||
free (data);
|
||||
|
|
|
@ -480,7 +480,7 @@ struct hb_reduce_t
|
|||
|
||||
template <typename Iter,
|
||||
hb_requires (hb_is_iterator (Iter)),
|
||||
typename AccuT = decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>
|
||||
typename AccuT = hb_decay<decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>>
|
||||
AccuT
|
||||
operator () (Iter it)
|
||||
{
|
||||
|
|
|
@ -80,8 +80,8 @@ template <typename T> using hb_type_identity = typename hb_type_identity_t<T>::t
|
|||
|
||||
struct
|
||||
{
|
||||
template <typename T>
|
||||
T* operator () (T& arg) const
|
||||
template <typename T> constexpr T*
|
||||
operator () (T& arg) const
|
||||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
@ -171,29 +171,29 @@ using hb_is_cr_convertible = hb_bool_constant<
|
|||
/* std::move and std::forward */
|
||||
|
||||
template <typename T>
|
||||
static hb_remove_reference<T>&& hb_move (T&& t) { return (hb_remove_reference<T>&&) (t); }
|
||||
static constexpr hb_remove_reference<T>&& hb_move (T&& t) { return (hb_remove_reference<T>&&) (t); }
|
||||
|
||||
template <typename T>
|
||||
static T&& hb_forward (hb_remove_reference<T>& t) { return (T&&) t; }
|
||||
static constexpr T&& hb_forward (hb_remove_reference<T>& t) { return (T&&) t; }
|
||||
template <typename T>
|
||||
static T&& hb_forward (hb_remove_reference<T>&& t) { return (T&&) t; }
|
||||
static constexpr T&& hb_forward (hb_remove_reference<T>&& t) { return (T&&) t; }
|
||||
|
||||
struct
|
||||
{
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
|
||||
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (T *v) const HB_AUTO_RETURN (*v)
|
||||
}
|
||||
HB_FUNCOBJ (hb_deref);
|
||||
|
||||
struct
|
||||
{
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
|
||||
|
||||
template <typename T> auto
|
||||
template <typename T> constexpr auto
|
||||
operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v))
|
||||
}
|
||||
HB_FUNCOBJ (hb_ref);
|
||||
|
|
|
@ -141,14 +141,15 @@ typedef struct OffsetTable
|
|||
TableRecord &rec = tables.arrayZ[i];
|
||||
hb_blob_t *blob = items[i].blob;
|
||||
rec.tag = items[i].tag;
|
||||
rec.length = hb_blob_get_length (blob);
|
||||
rec.length = blob->length;
|
||||
rec.offset.serialize (c, this);
|
||||
|
||||
/* Allocate room for the table and copy it. */
|
||||
char *start = (char *) c->allocate_size<void> (rec.length);
|
||||
if (unlikely (!start)) {return false;}
|
||||
if (unlikely (!start)) return false;
|
||||
|
||||
memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
|
||||
if (likely (rec.length))
|
||||
memcpy (start, blob->data, rec.length);
|
||||
|
||||
/* 4-byte alignment. */
|
||||
c->align (4);
|
||||
|
|
|
@ -576,13 +576,13 @@ struct ArrayOf
|
|||
operator writer_t () { return writer (); }
|
||||
|
||||
hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
|
||||
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
|
||||
{
|
||||
|
@ -826,13 +826,13 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
|
|||
operator writer_t () { return writer (); }
|
||||
|
||||
hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
|
||||
{ return as_array ().sub_array (start_offset, count);}
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
|
||||
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
|
||||
{
|
||||
|
|
|
@ -40,14 +40,14 @@ using namespace OT;
|
|||
|
||||
/* utility macro */
|
||||
template<typename Type>
|
||||
static inline const Type& StructAtOffsetOrNull(const void *P, unsigned int offset)
|
||||
{ return offset? (* reinterpret_cast<const Type*> ((const char *) P + offset)): Null(Type); }
|
||||
static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset)
|
||||
{ return offset ? StructAtOffset<Type> (P, offset) : Null (Type); }
|
||||
|
||||
inline unsigned int calcOffSize(unsigned int dataSize)
|
||||
inline unsigned int calcOffSize (unsigned int dataSize)
|
||||
{
|
||||
unsigned int size = 1;
|
||||
unsigned int offset = dataSize + 1;
|
||||
while ((offset & ~0xFF) != 0)
|
||||
while (offset & ~0xFF)
|
||||
{
|
||||
size++;
|
||||
offset >>= 8;
|
||||
|
@ -58,8 +58,8 @@ inline unsigned int calcOffSize(unsigned int dataSize)
|
|||
|
||||
struct code_pair_t
|
||||
{
|
||||
hb_codepoint_t code;
|
||||
hb_codepoint_t glyph;
|
||||
hb_codepoint_t code;
|
||||
hb_codepoint_t glyph;
|
||||
};
|
||||
|
||||
typedef hb_vector_t<unsigned char> str_buff_t;
|
||||
|
@ -92,10 +92,8 @@ struct CFFIndex
|
|||
static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count,
|
||||
unsigned int dataSize)
|
||||
{
|
||||
if (count == 0)
|
||||
return COUNT::static_size;
|
||||
else
|
||||
return min_size + calculate_offset_array_size (offSize_, count) + dataSize;
|
||||
if (count == 0) return COUNT::static_size;
|
||||
return min_size + calculate_offset_array_size (offSize_, count) + dataSize;
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
|
||||
|
@ -159,9 +157,7 @@ struct CFFIndex
|
|||
byteArray.init ();
|
||||
byteArray.resize (buffArray.length);
|
||||
for (unsigned int i = 0; i < byteArray.length; i++)
|
||||
{
|
||||
byteArray[i] = byte_str_t (buffArray[i].arrayZ, buffArray[i].length);
|
||||
}
|
||||
bool result = this->serialize (c, offSize_, byteArray);
|
||||
byteArray.fini ();
|
||||
return result;
|
||||
|
@ -192,43 +188,35 @@ struct CFFIndex
|
|||
|
||||
unsigned int length_at (unsigned int index) const
|
||||
{
|
||||
if (likely ((offset_at (index + 1) >= offset_at (index)) &&
|
||||
(offset_at (index + 1) <= offset_at (count))))
|
||||
return offset_at (index + 1) - offset_at (index);
|
||||
else
|
||||
if (unlikely ((offset_at (index + 1) < offset_at (index)) ||
|
||||
(offset_at (index + 1) > offset_at (count))))
|
||||
return 0;
|
||||
return offset_at (index + 1) - offset_at (index);
|
||||
}
|
||||
|
||||
const unsigned char *data_base () const
|
||||
{ return (const unsigned char *)this + min_size + offset_array_size (); }
|
||||
{ return (const unsigned char *) this + min_size + offset_array_size (); }
|
||||
|
||||
unsigned int data_size () const { return HBINT8::static_size; }
|
||||
|
||||
byte_str_t operator [] (unsigned int index) const
|
||||
{
|
||||
if (likely (index < count))
|
||||
return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
|
||||
else
|
||||
return Null (byte_str_t);
|
||||
if (unlikely (index >= count)) return Null (byte_str_t);
|
||||
return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
|
||||
}
|
||||
|
||||
unsigned int get_size () const
|
||||
{
|
||||
if (this != &Null (CFFIndex))
|
||||
{
|
||||
if (count > 0)
|
||||
return min_size + offset_array_size () + (offset_at (count) - 1);
|
||||
else
|
||||
return count.static_size; /* empty CFFIndex contains count only */
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
if (this == &Null (CFFIndex)) return 0;
|
||||
if (count > 0)
|
||||
return min_size + offset_array_size () + (offset_at (count) - 1);
|
||||
return count.static_size; /* empty CFFIndex contains count only */
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
|
||||
return_trace (likely ((c->check_struct (this) && count == 0) || /* empty INDEX */
|
||||
(c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
|
||||
c->check_array (offsets, offSize, count + 1) &&
|
||||
c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1))));
|
||||
|
|
|
@ -210,7 +210,7 @@ struct bounds_t
|
|||
point_t max;
|
||||
};
|
||||
|
||||
struct extents_param_t
|
||||
struct cff1_extents_param_t
|
||||
{
|
||||
void init (const OT::cff1::accelerator_t *_cff)
|
||||
{
|
||||
|
@ -229,15 +229,15 @@ struct extents_param_t
|
|||
const OT::cff1::accelerator_t *cff;
|
||||
};
|
||||
|
||||
struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, extents_param_t>
|
||||
struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, cff1_extents_param_t>
|
||||
{
|
||||
static void moveto (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
|
||||
static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt)
|
||||
{
|
||||
param.end_path ();
|
||||
env.moveto (pt);
|
||||
}
|
||||
|
||||
static void line (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
|
||||
static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
|
@ -248,7 +248,7 @@ struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_
|
|||
param.bounds.update (env.get_pt ());
|
||||
}
|
||||
|
||||
static void curve (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
|
||||
static void curve (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
|
@ -265,9 +265,9 @@ struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_
|
|||
|
||||
static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
|
||||
|
||||
struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, extents_param_t, cff1_path_procs_extents_t>
|
||||
struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, cff1_extents_param_t, cff1_path_procs_extents_t>
|
||||
{
|
||||
static void process_seac (cff1_cs_interp_env_t &env, extents_param_t& param)
|
||||
static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param)
|
||||
{
|
||||
unsigned int n = env.argStack.get_count ();
|
||||
point_t delta;
|
||||
|
@ -296,11 +296,11 @@ bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, boun
|
|||
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
|
||||
|
||||
unsigned int fd = cff->fdSelect->get_fd (glyph);
|
||||
cff1_cs_interpreter_t<cff1_cs_opset_extents_t, extents_param_t> interp;
|
||||
cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp;
|
||||
const byte_str_t str = (*cff->charStrings)[glyph];
|
||||
interp.env.init (str, *cff, fd);
|
||||
interp.env.set_in_seac (in_seac);
|
||||
extents_param_t param;
|
||||
cff1_extents_param_t param;
|
||||
param.init (cff);
|
||||
if (unlikely (!interp.interpret (param))) return false;
|
||||
bounds = param.bounds;
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
using namespace CFF;
|
||||
|
||||
struct extents_param_t
|
||||
struct cff2_extents_param_t
|
||||
{
|
||||
void init ()
|
||||
{
|
||||
|
@ -63,15 +63,15 @@ struct extents_param_t
|
|||
number_t max_y;
|
||||
};
|
||||
|
||||
struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, extents_param_t>
|
||||
struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, cff2_extents_param_t>
|
||||
{
|
||||
static void moveto (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
|
||||
static void moveto (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt)
|
||||
{
|
||||
param.end_path ();
|
||||
env.moveto (pt);
|
||||
}
|
||||
|
||||
static void line (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
|
||||
static void line (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
|
|||
param.update_bounds (env.get_pt ());
|
||||
}
|
||||
|
||||
static void curve (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
|
||||
static void curve (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
|
@ -97,7 +97,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
|
|||
}
|
||||
};
|
||||
|
||||
struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, extents_param_t, cff2_path_procs_extents_t> {};
|
||||
struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_extents_param_t, cff2_path_procs_extents_t> {};
|
||||
|
||||
bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
|
@ -113,10 +113,10 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
|
|||
unsigned int num_coords;
|
||||
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
|
||||
unsigned int fd = fdSelect->get_fd (glyph);
|
||||
cff2_cs_interpreter_t<cff2_cs_opset_extents_t, extents_param_t> interp;
|
||||
cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t> interp;
|
||||
const byte_str_t str = (*charStrings)[glyph];
|
||||
interp.env.init (str, *this, fd, coords, num_coords);
|
||||
extents_param_t param;
|
||||
cff2_extents_param_t param;
|
||||
param.init ();
|
||||
if (unlikely (!interp.interpret (param))) return false;
|
||||
|
||||
|
|
|
@ -74,153 +74,201 @@ struct CmapSubtableFormat0
|
|||
|
||||
struct CmapSubtableFormat4
|
||||
{
|
||||
struct segment_plan
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
HBUINT16* serialize_endcode_array (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{
|
||||
HBUINT16 start_code;
|
||||
HBUINT16 end_code;
|
||||
bool use_delta;
|
||||
};
|
||||
HBUINT16 *endCode = c->start_embed<HBUINT16> ();
|
||||
hb_codepoint_t prev_endcp = 0xFFFF;
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const hb_subset_plan_t *plan,
|
||||
const hb_sorted_vector_t<segment_plan> &segments)
|
||||
+ it
|
||||
| hb_apply ([&] (const hb_item_type<Iterator> _)
|
||||
{
|
||||
if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
|
||||
{
|
||||
HBUINT16 end_code;
|
||||
end_code = prev_endcp;
|
||||
c->copy<HBUINT16> (end_code);
|
||||
}
|
||||
prev_endcp = _.first;
|
||||
})
|
||||
;
|
||||
|
||||
{
|
||||
// last endCode
|
||||
HBUINT16 endcode;
|
||||
endcode = prev_endcp;
|
||||
if (unlikely (!c->copy<HBUINT16> (endcode))) return nullptr;
|
||||
// There must be a final entry with end_code == 0xFFFF.
|
||||
if (prev_endcp != 0xFFFF)
|
||||
{
|
||||
HBUINT16 finalcode;
|
||||
finalcode = 0xFFFF;
|
||||
if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return endCode;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
HBUINT16* serialize_startcode_array (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
HBUINT16 *startCode = c->start_embed<HBUINT16> ();
|
||||
hb_codepoint_t prev_cp = 0xFFFF;
|
||||
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
+ it
|
||||
| hb_apply ([&] (const hb_item_type<Iterator> _)
|
||||
{
|
||||
if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
|
||||
{
|
||||
HBUINT16 start_code;
|
||||
start_code = _.first;
|
||||
c->copy<HBUINT16> (start_code);
|
||||
}
|
||||
|
||||
prev_cp = _.first;
|
||||
})
|
||||
;
|
||||
|
||||
// There must be a final entry with end_code == 0xFFFF.
|
||||
if (it.len () == 0 || prev_cp != 0xFFFF)
|
||||
{
|
||||
HBUINT16 finalcode;
|
||||
finalcode = 0xFFFF;
|
||||
if (unlikely (!c->copy<HBUINT16> (finalcode))) return nullptr;
|
||||
}
|
||||
|
||||
return startCode;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
HBINT16* serialize_idDelta_array (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
HBUINT16 *endCode,
|
||||
HBUINT16 *startCode,
|
||||
unsigned segcount)
|
||||
{
|
||||
unsigned i = 0;
|
||||
hb_codepoint_t last_gid = 0, start_gid = 0, last_cp = 0xFFFF;
|
||||
bool use_delta = true;
|
||||
|
||||
HBINT16 *idDelta = c->start_embed<HBINT16> ();
|
||||
if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size)
|
||||
return nullptr;
|
||||
|
||||
+ it
|
||||
| hb_apply ([&] (const hb_item_type<Iterator> _)
|
||||
{
|
||||
if (_.first == startCode[i])
|
||||
{
|
||||
use_delta = true;
|
||||
start_gid = _.second;
|
||||
}
|
||||
else if (_.second != last_gid + 1) use_delta = false;
|
||||
|
||||
if (_.first == endCode[i])
|
||||
{
|
||||
HBINT16 delta;
|
||||
if (use_delta) delta = (int)start_gid - (int)startCode[i];
|
||||
else delta = 0;
|
||||
c->copy<HBINT16> (delta);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
last_gid = _.second;
|
||||
last_cp = _.first;
|
||||
})
|
||||
;
|
||||
|
||||
if (it.len () == 0 || last_cp != 0xFFFF)
|
||||
{
|
||||
HBINT16 delta;
|
||||
delta = 1;
|
||||
if (unlikely (!c->copy<HBINT16> (delta))) return nullptr;
|
||||
}
|
||||
|
||||
return idDelta;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
HBUINT16* serialize_rangeoffset_glyid (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
HBUINT16 *endCode,
|
||||
HBUINT16 *startCode,
|
||||
HBINT16 *idDelta,
|
||||
unsigned segcount)
|
||||
{
|
||||
HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
|
||||
if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
|
||||
if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
|
||||
|
||||
+ hb_range (segcount)
|
||||
| hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; })
|
||||
| hb_apply ([&] (const unsigned i)
|
||||
{
|
||||
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
|
||||
|
||||
+ it
|
||||
| hb_filter ([&] (const hb_item_type<Iterator> _) { return _.first >= startCode[i] && _.first <= endCode[i]; })
|
||||
| hb_apply ([&] (const hb_item_type<Iterator> _)
|
||||
{
|
||||
HBUINT16 glyID;
|
||||
glyID = _.second;
|
||||
c->copy<HBUINT16> (glyID);
|
||||
})
|
||||
;
|
||||
|
||||
|
||||
})
|
||||
;
|
||||
|
||||
return idRangeOffset;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{
|
||||
unsigned table_initpos = c->length ();
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
this->format = 4;
|
||||
this->length = get_sub_table_size (segments);
|
||||
|
||||
this->segCountX2 = segments.length * 2;
|
||||
this->entrySelector = hb_max (1u, hb_bit_storage (segments.length)) - 1;
|
||||
//serialize endCode[]
|
||||
HBUINT16 *endCode = serialize_endcode_array (c, it);
|
||||
if (unlikely (!endCode)) return;
|
||||
|
||||
unsigned segcount = (c->length () - min_size) / HBUINT16::static_size;
|
||||
|
||||
// 2 bytes of padding.
|
||||
if (unlikely (!c->allocate_size<HBUINT16> (HBUINT16::static_size))) return; // 2 bytes of padding.
|
||||
|
||||
// serialize startCode[]
|
||||
HBUINT16 *startCode = serialize_startcode_array (c, it);
|
||||
if (unlikely (!startCode)) return;
|
||||
|
||||
//serialize idDelta[]
|
||||
HBINT16 *idDelta = serialize_idDelta_array (c, it, endCode, startCode, segcount);
|
||||
if (unlikely (!idDelta)) return;
|
||||
|
||||
HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, it, endCode, startCode, idDelta, segcount);
|
||||
if (unlikely (!c->check_success (idRangeOffset))) return;
|
||||
|
||||
if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return;
|
||||
this->segCountX2 = segcount * 2;
|
||||
this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1;
|
||||
this->searchRange = 2 * (1u << this->entrySelector);
|
||||
this->rangeShift = segments.length * 2 > this->searchRange
|
||||
? 2 * segments.length - this->searchRange
|
||||
this->rangeShift = segcount * 2 > this->searchRange
|
||||
? 2 * segcount - this->searchRange
|
||||
: 0;
|
||||
|
||||
HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
|
||||
c->allocate_size<HBUINT16> (HBUINT16::static_size); // 2 bytes of padding.
|
||||
HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
|
||||
HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.length);
|
||||
HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
|
||||
|
||||
if (id_range_offset == nullptr)
|
||||
return_trace (false);
|
||||
|
||||
for (unsigned int i = 0; i < segments.length; i++)
|
||||
{
|
||||
end_count[i] = segments[i].end_code;
|
||||
start_count[i] = segments[i].start_code;
|
||||
if (segments[i].use_delta)
|
||||
{
|
||||
hb_codepoint_t cp = segments[i].start_code;
|
||||
hb_codepoint_t start_gid = 0;
|
||||
if (unlikely (!plan->new_gid_for_codepoint (cp, &start_gid) && cp != 0xFFFF))
|
||||
return_trace (false);
|
||||
id_delta[i] = start_gid - segments[i].start_code;
|
||||
} else {
|
||||
id_delta[i] = 0;
|
||||
unsigned int num_codepoints = segments[i].end_code - segments[i].start_code + 1;
|
||||
HBUINT16 *glyph_id_array = c->allocate_size<HBUINT16> (HBUINT16::static_size * num_codepoints);
|
||||
if (glyph_id_array == nullptr)
|
||||
return_trace (false);
|
||||
// From the cmap spec:
|
||||
//
|
||||
// id_range_offset[i]/2
|
||||
// + (cp - segments[i].start_code)
|
||||
// + (id_range_offset + i)
|
||||
// =
|
||||
// glyph_id_array + (cp - segments[i].start_code)
|
||||
//
|
||||
// So, solve for id_range_offset[i]:
|
||||
//
|
||||
// id_range_offset[i]
|
||||
// =
|
||||
// 2 * (glyph_id_array - id_range_offset - i)
|
||||
id_range_offset[i] = 2 * (glyph_id_array - id_range_offset - i);
|
||||
for (unsigned int j = 0; j < num_codepoints; j++)
|
||||
{
|
||||
hb_codepoint_t cp = segments[i].start_code + j;
|
||||
hb_codepoint_t new_gid = 0;
|
||||
if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
|
||||
return_trace (false);
|
||||
glyph_id_array[j] = new_gid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
static size_t get_sub_table_size (const hb_sorted_vector_t<segment_plan> &segments)
|
||||
{
|
||||
size_t segment_size = 0;
|
||||
for (unsigned int i = 0; i < segments.length; i++)
|
||||
{
|
||||
// Parallel array entries
|
||||
segment_size +=
|
||||
2 // end count
|
||||
+ 2 // start count
|
||||
+ 2 // delta
|
||||
+ 2; // range offset
|
||||
|
||||
if (!segments[i].use_delta)
|
||||
// Add bytes for the glyph index array entries for this segment.
|
||||
segment_size += (segments[i].end_code - segments[i].start_code + 1) * 2;
|
||||
}
|
||||
|
||||
return min_size
|
||||
+ 2 // Padding
|
||||
+ segment_size;
|
||||
}
|
||||
|
||||
static bool create_sub_table_plan (const hb_subset_plan_t *plan,
|
||||
hb_sorted_vector_t<segment_plan> *segments)
|
||||
{
|
||||
segment_plan *segment = nullptr;
|
||||
hb_codepoint_t last_gid = 0;
|
||||
|
||||
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
|
||||
while (plan->unicodes->next (&cp)) {
|
||||
hb_codepoint_t new_gid = 0;
|
||||
if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Stop adding to cmap if we are now outside of unicode BMP. */
|
||||
if (cp > 0xFFFF) break;
|
||||
|
||||
if (!segment ||
|
||||
cp != segment->end_code + 1u)
|
||||
{
|
||||
segment = segments->push ();
|
||||
segment->start_code = cp;
|
||||
segment->end_code = cp;
|
||||
segment->use_delta = true;
|
||||
} else {
|
||||
segment->end_code = cp;
|
||||
if (last_gid + 1u != new_gid)
|
||||
// gid's are not consecutive in this segment so delta
|
||||
// cannot be used.
|
||||
segment->use_delta = false;
|
||||
}
|
||||
|
||||
last_gid = new_gid;
|
||||
}
|
||||
|
||||
// There must be a final entry with end_code == 0xFFFF. Check if we need to add one.
|
||||
if (segment == nullptr || segment->end_code != 0xFFFF)
|
||||
{
|
||||
segment = segments->push ();
|
||||
segment->start_code = 0xFFFF;
|
||||
segment->end_code = 0xFFFF;
|
||||
segment->use_delta = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct accelerator_t
|
||||
|
@ -489,15 +537,6 @@ struct CmapSubtableLongSegmented
|
|||
return_trace (c->check_struct (this) && groups.sanitize (c));
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const hb_sorted_vector_t<CmapSubtableLongGroup> &group_data)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!groups.serialize (c, group_data.as_array ()))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Subtable format; set to 12. */
|
||||
HBUINT16 reserved; /* Reserved; set to 0. */
|
||||
|
@ -517,17 +556,56 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
|
|||
group.glyphID + (u - group.startCharCode) : 0; }
|
||||
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (it.len () == 0) return;
|
||||
unsigned table_initpos = c->length ();
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
|
||||
hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
|
||||
hb_codepoint_t glyphID = 0;
|
||||
|
||||
+ it
|
||||
| hb_apply ([&] (const hb_item_type<Iterator> _)
|
||||
{
|
||||
if (startCharCode == 0xFFFF)
|
||||
{
|
||||
startCharCode = _.first;
|
||||
endCharCode = _.first;
|
||||
glyphID = _.second;
|
||||
}
|
||||
else if (!_is_gid_consecutive (endCharCode, startCharCode, glyphID, _.first, _.second))
|
||||
{
|
||||
CmapSubtableLongGroup grouprecord;
|
||||
grouprecord.startCharCode = startCharCode;
|
||||
grouprecord.endCharCode = endCharCode;
|
||||
grouprecord.glyphID = glyphID;
|
||||
c->copy<CmapSubtableLongGroup> (grouprecord);
|
||||
|
||||
startCharCode = _.first;
|
||||
endCharCode = _.first;
|
||||
glyphID = _.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
endCharCode = _.first;
|
||||
}
|
||||
})
|
||||
;
|
||||
|
||||
CmapSubtableLongGroup record;
|
||||
record.startCharCode = startCharCode;
|
||||
record.endCharCode = endCharCode;
|
||||
record.glyphID = glyphID;
|
||||
c->copy<CmapSubtableLongGroup> (record);
|
||||
|
||||
this->format = 12;
|
||||
this->reserved = 0;
|
||||
this->length = get_sub_table_size (groups_data);
|
||||
|
||||
return_trace (CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups_data));
|
||||
this->length = c->length () - table_initpos;
|
||||
this->groups.len = (this->length - min_size)/CmapSubtableLongGroup::static_size;
|
||||
}
|
||||
|
||||
static size_t get_sub_table_size (const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
|
||||
|
@ -535,46 +613,15 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
|
|||
return 16 + 12 * groups_data.length;
|
||||
}
|
||||
|
||||
static bool create_sub_table_plan (const hb_subset_plan_t *plan,
|
||||
hb_sorted_vector_t<CmapSubtableLongGroup> *groups_out)
|
||||
{
|
||||
CmapSubtableLongGroup *group = nullptr;
|
||||
|
||||
hb_codepoint_t cp = HB_SET_VALUE_INVALID;
|
||||
while (plan->unicodes->next (&cp)) {
|
||||
hb_codepoint_t new_gid = 0;
|
||||
if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!group || !_is_gid_consecutive (group, cp, new_gid))
|
||||
{
|
||||
group = groups_out->push ();
|
||||
group->startCharCode = cp;
|
||||
group->endCharCode = cp;
|
||||
group->glyphID = new_gid;
|
||||
}
|
||||
else group->endCharCode = cp;
|
||||
}
|
||||
|
||||
DEBUG_MSG(SUBSET, nullptr, "cmap");
|
||||
for (unsigned int i = 0; i < groups_out->length; i++) {
|
||||
CmapSubtableLongGroup& group = (*groups_out)[i];
|
||||
DEBUG_MSG(SUBSET, nullptr, " %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool _is_gid_consecutive (CmapSubtableLongGroup *group,
|
||||
static bool _is_gid_consecutive (hb_codepoint_t endCharCode,
|
||||
hb_codepoint_t startCharCode,
|
||||
hb_codepoint_t glyphID,
|
||||
hb_codepoint_t cp,
|
||||
hb_codepoint_t new_gid)
|
||||
{
|
||||
return (cp - 1 == group->endCharCode) &&
|
||||
new_gid == group->glyphID + (cp - group->startCharCode);
|
||||
return (cp - 1 == endCharCode) &&
|
||||
new_gid == glyphID + (cp - startCharCode);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -756,12 +803,10 @@ struct CmapSubtable
|
|||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
switch (u.format) {
|
||||
#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
|
||||
case 0: return u.format0 .get_glyph (codepoint, glyph);
|
||||
case 4: return u.format4 .get_glyph (codepoint, glyph);
|
||||
case 6: return u.format6 .get_glyph (codepoint, glyph);
|
||||
case 10: return u.format10.get_glyph (codepoint, glyph);
|
||||
#endif
|
||||
case 4: return u.format4 .get_glyph (codepoint, glyph);
|
||||
case 12: return u.format12.get_glyph (codepoint, glyph);
|
||||
case 13: return u.format13.get_glyph (codepoint, glyph);
|
||||
case 14:
|
||||
|
@ -771,12 +816,10 @@ struct CmapSubtable
|
|||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
switch (u.format) {
|
||||
#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
|
||||
case 0: u.format0 .collect_unicodes (out); return;
|
||||
case 4: u.format4 .collect_unicodes (out); return;
|
||||
case 6: u.format6 .collect_unicodes (out); return;
|
||||
case 10: u.format10.collect_unicodes (out); return;
|
||||
#endif
|
||||
case 4: u.format4 .collect_unicodes (out); return;
|
||||
case 12: u.format12.collect_unicodes (out); return;
|
||||
case 13: u.format13.collect_unicodes (out); return;
|
||||
case 14:
|
||||
|
@ -784,17 +827,28 @@ struct CmapSubtable
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
unsigned format)
|
||||
{
|
||||
switch (format) {
|
||||
case 4: u.format4.serialize (c, it); return;
|
||||
case 12: u.format12.serialize (c, it); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
switch (u.format) {
|
||||
#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
|
||||
case 0: return_trace (u.format0 .sanitize (c));
|
||||
case 4: return_trace (u.format4 .sanitize (c));
|
||||
case 6: return_trace (u.format6 .sanitize (c));
|
||||
case 10: return_trace (u.format10.sanitize (c));
|
||||
#endif
|
||||
case 4: return_trace (u.format4 .sanitize (c));
|
||||
case 12: return_trace (u.format12.sanitize (c));
|
||||
case 13: return_trace (u.format13.sanitize (c));
|
||||
case 14: return_trace (u.format14.sanitize (c));
|
||||
|
@ -805,12 +859,10 @@ struct CmapSubtable
|
|||
public:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
|
||||
CmapSubtableFormat0 format0;
|
||||
CmapSubtableFormat4 format4;
|
||||
CmapSubtableFormat6 format6;
|
||||
CmapSubtableFormat10 format10;
|
||||
#endif
|
||||
CmapSubtableFormat4 format4;
|
||||
CmapSubtableFormat12 format12;
|
||||
CmapSubtableFormat13 format13;
|
||||
CmapSubtableFormat14 format14;
|
||||
|
@ -839,6 +891,32 @@ struct EncodingRecord
|
|||
subtable.sanitize (c, base));
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
EncodingRecord* copy (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
unsigned format,
|
||||
void *base,
|
||||
/* INOUT */ unsigned *objidx) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->embed (this);
|
||||
if (unlikely (!out)) return_trace (nullptr);
|
||||
out->subtable = 0;
|
||||
|
||||
if (*objidx == 0)
|
||||
{
|
||||
CmapSubtable *cmapsubtable = c->push<CmapSubtable> ();
|
||||
unsigned origin_length = c->length ();
|
||||
cmapsubtable->serialize (c, it, format);
|
||||
if (c->length () - origin_length > 0) *objidx = c->pop_pack ();
|
||||
else c->pop_discard ();
|
||||
}
|
||||
|
||||
c->add_link (out->subtable, *objidx, base);
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
HBUINT16 platformID; /* Platform ID. */
|
||||
HBUINT16 encodingID; /* Platform-specific encoding ID. */
|
||||
LOffsetTo<CmapSubtable>
|
||||
|
@ -851,174 +929,62 @@ struct cmap
|
|||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
|
||||
|
||||
struct subset_plan
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
const EncodingRecord *unicode_bmp,
|
||||
const EncodingRecord *unicode_ucs4,
|
||||
const EncodingRecord *ms_bmp,
|
||||
const EncodingRecord *ms_ucs4)
|
||||
{
|
||||
size_t final_size () const
|
||||
{
|
||||
return 4 // header
|
||||
+ 8 * num_enc_records
|
||||
+ CmapSubtableFormat4::get_sub_table_size (this->format4_segments)
|
||||
+ CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
|
||||
}
|
||||
if (unlikely (!c->extend_min ((*this)))) return;
|
||||
this->version = 0;
|
||||
|
||||
unsigned int num_enc_records;
|
||||
bool has_unicode_bmp;
|
||||
bool has_unicode_ucs4;
|
||||
bool has_ms_bmp;
|
||||
bool has_ms_ucs4;
|
||||
hb_sorted_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
|
||||
hb_sorted_vector_t<CmapSubtableLongGroup> format12_groups;
|
||||
};
|
||||
unsigned numTables = (unicode_bmp ? 1 : 0) + (unicode_ucs4 ? 1 : 0) + (ms_bmp ? 1 : 0) + (ms_ucs4 ? 1 : 0);
|
||||
if (unlikely (!c->check_assign(this->encodingRecord.len, numTables))) return;
|
||||
|
||||
bool _create_plan (const hb_subset_plan_t *plan,
|
||||
subset_plan *cmap_plan) const
|
||||
{
|
||||
cmap_plan->has_unicode_bmp = find_subtable (0, 3);
|
||||
cmap_plan->has_unicode_ucs4 = find_subtable (0, 4);
|
||||
cmap_plan->has_ms_bmp = find_subtable (3, 1);
|
||||
cmap_plan->has_ms_ucs4 = find_subtable (3, 10);
|
||||
cmap_plan->num_enc_records = cmap_plan->has_unicode_bmp + cmap_plan->has_unicode_ucs4 + cmap_plan->has_ms_bmp + cmap_plan->has_ms_ucs4;
|
||||
unsigned format4objidx = 0, format12objidx = 0;
|
||||
if (unicode_bmp) c->copy (unicode_bmp, it, 4u, this, &format4objidx);
|
||||
if (unicode_ucs4) c->copy (unicode_ucs4, it, 12u, this, &format12objidx);
|
||||
if (ms_bmp) c->copy (ms_bmp, it, 4u, this, &format4objidx);
|
||||
if (ms_ucs4) c->copy (ms_ucs4, it, 12u, this, &format12objidx);
|
||||
|
||||
if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
|
||||
return false;
|
||||
|
||||
if (!find_subtable (12)) return true;
|
||||
return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
|
||||
}
|
||||
|
||||
bool _subset (const hb_subset_plan_t *plan,
|
||||
const subset_plan &cmap_subset_plan,
|
||||
size_t dest_sz,
|
||||
void *dest) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_serialize_context_t c (dest, dest_sz);
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
cmap *table = c.start_serialize<cmap> ();
|
||||
if (unlikely (!c.extend_min (*table)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
cmap *cmap_prime = c->serializer->start_embed<cmap> ();
|
||||
if (unlikely (!c->serializer->check_success (cmap_prime))) return_trace (false);
|
||||
|
||||
table->version = 0;
|
||||
const EncodingRecord *unicode_bmp = find_encodingrec (0, 3);
|
||||
const EncodingRecord *unicode_ucs4 = find_encodingrec (0, 4);
|
||||
const EncodingRecord *ms_bmp = find_encodingrec (3, 1);
|
||||
const EncodingRecord *ms_ucs4 = find_encodingrec (3, 10);
|
||||
bool has_format12 = find_subtable (12);
|
||||
|
||||
if (unlikely (!table->encodingRecord.serialize (&c, cmap_subset_plan.num_enc_records))) return false;
|
||||
if (unlikely (!unicode_bmp && !ms_bmp)) return_trace (false);
|
||||
if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
|
||||
|
||||
// TODO(grieger): Convert the below to a for loop
|
||||
int enc_index = 0;
|
||||
int unicode_bmp_index = 0;
|
||||
int unicode_ucs4_index = 0;
|
||||
int ms_bmp_index = 0;
|
||||
int ms_ucs4_index = 0;
|
||||
|
||||
// Format 4, Plat 0 Encoding Record
|
||||
if (cmap_subset_plan.has_unicode_bmp)
|
||||
{
|
||||
unicode_bmp_index = enc_index;
|
||||
EncodingRecord &format4_plat0_rec = table->encodingRecord[enc_index++];
|
||||
format4_plat0_rec.platformID = 0; // Unicode
|
||||
format4_plat0_rec.encodingID = 3;
|
||||
}
|
||||
auto it =
|
||||
+ hb_iter (c->plan->unicodes)
|
||||
| hb_map ([&] (hb_codepoint_t _)
|
||||
{
|
||||
hb_codepoint_t new_gid = HB_MAP_VALUE_INVALID;
|
||||
c->plan->new_gid_for_codepoint (_, &new_gid);
|
||||
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, new_gid);
|
||||
})
|
||||
| hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
|
||||
{
|
||||
return (_.second != HB_MAP_VALUE_INVALID);
|
||||
})
|
||||
;
|
||||
|
||||
// Format 12, Plat 0 Encoding Record
|
||||
if (cmap_subset_plan.has_unicode_ucs4)
|
||||
{
|
||||
unicode_ucs4_index = enc_index;
|
||||
EncodingRecord &format12_rec = table->encodingRecord[enc_index++];
|
||||
format12_rec.platformID = 0; // Unicode
|
||||
format12_rec.encodingID = 4; // Unicode UCS-4
|
||||
}
|
||||
|
||||
// Format 4, Plat 3 Encoding Record
|
||||
if (cmap_subset_plan.has_ms_bmp)
|
||||
{
|
||||
ms_bmp_index = enc_index;
|
||||
EncodingRecord &format4_plat3_rec = table->encodingRecord[enc_index++];
|
||||
format4_plat3_rec.platformID = 3; // Windows
|
||||
format4_plat3_rec.encodingID = 1; // Unicode BMP
|
||||
}
|
||||
|
||||
// Format 12, Plat 3 Encoding Record
|
||||
if (cmap_subset_plan.has_ms_ucs4)
|
||||
{
|
||||
ms_ucs4_index = enc_index;
|
||||
EncodingRecord &format12_rec = table->encodingRecord[enc_index++];
|
||||
format12_rec.platformID = 3; // Windows
|
||||
format12_rec.encodingID = 10; // Unicode UCS-4
|
||||
}
|
||||
|
||||
// Write out format 4 sub table
|
||||
{
|
||||
if (unlikely (!cmap_subset_plan.has_unicode_bmp && !cmap_subset_plan.has_ms_bmp)) return false;
|
||||
EncodingRecord &format4_rec = cmap_subset_plan.has_unicode_bmp?
|
||||
table->encodingRecord[unicode_bmp_index]:
|
||||
table->encodingRecord[ms_bmp_index];
|
||||
CmapSubtable &subtable = format4_rec.subtable.serialize (&c, table);
|
||||
if (cmap_subset_plan.has_unicode_bmp && cmap_subset_plan.has_ms_bmp)
|
||||
table->encodingRecord[ms_bmp_index].subtable = (unsigned int) format4_rec.subtable;
|
||||
subtable.u.format = 4;
|
||||
|
||||
CmapSubtableFormat4 &format4 = subtable.u.format4;
|
||||
if (unlikely (!format4.serialize (&c, plan, cmap_subset_plan.format4_segments)))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write out format 12 sub table.
|
||||
if (cmap_subset_plan.format12_groups)
|
||||
{
|
||||
if (unlikely (!cmap_subset_plan.has_unicode_ucs4 && !cmap_subset_plan.has_ms_ucs4)) return false;
|
||||
EncodingRecord &format12_rec = cmap_subset_plan.has_unicode_ucs4?
|
||||
table->encodingRecord[unicode_ucs4_index]:
|
||||
table->encodingRecord[ms_ucs4_index];
|
||||
|
||||
CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
|
||||
if (cmap_subset_plan.has_unicode_ucs4 && cmap_subset_plan.has_ms_ucs4)
|
||||
table->encodingRecord[ms_ucs4_index].subtable = (unsigned int) format12_rec.subtable;
|
||||
subtable.u.format = 12;
|
||||
|
||||
CmapSubtableFormat12 &format12 = subtable.u.format12;
|
||||
if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups)))
|
||||
return false;
|
||||
}
|
||||
|
||||
c.end_serialize ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_plan_t *plan) const
|
||||
{
|
||||
subset_plan cmap_subset_plan;
|
||||
|
||||
if (unlikely (!_create_plan (plan, &cmap_subset_plan)))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cmap subsetting plan.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We now know how big our blob needs to be
|
||||
size_t dest_sz = cmap_subset_plan.final_size ();
|
||||
void *dest = malloc (dest_sz);
|
||||
if (unlikely (!dest)) {
|
||||
DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unlikely (!_subset (plan, cmap_subset_plan, dest_sz, dest)))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Failed to perform subsetting of cmap.");
|
||||
free (dest);
|
||||
return false;
|
||||
}
|
||||
|
||||
// all done, write the blob into dest
|
||||
hb_blob_t *cmap_prime = hb_blob_create ((const char *) dest,
|
||||
dest_sz,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
dest,
|
||||
free);
|
||||
bool result = plan->add_table (HB_OT_TAG_cmap, cmap_prime);
|
||||
hb_blob_destroy (cmap_prime);
|
||||
return result;
|
||||
cmap_prime->serialize (c->serializer, it, unicode_bmp, unicode_ucs4, ms_bmp, ms_ucs4);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
|
||||
|
@ -1212,6 +1178,16 @@ struct cmap
|
|||
return &(this+result.subtable);
|
||||
}
|
||||
|
||||
const EncodingRecord *find_encodingrec (unsigned int platform_id,
|
||||
unsigned int encoding_id) const
|
||||
{
|
||||
EncodingRecord key;
|
||||
key.platformID = platform_id;
|
||||
key.encodingID = encoding_id;
|
||||
|
||||
return encodingRecord.as_array ().bsearch (key);
|
||||
}
|
||||
|
||||
bool find_subtable (unsigned format) const
|
||||
{
|
||||
auto it =
|
||||
|
|
|
@ -39,13 +39,15 @@ namespace OT {
|
|||
|
||||
struct LayerRecord
|
||||
{
|
||||
operator hb_ot_color_layer_t () const { return {glyphId, colorIdx}; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
public:
|
||||
protected:
|
||||
GlyphID glyphId; /* Glyph ID of layer glyph */
|
||||
Index colorIdx; /* Index value to use with a
|
||||
* selected color palette.
|
||||
|
@ -98,18 +100,14 @@ struct COLR
|
|||
{
|
||||
const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph);
|
||||
|
||||
hb_array_t<const LayerRecord> all_layers ((this+layersZ).arrayZ, numLayers);
|
||||
hb_array_t<const LayerRecord> all_layers = (this+layersZ).as_array (numLayers);
|
||||
hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
|
||||
record.numLayers);
|
||||
if (count)
|
||||
{
|
||||
hb_array_t<const LayerRecord> segment_layers = glyph_layers.sub_array (start_offset, *count);
|
||||
*count = segment_layers.length;
|
||||
for (unsigned int i = 0; i < segment_layers.length; i++)
|
||||
{
|
||||
layers[i].glyph = segment_layers.arrayZ[i].glyphId;
|
||||
layers[i].color_index = segment_layers.arrayZ[i].colorIdx;
|
||||
}
|
||||
+ glyph_layers.sub_array (start_offset, count)
|
||||
| hb_sink (hb_array (layers, *count))
|
||||
;
|
||||
}
|
||||
return glyph_layers.length;
|
||||
}
|
||||
|
|
|
@ -235,9 +235,9 @@ struct sbix
|
|||
const PNGHeader &png = *blob->as<PNGHeader>();
|
||||
|
||||
extents->x_bearing = x_offset;
|
||||
extents->y_bearing = y_offset;
|
||||
extents->y_bearing = png.IHDR.height + y_offset;
|
||||
extents->width = png.IHDR.width;
|
||||
extents->height = png.IHDR.height;
|
||||
extents->height = -png.IHDR.height;
|
||||
|
||||
/* Convert to font units. */
|
||||
if (strike_ppem)
|
||||
|
|
|
@ -50,9 +50,10 @@ HB_OT_TABLE (OT, head)
|
|||
#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
|
||||
HB_OT_ACCELERATOR (OT, cmap)
|
||||
#endif
|
||||
HB_OT_TABLE (OT, hhea)
|
||||
HB_OT_ACCELERATOR (OT, hmtx)
|
||||
HB_OT_TABLE (OT, OS2)
|
||||
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
|
||||
#if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS)
|
||||
HB_OT_ACCELERATOR (OT, post)
|
||||
#endif
|
||||
#ifndef HB_NO_NAME
|
||||
|
@ -61,8 +62,12 @@ HB_OT_ACCELERATOR (OT, name)
|
|||
#ifndef HB_NO_STAT
|
||||
HB_OT_TABLE (OT, STAT)
|
||||
#endif
|
||||
#ifndef HB_NO_META
|
||||
HB_OT_ACCELERATOR (OT, meta)
|
||||
#endif
|
||||
|
||||
/* Vertical layout. */
|
||||
HB_OT_TABLE (OT, vhea)
|
||||
HB_OT_ACCELERATOR (OT, vmtx)
|
||||
|
||||
/* TrueType outlines. */
|
||||
|
@ -88,11 +93,17 @@ HB_OT_TABLE (OT, kern)
|
|||
#endif
|
||||
|
||||
/* OpenType shaping. */
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
HB_OT_ACCELERATOR (OT, GDEF)
|
||||
HB_OT_ACCELERATOR (OT, GSUB)
|
||||
HB_OT_ACCELERATOR (OT, GPOS)
|
||||
//HB_OT_TABLE (OT, BASE)
|
||||
//HB_OT_TABLE (OT, JSTF)
|
||||
#endif
|
||||
|
||||
/* OpenType baseline. */
|
||||
#ifndef HB_NO_BASE
|
||||
HB_OT_TABLE (OT, BASE)
|
||||
#endif
|
||||
|
||||
/* AAT shaping. */
|
||||
#ifndef HB_NO_AAT
|
||||
|
@ -104,6 +115,7 @@ HB_OT_TABLE (AAT, trak)
|
|||
HB_OT_TABLE (AAT, lcar)
|
||||
HB_OT_TABLE (AAT, ltag)
|
||||
HB_OT_TABLE (AAT, feat)
|
||||
// HB_OT_TABLE (AAT, opbd)
|
||||
#endif
|
||||
|
||||
/* OpenType color fonts. */
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "hb-ot-cff2-table.hh"
|
||||
#include "hb-ot-hmtx-table.hh"
|
||||
#include "hb-ot-kern-table.hh"
|
||||
#include "hb-ot-meta-table.hh"
|
||||
#include "hb-ot-name-table.hh"
|
||||
#include "hb-ot-post-table.hh"
|
||||
#include "hb-ot-color-cbdt-table.hh"
|
||||
|
|
|
@ -230,32 +230,24 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
|||
|
||||
static hb_bool_t
|
||||
hb_ot_get_font_h_extents (hb_font_t *font,
|
||||
void *font_data,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
|
||||
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
|
||||
metrics->ascender = font->em_scale_y (hmtx.ascender);
|
||||
metrics->descender = font->em_scale_y (hmtx.descender);
|
||||
metrics->line_gap = font->em_scale_y (hmtx.line_gap);
|
||||
// TODO Hook up variations.
|
||||
return hmtx.has_font_extents;
|
||||
return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
hb_ot_get_font_v_extents (hb_font_t *font,
|
||||
void *font_data,
|
||||
void *font_data HB_UNUSED,
|
||||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
|
||||
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
|
||||
metrics->ascender = font->em_scale_x (vmtx.ascender);
|
||||
metrics->descender = font->em_scale_x (vmtx.descender);
|
||||
metrics->line_gap = font->em_scale_x (vmtx.line_gap);
|
||||
// TODO Hook up variations.
|
||||
return vmtx.has_font_extents;
|
||||
return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_ASCENDER, &metrics->ascender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
|
||||
}
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
|
|
|
@ -45,6 +45,8 @@ namespace OT {
|
|||
template <typename T>
|
||||
struct _hea
|
||||
{
|
||||
bool has_data () const { return version.major; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-hhea-table.hh"
|
||||
#include "hb-ot-os2-table.hh"
|
||||
#include "hb-ot-var-hvar-table.hh"
|
||||
#include "hb-ot-metrics.hh"
|
||||
|
||||
/*
|
||||
* hmtx -- Horizontal Metrics
|
||||
|
@ -162,28 +162,7 @@ struct hmtxvmtx
|
|||
{
|
||||
default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
|
||||
|
||||
bool got_font_extents = false;
|
||||
if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ())
|
||||
{
|
||||
ascender = abs (face->table.OS2->sTypoAscender);
|
||||
descender = -abs (face->table.OS2->sTypoDescender);
|
||||
line_gap = face->table.OS2->sTypoLineGap;
|
||||
got_font_extents = (ascender | descender) != 0;
|
||||
}
|
||||
|
||||
hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
|
||||
const H *_hea_table = _hea_blob->as<H> ();
|
||||
num_advances = _hea_table->numberOfLongMetrics;
|
||||
if (!got_font_extents)
|
||||
{
|
||||
ascender = abs (_hea_table->ascender);
|
||||
descender = -abs (_hea_table->descender);
|
||||
line_gap = _hea_table->lineGap;
|
||||
got_font_extents = (ascender | descender) != 0;
|
||||
}
|
||||
hb_blob_destroy (_hea_blob);
|
||||
|
||||
has_font_extents = got_font_extents;
|
||||
num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics;
|
||||
|
||||
table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
|
||||
|
||||
|
@ -277,12 +256,6 @@ struct hmtxvmtx
|
|||
return get_advance (old_gid);
|
||||
}
|
||||
|
||||
public:
|
||||
bool has_font_extents;
|
||||
int ascender;
|
||||
int descender;
|
||||
int line_gap;
|
||||
|
||||
protected:
|
||||
unsigned int num_metrics;
|
||||
unsigned int num_advances;
|
||||
|
@ -322,12 +295,12 @@ struct hmtxvmtx
|
|||
struct hmtx : hmtxvmtx<hmtx, hhea> {
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
|
||||
static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
|
||||
static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2;
|
||||
static constexpr bool is_horizontal = true;
|
||||
};
|
||||
struct vmtx : hmtxvmtx<vmtx, vhea> {
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
|
||||
static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
|
||||
static constexpr hb_tag_t os2Tag = HB_TAG_NONE;
|
||||
static constexpr bool is_horizontal = false;
|
||||
};
|
||||
|
||||
struct hmtx_accelerator_t : hmtx::accelerator_t {};
|
||||
|
|
|
@ -128,11 +128,11 @@ struct KernSubTable
|
|||
TRACE_DISPATCH (this, subtable_type);
|
||||
switch (subtable_type) {
|
||||
case 0: return_trace (c->dispatch (u.format0));
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
case 1: return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward<Ts> (ds)...) : c->default_return_value ());
|
||||
#endif
|
||||
case 2: return_trace (c->dispatch (u.format2));
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
case 3: return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward<Ts> (ds)...) : c->default_return_value ());
|
||||
#endif
|
||||
default: return_trace (c->default_return_value ());
|
||||
|
@ -282,7 +282,7 @@ struct kern
|
|||
{
|
||||
switch (get_type ()) {
|
||||
case 0: return u.ot.has_state_machine ();
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
case 1: return u.aat.has_state_machine ();
|
||||
#endif
|
||||
default:return false;
|
||||
|
@ -293,7 +293,7 @@ struct kern
|
|||
{
|
||||
switch (get_type ()) {
|
||||
case 0: return u.ot.has_cross_stream ();
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
case 1: return u.aat.has_cross_stream ();
|
||||
#endif
|
||||
default:return false;
|
||||
|
@ -304,7 +304,7 @@ struct kern
|
|||
{
|
||||
switch (get_type ()) {
|
||||
case 0: return u.ot.get_h_kerning (left, right);
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
case 1: return u.aat.get_h_kerning (left, right);
|
||||
#endif
|
||||
default:return 0;
|
||||
|
@ -321,7 +321,7 @@ struct kern
|
|||
TRACE_DISPATCH (this, subtable_type);
|
||||
switch (subtable_type) {
|
||||
case 0: return_trace (c->dispatch (u.ot, hb_forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
case 1: return_trace (c->dispatch (u.aat, hb_forward<Ts> (ds)...));
|
||||
#endif
|
||||
default: return_trace (c->default_return_value ());
|
||||
|
@ -340,7 +340,7 @@ struct kern
|
|||
HBUINT32 version32;
|
||||
HBUINT16 major;
|
||||
KernOT ot;
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
KernAAT aat;
|
||||
#endif
|
||||
} u;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
|
||||
* Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
|
||||
* Copyright © 2018 Google, Inc.
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
* Copyright © 2018-2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -32,9 +32,6 @@
|
|||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
|
||||
/* To be removed */
|
||||
typedef hb_tag_t hb_ot_layout_baseline_t;
|
||||
|
||||
namespace OT {
|
||||
|
||||
/*
|
||||
|
@ -116,9 +113,11 @@ struct BaseCoordFormat3
|
|||
|
||||
struct BaseCoord
|
||||
{
|
||||
hb_position_t get_coord (hb_font_t *font,
|
||||
bool has_data () const { return u.format; }
|
||||
|
||||
hb_position_t get_coord (hb_font_t *font,
|
||||
const VariationStore &var_store,
|
||||
hb_direction_t direction) const
|
||||
hb_direction_t direction) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1: return u.format1.get_coord ();
|
||||
|
@ -142,10 +141,10 @@ struct BaseCoord
|
|||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format;
|
||||
BaseCoordFormat1 format1;
|
||||
BaseCoordFormat2 format2;
|
||||
BaseCoordFormat3 format3;
|
||||
HBUINT16 format;
|
||||
BaseCoordFormat1 format1;
|
||||
BaseCoordFormat2 format2;
|
||||
BaseCoordFormat3 format3;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
|
@ -153,14 +152,9 @@ struct BaseCoord
|
|||
|
||||
struct FeatMinMaxRecord
|
||||
{
|
||||
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
|
||||
{
|
||||
hb_tag_t key = * (hb_tag_t *) key_;
|
||||
const FeatMinMaxRecord &entry = * (const FeatMinMaxRecord *) entry_;
|
||||
return key < (unsigned int) entry.tag ? -1 :
|
||||
key > (unsigned int) entry.tag ? 1 :
|
||||
0;
|
||||
}
|
||||
int cmp (hb_tag_t key) const { return tag.cmp (key); }
|
||||
|
||||
bool has_data () const { return tag; }
|
||||
|
||||
void get_min_max (const BaseCoord **min, const BaseCoord **max) const
|
||||
{
|
||||
|
@ -195,17 +189,12 @@ struct FeatMinMaxRecord
|
|||
struct MinMax
|
||||
{
|
||||
void get_min_max (hb_tag_t feature_tag,
|
||||
const BaseCoord **min,
|
||||
const BaseCoord **max) const
|
||||
const BaseCoord **min,
|
||||
const BaseCoord **max) const
|
||||
{
|
||||
/* TODO Replace hb_bsearch() with .bsearch(). */
|
||||
const FeatMinMaxRecord *minMaxCoord = (const FeatMinMaxRecord *)
|
||||
hb_bsearch (&feature_tag, featMinMaxRecords.arrayZ,
|
||||
featMinMaxRecords.len,
|
||||
FeatMinMaxRecord::static_size,
|
||||
FeatMinMaxRecord::cmp);
|
||||
if (minMaxCoord)
|
||||
minMaxCoord->get_min_max (min, max);
|
||||
const FeatMinMaxRecord &minMaxCoord = featMinMaxRecords.bsearch (feature_tag);
|
||||
if (minMaxCoord.has_data ())
|
||||
minMaxCoord.get_min_max (min, max);
|
||||
else
|
||||
{
|
||||
if (likely (min)) *min = &(this+minCoord);
|
||||
|
@ -271,17 +260,11 @@ struct BaseValues
|
|||
|
||||
struct BaseLangSysRecord
|
||||
{
|
||||
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
|
||||
{
|
||||
hb_tag_t key = * (hb_tag_t *) key_;
|
||||
const BaseLangSysRecord &entry = * (const BaseLangSysRecord *) entry_;
|
||||
return key < (unsigned int) entry.baseLangSysTag ? -1 :
|
||||
key > (unsigned int) entry.baseLangSysTag ? 1 :
|
||||
0;
|
||||
}
|
||||
int cmp (hb_tag_t key) const { return baseLangSysTag.cmp (key); }
|
||||
|
||||
const MinMax &get_min_max () const
|
||||
{ return this+minMax; }
|
||||
bool has_data () const { return baseLangSysTag; }
|
||||
|
||||
const MinMax &get_min_max () const { return this+minMax; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
|
@ -303,19 +286,14 @@ struct BaseScript
|
|||
{
|
||||
const MinMax &get_min_max (hb_tag_t language_tag) const
|
||||
{
|
||||
/* TODO Replace hb_bsearch() with .bsearch(). */
|
||||
const BaseLangSysRecord* record = (const BaseLangSysRecord *)
|
||||
hb_bsearch (&language_tag, baseLangSysRecords.arrayZ,
|
||||
baseLangSysRecords.len,
|
||||
BaseLangSysRecord::static_size,
|
||||
BaseLangSysRecord::cmp);
|
||||
return record ? record->get_min_max () : this+defaultMinMax;
|
||||
const BaseLangSysRecord& record = baseLangSysRecords.bsearch (language_tag);
|
||||
return record.has_data () ? record.get_min_max () : this+defaultMinMax;
|
||||
}
|
||||
|
||||
const BaseCoord &get_base_coord (int baseline_tag_index) const
|
||||
{ return (this+baseValues).get_base_coord (baseline_tag_index); }
|
||||
|
||||
bool is_empty () const { return !baseValues; }
|
||||
bool has_data () const { return baseValues; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -345,14 +323,9 @@ struct BaseScript
|
|||
struct BaseScriptList;
|
||||
struct BaseScriptRecord
|
||||
{
|
||||
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
|
||||
{
|
||||
hb_tag_t key = * (hb_tag_t *) key_;
|
||||
const BaseScriptRecord &entry = * (const BaseScriptRecord *) entry_;
|
||||
return key < (unsigned int) entry.baseScriptTag ? -1 :
|
||||
key > (unsigned int) entry.baseScriptTag ? 1 :
|
||||
0;
|
||||
}
|
||||
int cmp (hb_tag_t key) const { return baseScriptTag.cmp (key); }
|
||||
|
||||
bool has_data () const { return baseScriptTag; }
|
||||
|
||||
const BaseScript &get_base_script (const BaseScriptList *list) const
|
||||
{ return list+baseScript; }
|
||||
|
@ -376,22 +349,11 @@ struct BaseScriptRecord
|
|||
|
||||
struct BaseScriptList
|
||||
{
|
||||
const BaseScriptRecord *find_record (hb_tag_t script) const
|
||||
{
|
||||
/* TODO Replace hb_bsearch() with .bsearch(). */
|
||||
return (const BaseScriptRecord *) hb_bsearch (&script, baseScriptRecords.arrayZ,
|
||||
baseScriptRecords.len,
|
||||
BaseScriptRecord::static_size,
|
||||
BaseScriptRecord::cmp);
|
||||
}
|
||||
|
||||
/* TODO: Or client should handle fallback? */
|
||||
const BaseScript &get_base_script (hb_tag_t script) const
|
||||
{
|
||||
const BaseScriptRecord *record = find_record (script);
|
||||
if (!record) record = find_record ((hb_script_t) HB_TAG ('D','F','L','T'));
|
||||
|
||||
return record ? record->get_base_script (this) : Null (BaseScript);
|
||||
const BaseScriptRecord *record = &baseScriptRecords.bsearch (script);
|
||||
if (!record->has_data ()) record = &baseScriptRecords.bsearch (HB_TAG ('D','F','L','T'));
|
||||
return record->has_data () ? record->get_base_script (this) : Null (BaseScript);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -411,15 +373,20 @@ struct BaseScriptList
|
|||
|
||||
struct Axis
|
||||
{
|
||||
bool get_baseline (hb_ot_layout_baseline_t baseline,
|
||||
hb_tag_t script_tag,
|
||||
hb_tag_t language_tag,
|
||||
const BaseCoord **coord) const
|
||||
bool get_baseline (hb_tag_t baseline_tag,
|
||||
hb_tag_t script_tag,
|
||||
hb_tag_t language_tag,
|
||||
const BaseCoord **coord) const
|
||||
{
|
||||
const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
|
||||
if (base_script.is_empty ()) return false;
|
||||
if (!base_script.has_data ()) return false;
|
||||
|
||||
if (likely (coord)) *coord = &base_script.get_base_coord ((this+baseTagList).bsearch (baseline));
|
||||
if (likely (coord))
|
||||
{
|
||||
unsigned int tag_index = 0;
|
||||
(this+baseTagList).bfind (baseline_tag, &tag_index);
|
||||
*coord = &base_script.get_base_coord (tag_index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -431,7 +398,7 @@ struct Axis
|
|||
const BaseCoord **max_coord) const
|
||||
{
|
||||
const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
|
||||
if (base_script.is_empty ()) return false;
|
||||
if (!base_script.has_data ()) return false;
|
||||
|
||||
base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord);
|
||||
|
||||
|
@ -472,20 +439,21 @@ struct BASE
|
|||
const VariationStore &get_var_store () const
|
||||
{ return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; }
|
||||
|
||||
bool get_baseline (hb_font_t *font,
|
||||
hb_ot_layout_baseline_t baseline,
|
||||
hb_direction_t direction,
|
||||
hb_tag_t script_tag,
|
||||
hb_tag_t language_tag,
|
||||
hb_position_t *base) const
|
||||
bool get_baseline (hb_font_t *font,
|
||||
hb_tag_t baseline_tag,
|
||||
hb_direction_t direction,
|
||||
hb_tag_t script_tag,
|
||||
hb_tag_t language_tag,
|
||||
hb_position_t *base) const
|
||||
{
|
||||
const BaseCoord *base_coord;
|
||||
if (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord))
|
||||
const BaseCoord *base_coord = nullptr;
|
||||
if (unlikely (!get_axis (direction).get_baseline (baseline_tag, script_tag, language_tag, &base_coord) ||
|
||||
!base_coord || !base_coord->has_data ()))
|
||||
return false;
|
||||
|
||||
if (likely (base && base_coord)) *base = base_coord->get_coord (font,
|
||||
get_var_store (),
|
||||
direction);
|
||||
if (likely (base))
|
||||
*base = base_coord->get_coord (font, get_var_store (), direction);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -236,6 +236,11 @@ struct ValueFormat : HBUINT16
|
|||
}
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
static inline void SinglePos_serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
ValueFormat valFormat);
|
||||
|
||||
|
||||
struct AnchorFormat1
|
||||
{
|
||||
|
@ -496,11 +501,52 @@ struct SinglePosFormat1
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
ValueFormat valFormat)
|
||||
{
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
|
||||
|
||||
auto vals = hb_second (*it);
|
||||
|
||||
+ vals
|
||||
| hb_apply ([=] (const Value& _)
|
||||
{
|
||||
c->copy (_);
|
||||
})
|
||||
;
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
coverage.serialize (c, this).serialize (c, glyphs);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
// TODO(subset)
|
||||
return_trace (false);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
unsigned length = valueFormat.get_len ();
|
||||
|
||||
auto it =
|
||||
+ hb_iter (this+coverage)
|
||||
| hb_filter (glyphset)
|
||||
| hb_map_retains_sorting ([&] (hb_codepoint_t p)
|
||||
{
|
||||
return hb_pair (glyph_map[p], values.as_array (length));
|
||||
})
|
||||
;
|
||||
|
||||
bool ret = bool (it);
|
||||
SinglePos_serialize (c->serializer, it, valueFormat);
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -552,11 +598,58 @@ struct SinglePosFormat2
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
ValueFormat valFormat)
|
||||
{
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
|
||||
if (unlikely (!c->check_assign (valueCount, it.len ()))) return;
|
||||
|
||||
+ it
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([=] (hb_array_t<const Value> val_iter)
|
||||
{
|
||||
+ val_iter
|
||||
| hb_apply ([=] (const Value& _)
|
||||
{
|
||||
c->copy (_);
|
||||
})
|
||||
;
|
||||
})
|
||||
;
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
coverage.serialize (c, this).serialize (c, glyphs);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
// TODO(subset)
|
||||
return_trace (false);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
unsigned sub_length = valueFormat.get_len ();
|
||||
unsigned total_length = (unsigned)valueCount * sub_length;
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, hb_range ((unsigned) valueCount))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
|
||||
{
|
||||
return hb_pair (glyph_map[_.first], values.as_array (total_length).sub_array (_.second * sub_length, sub_length));
|
||||
})
|
||||
;
|
||||
|
||||
bool ret = bool (it);
|
||||
SinglePos_serialize (c->serializer, it, valueFormat);
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -583,6 +676,55 @@ struct SinglePosFormat2
|
|||
|
||||
struct SinglePos
|
||||
{
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
unsigned get_format (Iterator glyph_val_iter_pairs)
|
||||
{
|
||||
unsigned subset_format = 1;
|
||||
hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
|
||||
|
||||
+ glyph_val_iter_pairs
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (hb_array_t<const Value> val_iter)
|
||||
{
|
||||
+ hb_zip (val_iter, first_val_iter)
|
||||
| hb_apply ([&] (const hb_pair_t<Value, Value>& _)
|
||||
{
|
||||
if (_.first != _.second)
|
||||
{
|
||||
subset_format = 2;
|
||||
return;
|
||||
}
|
||||
})
|
||||
;
|
||||
})
|
||||
;
|
||||
|
||||
return subset_format;
|
||||
}
|
||||
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
Iterator glyph_val_iter_pairs,
|
||||
ValueFormat valFormat)
|
||||
{
|
||||
if (unlikely (!c->extend_min (u.format))) return;
|
||||
unsigned format = 2;
|
||||
|
||||
if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs);
|
||||
|
||||
u.format = format;
|
||||
switch (u.format) {
|
||||
case 1: u.format1.serialize (c, glyph_val_iter_pairs, valFormat);
|
||||
return;
|
||||
case 2: u.format2.serialize (c, glyph_val_iter_pairs, valFormat);
|
||||
return;
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
|
@ -603,6 +745,13 @@ struct SinglePos
|
|||
} u;
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
static inline void
|
||||
SinglePos_serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
ValueFormat valFormat)
|
||||
{ c->start_embed<SinglePos> ()->serialize (c, it, valFormat); }
|
||||
|
||||
|
||||
struct PairValueRecord
|
||||
{
|
||||
|
@ -733,7 +882,7 @@ struct PairPosFormat1
|
|||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (*glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map ([=] (const OffsetTo<PairSet> &_)
|
||||
| hb_map ([glyphs, this] (const OffsetTo<PairSet> &_)
|
||||
{ return (this+_).intersects (glyphs, valueFormat); })
|
||||
| hb_any
|
||||
;
|
||||
|
@ -1737,13 +1886,13 @@ struct GPOS_accelerator_t : GPOS::accelerator_t {};
|
|||
|
||||
/* Out-of-class implementation for methods recursing */
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
template <typename context_t>
|
||||
/*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
|
||||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
/*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
|
||||
|
@ -1756,6 +1905,7 @@ template <typename context_t>
|
|||
c->set_lookup_props (saved_lookup_props);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
} /* namespace OT */
|
||||
|
|
|
@ -248,7 +248,7 @@ struct SingleSubst
|
|||
if (unlikely (!c->extend_min (u.format))) return_trace (false);
|
||||
unsigned format = 2;
|
||||
unsigned delta = 0;
|
||||
if (glyphs.len ())
|
||||
if (glyphs)
|
||||
{
|
||||
format = 1;
|
||||
auto get_delta = [=] (hb_codepoint_pair_t _) {
|
||||
|
@ -1409,6 +1409,7 @@ struct GSUB_accelerator_t : GSUB::accelerator_t {};
|
|||
|
||||
/* Out-of-class implementation for methods recursing */
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
/*static*/ inline bool ExtensionSubst::is_reverse () const
|
||||
{
|
||||
unsigned int type = get_type ();
|
||||
|
@ -1416,14 +1417,12 @@ struct GSUB_accelerator_t : GSUB::accelerator_t {};
|
|||
return CastR<ExtensionSubst> (get_subtable<SubTable>()).is_reverse ();
|
||||
return SubstLookup::lookup_type_is_reverse (type);
|
||||
}
|
||||
|
||||
template <typename context_t>
|
||||
/*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
|
||||
return l.dispatch (c);
|
||||
}
|
||||
|
||||
/*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
|
||||
{
|
||||
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
|
||||
|
@ -1436,6 +1435,8 @@ template <typename context_t>
|
|||
c->set_lookup_props (saved_lookup_props);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
|
|
@ -483,7 +483,13 @@ struct hb_ot_apply_context_t :
|
|||
iter_input (), iter_context (),
|
||||
font (font_), face (font->face), buffer (buffer_),
|
||||
recurse_func (nullptr),
|
||||
gdef (*face->table.GDEF->table),
|
||||
gdef (
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
*face->table.GDEF->table
|
||||
#else
|
||||
Null(GDEF)
|
||||
#endif
|
||||
),
|
||||
var_store (gdef.get_var_store ()),
|
||||
direction (buffer_->props.direction),
|
||||
lookup_mask (1),
|
||||
|
|
|
@ -28,6 +28,14 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT
|
||||
|
||||
#ifdef HB_NO_OT_TAG
|
||||
#error "Cannot compile hb-ot-layout.cc with HB_NO_OT_TAG."
|
||||
#endif
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-layout.hh"
|
||||
#include "hb-ot-face.hh"
|
||||
|
@ -35,7 +43,6 @@
|
|||
#include "hb-map.hh"
|
||||
|
||||
#include "hb-ot-kern-table.hh"
|
||||
#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-layout-gpos-table.hh"
|
||||
|
@ -47,6 +54,7 @@
|
|||
#include "hb-aat-layout-lcar-table.hh"
|
||||
#include "hb-aat-layout-morx-table.hh"
|
||||
|
||||
#include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise.
|
||||
|
||||
/**
|
||||
* SECTION:hb-ot-layout
|
||||
|
@ -388,7 +396,7 @@ OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
|
|||
return false;
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
/* Mac OS X prefers morx over GSUB. It also ships with various Indic fonts,
|
||||
* all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
|
||||
* GSUB/GPOS tables. Some have GSUB with zero scripts, those are ignored by
|
||||
|
@ -1933,70 +1941,36 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
|
|||
apply_string<GSUBProxy> (c, lookup, accel);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifndef HB_NO_BASE
|
||||
/**
|
||||
* hb_ot_layout_get_baseline:
|
||||
* @font: a font
|
||||
* @baseline: a baseline tag
|
||||
* @direction: text direction.
|
||||
* @script_tag: script tag.
|
||||
* @language_tag: language tag.
|
||||
* @coord: (out): baseline value if found.
|
||||
*
|
||||
* Fetches a baseline value from the face.
|
||||
*
|
||||
* Return value: if found baseline value in the the font.
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_ot_layout_get_baseline (hb_font_t *font,
|
||||
hb_ot_layout_baseline_t baseline,
|
||||
hb_direction_t direction,
|
||||
hb_tag_t script_tag,
|
||||
hb_tag_t language_tag,
|
||||
hb_position_t *coord /* OUT. May be NULL. */)
|
||||
hb_ot_layout_get_baseline (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. May be NULL. */)
|
||||
{
|
||||
bool result = font->face->table.BASE->get_baseline (font, baseline, direction, script_tag,
|
||||
language_tag, coord);
|
||||
bool result = font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord);
|
||||
|
||||
/* TODO: Simulate https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags#ideographic-em-box */
|
||||
if (!result && coord) *coord = 0;
|
||||
|
||||
if (coord) *coord = font->em_scale_dir (*coord, direction);
|
||||
if (result && coord)
|
||||
*coord = HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (*coord) : font->em_scale_x (*coord);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* To be moved to public header */
|
||||
/*
|
||||
* BASE
|
||||
*/
|
||||
|
||||
/**
|
||||
* hb_ot_layout_baseline_t:
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags
|
||||
*
|
||||
* Since: DONTREPLACEME
|
||||
*/
|
||||
typedef enum {
|
||||
HB_OT_LAYOUT_BASELINE_HANG = HB_TAG('h','a','n','g'),
|
||||
HB_OT_LAYOUT_BASELINE_ICFB = HB_TAG('i','c','f','b'),
|
||||
HB_OT_LAYOUT_BASELINE_ICFT = HB_TAG('i','c','f','t'),
|
||||
HB_OT_LAYOUT_BASELINE_IDEO = HB_TAG('i','d','e','o'),
|
||||
HB_OT_LAYOUT_BASELINE_IDTB = HB_TAG('i','d','t','b'),
|
||||
HB_OT_LAYOUT_BASELINE_MATH = HB_TAG('m','a','t','h'),
|
||||
HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n')
|
||||
} hb_ot_layout_baseline_t;
|
||||
|
||||
|
||||
/**
|
||||
* hb_ot_layout_get_baseline:
|
||||
* @font: The #hb_font_t to work upon
|
||||
* @baseline: The #hb_ot_layout_baseline_t to query
|
||||
* @direction: The #hb_direction_t text direction to use (horizontal or vertical)
|
||||
* @script_tag: #hb_tag_t of the script to use
|
||||
* @language_tag: #hb_tag_t of the language to use
|
||||
* @coord: (out): The position of the requested baseline
|
||||
*
|
||||
* Fetches the coordinates of the specified baseline in the face, underneath
|
||||
* the specified script and language and in the specified text direction.
|
||||
*
|
||||
* Return value: true if the baseline is found for the settings queried, false otherwise
|
||||
*
|
||||
**/
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_layout_get_baseline (hb_font_t *font,
|
||||
hb_ot_layout_baseline_t baseline,
|
||||
hb_direction_t direction,
|
||||
hb_tag_t script_tag,
|
||||
hb_tag_t language_tag,
|
||||
hb_position_t *coord /* OUT. May be NULL. */);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -402,6 +402,55 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
|
|||
unsigned int *char_count /* IN/OUT. May be NULL */,
|
||||
hb_codepoint_t *characters /* OUT. May be NULL */);
|
||||
|
||||
/*
|
||||
* BASE
|
||||
*/
|
||||
|
||||
/**
|
||||
* hb_ot_layout_baseline_tag_t:
|
||||
* @HB_OT_LAYOUT_BASELINE_TAG_ROMAN: The baseline used by alphabetic scripts such as Latin, Cyrillic and Greek.
|
||||
* In vertical writing mode, the alphabetic baseline for characters rotated 90 degrees clockwise.
|
||||
* (This would not apply to alphabetic characters that remain upright in vertical writing mode, since these
|
||||
* characters are not rotated.)
|
||||
* @HB_OT_LAYOUT_BASELINE_TAG_HANGING: The hanging baseline. In horizontal direction, this is the horizontal
|
||||
* line from which syllables seem, to hang in Tibetan and other similar scripts. In vertical writing mode,
|
||||
* for Tibetan (or some other similar script) characters rotated 90 degrees clockwise.
|
||||
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT: Ideographic character face bottom or left edge,
|
||||
* 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_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,
|
||||
* 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.
|
||||
*
|
||||
* Baseline tags from https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags
|
||||
*
|
||||
* Since: 2.6.0
|
||||
*/
|
||||
typedef enum {
|
||||
HB_OT_LAYOUT_BASELINE_TAG_ROMAN = HB_TAG ('r','o','m','n'),
|
||||
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_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_MATH = HB_TAG ('m','a','t','h'),
|
||||
|
||||
_HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_ot_layout_baseline_tag_t;
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_layout_get_baseline (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. May be NULL. */);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_OT_LAYOUT_H */
|
||||
|
|
|
@ -168,6 +168,17 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
|
|||
return start;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
info[i].syllable() = 0;
|
||||
}
|
||||
|
||||
|
||||
/* unicode_props */
|
||||
|
||||
|
@ -551,6 +562,17 @@ _hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
|
|||
info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
_hb_glyph_info_clear_substituted (&info[i]);
|
||||
}
|
||||
|
||||
|
||||
/* Allocation / deallocation. */
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-map.hh"
|
||||
#include "hb-ot-shape.hh"
|
||||
#include "hb-ot-layout.hh"
|
||||
|
@ -332,3 +336,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -154,8 +154,8 @@ struct hb_ot_map_t
|
|||
|
||||
HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
|
||||
template <typename Proxy>
|
||||
HB_INTERNAL inline void apply (const Proxy &proxy,
|
||||
const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
|
||||
HB_INTERNAL void apply (const Proxy &proxy,
|
||||
const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
|
||||
HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
|
||||
HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
|
||||
|
||||
|
|
|
@ -453,14 +453,14 @@ struct MathGlyphPartRecord
|
|||
}
|
||||
|
||||
void extract (hb_ot_math_glyph_part_t &out,
|
||||
int scale,
|
||||
int64_t mult,
|
||||
hb_font_t *font) const
|
||||
{
|
||||
out.glyph = glyph;
|
||||
|
||||
out.start_connector_length = font->em_scale (startConnectorLength, scale);
|
||||
out.end_connector_length = font->em_scale (endConnectorLength, scale);
|
||||
out.full_advance = font->em_scale (fullAdvance, scale);
|
||||
out.start_connector_length = font->em_mult (startConnectorLength, mult);
|
||||
out.end_connector_length = font->em_mult (endConnectorLength, mult);
|
||||
out.full_advance = font->em_mult (fullAdvance, mult);
|
||||
|
||||
static_assert ((unsigned int) HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER ==
|
||||
(unsigned int) PartFlags::Extender, "");
|
||||
|
@ -508,11 +508,11 @@ struct MathGlyphAssembly
|
|||
{
|
||||
if (parts_count)
|
||||
{
|
||||
int scale = font->dir_scale (direction);
|
||||
int64_t mult = font->dir_mult (direction);
|
||||
hb_array_t<const MathGlyphPartRecord> arr = partRecords.sub_array (start_offset, parts_count);
|
||||
unsigned int count = arr.length;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
arr[i].extract (parts[i], scale, font);
|
||||
arr[i].extract (parts[i], mult, font);
|
||||
}
|
||||
|
||||
if (italics_correction)
|
||||
|
@ -553,13 +553,13 @@ struct MathGlyphConstruction
|
|||
{
|
||||
if (variants_count)
|
||||
{
|
||||
int scale = font->dir_scale (direction);
|
||||
int64_t mult = font->dir_mult (direction);
|
||||
hb_array_t<const MathGlyphVariantRecord> arr = mathGlyphVariantRecord.sub_array (start_offset, variants_count);
|
||||
unsigned int count = arr.length;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
variants[i].glyph = arr[i].variantGlyph;
|
||||
variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale);
|
||||
variants[i].advance = font->em_mult (arr[i].advanceMeasurement, mult);
|
||||
}
|
||||
}
|
||||
return mathGlyphVariantRecord.len;
|
||||
|
|
|
@ -158,7 +158,7 @@ typedef enum { /*< flags >*/
|
|||
* hb_ot_math_glyph_part_t:
|
||||
* @glyph: The glyph index of the variant part
|
||||
* @start_connector_length: The length of the connector on the starting side of the variant part
|
||||
* @end_connection_length: The length of the connector on the ending side of the variant part
|
||||
* @end_connector_length: The length of the connector on the ending side of the variant part
|
||||
* @full_advance: The total advance of the part
|
||||
* @flags: #hb_ot_math_glyph_part_flags_t flags for the part
|
||||
*
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright © 2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_META_TABLE_HH
|
||||
#define HB_OT_META_TABLE_HH
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
|
||||
/*
|
||||
* meta -- Metadata Table
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/meta
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html
|
||||
*/
|
||||
#define HB_OT_TAG_meta HB_TAG ('m','e','t','a')
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct DataMap
|
||||
{
|
||||
int cmp (hb_tag_t a) const { return tag.cmp (a); }
|
||||
|
||||
hb_tag_t get_tag () const { return tag; }
|
||||
|
||||
hb_blob_t *reference_entry (hb_blob_t *meta_blob) const
|
||||
{ return hb_blob_create_sub_blob (meta_blob, dataZ, dataLength); }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
dataZ.sanitize (c, base, dataLength)));
|
||||
}
|
||||
|
||||
protected:
|
||||
Tag tag; /* A tag indicating the type of metadata. */
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT8>>
|
||||
dataZ; /* Offset in bytes from the beginning of the
|
||||
* metadata table to the data for this tag. */
|
||||
HBUINT32 dataLength; /* Length of the data. The data is not required to
|
||||
* be padded to any byte boundary. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
|
||||
struct meta
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_meta;
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
void init (hb_face_t *face)
|
||||
{ table = hb_sanitize_context_t ().reference_table<meta> (face); }
|
||||
void fini () { table.destroy (); }
|
||||
|
||||
hb_blob_t *reference_entry (hb_tag_t tag) const
|
||||
{ return table->dataMaps.lsearch (tag).reference_entry (table.get_blob ()); }
|
||||
|
||||
unsigned int get_entries (unsigned int start_offset,
|
||||
unsigned int *count,
|
||||
hb_ot_meta_tag_t *entries) const
|
||||
{
|
||||
if (count)
|
||||
{
|
||||
+ table->dataMaps.sub_array (start_offset, count)
|
||||
| hb_map (&DataMap::get_tag)
|
||||
| hb_map ([](hb_tag_t tag) { return (hb_ot_meta_tag_t) tag; })
|
||||
| hb_sink (hb_array (entries, *count))
|
||||
;
|
||||
}
|
||||
return table->dataMaps.len;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_blob_ptr_t<meta> table;
|
||||
};
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
version == 1 &&
|
||||
dataMaps.sanitize (c, this)));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT32 version; /* Version number of the metadata table — set to 1. */
|
||||
HBUINT32 flags; /* Flags — currently unused; set to 0. */
|
||||
HBUINT32 dataOffset; /* Per Apple specification:
|
||||
* Offset from the beginning of the table to the data.
|
||||
* Per OT specification:
|
||||
* Reserved. Not used; should be set to 0. */
|
||||
LArrayOf<DataMap>
|
||||
dataMaps; /* Array of data map records. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (16, dataMaps);
|
||||
};
|
||||
|
||||
struct meta_accelerator_t : meta::accelerator_t {};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* HB_OT_META_TABLE_HH */
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright © 2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_META
|
||||
|
||||
#include "hb-ot-meta-table.hh"
|
||||
|
||||
/**
|
||||
* SECTION:hb-ot-meta
|
||||
* @title: hb-ot-meta
|
||||
* @short_description: OpenType Metadata
|
||||
* @include: hb-ot.h
|
||||
*
|
||||
* Functions for fetching metadata from fonts.
|
||||
**/
|
||||
|
||||
/**
|
||||
* hb_ot_meta_reference_entry:
|
||||
* @face: a face object
|
||||
* @start_offset: iteration's start offset
|
||||
* @entries_count:(inout) (allow-none): buffer size as input, filled size as output
|
||||
* @entries: (out caller-allocates) (array length=entries_count): entries tags buffer
|
||||
*
|
||||
* Return value: Number of all available feature types.
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
unsigned int
|
||||
hb_ot_meta_get_entry_tags (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *entries_count, /* IN/OUT. May be NULL. */
|
||||
hb_ot_meta_tag_t *entries /* OUT. May be NULL. */)
|
||||
{
|
||||
return face->table.meta->get_entries (start_offset, entries_count, entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_meta_reference_entry:
|
||||
* @face: a #hb_face_t object.
|
||||
* @meta_tag: tag of metadata you like to have.
|
||||
*
|
||||
* It fetches metadata entry of a given tag from a font.
|
||||
*
|
||||
* Returns: (transfer full): A blob containing the blob.
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
hb_blob_t *
|
||||
hb_ot_meta_reference_entry (hb_face_t *face, hb_ot_meta_tag_t meta_tag)
|
||||
{
|
||||
return face->table.meta->reference_entry (meta_tag);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright © 2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_H_IN
|
||||
#error "Include <hb-ot.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef HB_OT_META_H
|
||||
#define HB_OT_META_H
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* hb_ot_meta_tag_t:
|
||||
* @HB_OT_META_TAG_DESIGN_LANGUAGES: Design languages. Text, using only
|
||||
* Basic Latin (ASCII) characters. Indicates languages and/or scripts
|
||||
* for the user audiences that the font was primarily designed for.
|
||||
* @HB_OT_META_TAG_SUPPORTED_LANGUAGES: Supported languages. Text, using
|
||||
* only Basic Latin (ASCII) characters. Indicates languages and/or scripts
|
||||
* that the font is declared to be capable of supporting.
|
||||
*
|
||||
* Known metadata tags from https://docs.microsoft.com/en-us/typography/opentype/spec/meta
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
typedef enum {
|
||||
/*
|
||||
HB_OT_META_TAG_APPL = HB_TAG ('a','p','p','l'),
|
||||
HB_OT_META_TAG_BILD = HB_TAG ('b','i','l','d'),
|
||||
*/
|
||||
HB_OT_META_TAG_DESIGN_LANGUAGES = HB_TAG ('d','l','n','g'),
|
||||
HB_OT_META_TAG_SUPPORTED_LANGUAGES = HB_TAG ('s','l','n','g'),
|
||||
|
||||
_HB_OT_META_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_ot_meta_tag_t;
|
||||
|
||||
HB_EXTERN unsigned int
|
||||
hb_ot_meta_get_entry_tags (hb_face_t *face,
|
||||
unsigned int start_offset,
|
||||
unsigned int *entries_count, /* IN/OUT. May be NULL. */
|
||||
hb_ot_meta_tag_t *entries /* OUT. May be NULL. */);
|
||||
|
||||
HB_EXTERN hb_blob_t *
|
||||
hb_ot_meta_reference_entry (hb_face_t *face, hb_ot_meta_tag_t meta_tag);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_OT_META_H */
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Copyright © 2018-2019 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-ot-var-mvar-table.hh"
|
||||
#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-ot-os2-table.hh"
|
||||
#include "hb-ot-post-table.hh"
|
||||
#include "hb-ot-hhea-table.hh"
|
||||
#include "hb-ot-metrics.hh"
|
||||
#include "hb-ot-face.hh"
|
||||
|
||||
|
||||
static float
|
||||
_fix_ascender_descender (float value, hb_ot_metrics_tag_t metrics_tag)
|
||||
{
|
||||
if (metrics_tag == HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER ||
|
||||
metrics_tag == HB_OT_METRICS_TAG_VERTICAL_ASCENDER)
|
||||
return fabs ((double) value);
|
||||
if (metrics_tag == HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER ||
|
||||
metrics_tag == HB_OT_METRICS_TAG_VERTICAL_DESCENDER)
|
||||
return -fabs ((double) value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* The common part of _get_position logic needed on hb-ot-font and here
|
||||
to be able to have slim builds without the not always needed parts */
|
||||
bool
|
||||
_hb_ot_metrics_get_position_common (hb_font_t *font,
|
||||
hb_ot_metrics_tag_t metrics_tag,
|
||||
hb_position_t *position /* OUT. May be NULL. */)
|
||||
{
|
||||
hb_face_t *face = font->face;
|
||||
switch ((unsigned) metrics_tag)
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
#define GET_VAR face->table.MVAR->get_var (metrics_tag, font->coords, font->num_coords)
|
||||
#else
|
||||
#define GET_VAR .0f
|
||||
#endif
|
||||
#define GET_METRIC_X(TABLE, ATTR) \
|
||||
(face->table.TABLE->has_data () && \
|
||||
(position && (*position = font->em_scalef_x (_fix_ascender_descender ( \
|
||||
face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
|
||||
#define GET_METRIC_Y(TABLE, ATTR) \
|
||||
(face->table.TABLE->has_data () && \
|
||||
(position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
|
||||
face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
|
||||
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) ||
|
||||
GET_METRIC_Y (hhea, ascender);
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER:
|
||||
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoDescender)) ||
|
||||
GET_METRIC_Y (hhea, descender);
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP:
|
||||
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoLineGap)) ||
|
||||
GET_METRIC_Y (hhea, lineGap);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_ASCENDER: return GET_METRIC_X (vhea, ascender);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_DESCENDER: return GET_METRIC_X (vhea, descender);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP: return GET_METRIC_X (vhea, lineGap);
|
||||
#undef GET_METRIC_Y
|
||||
#undef GET_METRIC_X
|
||||
#undef GET_VAR
|
||||
default: assert (0); return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_METRICS
|
||||
|
||||
#if 0
|
||||
static bool
|
||||
_get_gasp (hb_face_t *face, float *result, hb_ot_metrics_tag_t metrics_tag)
|
||||
{
|
||||
const OT::GaspRange& range = face->table.gasp->get_gasp_range (metrics_tag - HB_TAG ('g','s','p','0'));
|
||||
if (&range == &Null (OT::GaspRange)) return false;
|
||||
if (result) *result = range.rangeMaxPPEM + font->face->table.MVAR->get_var (metrics_tag, font->coords, font->num_coords);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Private tags for https://github.com/harfbuzz/harfbuzz/issues/1866 */
|
||||
#define _HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER_OS2 HB_TAG ('O','a','s','c')
|
||||
#define _HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER_HHEA HB_TAG ('H','a','s','c')
|
||||
#define _HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER_OS2 HB_TAG ('O','d','s','c')
|
||||
#define _HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER_HHEA HB_TAG ('H','d','s','c')
|
||||
#define _HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP_OS2 HB_TAG ('O','l','g','p')
|
||||
#define _HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP_HHEA HB_TAG ('H','l','g','p')
|
||||
|
||||
/**
|
||||
* hb_ot_metrics_get_position:
|
||||
* @font: a #hb_font_t object.
|
||||
* @metrics_tag: tag of metrics value you like to fetch.
|
||||
* @position: (out) (optional): result of metrics value from the font.
|
||||
*
|
||||
* It fetches metrics value corresponding to a given tag from a font.
|
||||
*
|
||||
* Returns: Whether found the requested metrics in the font.
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
hb_bool_t
|
||||
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_face_t *face = font->face;
|
||||
switch ((unsigned) metrics_tag)
|
||||
{
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER:
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP:
|
||||
case HB_OT_METRICS_TAG_VERTICAL_ASCENDER:
|
||||
case HB_OT_METRICS_TAG_VERTICAL_DESCENDER:
|
||||
case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP: return _hb_ot_metrics_get_position_common (font, metrics_tag, position);
|
||||
#ifndef HB_NO_VAR
|
||||
#define GET_VAR hb_ot_metrics_get_variation (font, metrics_tag)
|
||||
#else
|
||||
#define GET_VAR 0
|
||||
#endif
|
||||
#define GET_METRIC_X(TABLE, ATTR) \
|
||||
(face->table.TABLE->has_data () && \
|
||||
(position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR)), true))
|
||||
#define GET_METRIC_Y(TABLE, ATTR) \
|
||||
(face->table.TABLE->has_data () && \
|
||||
(position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true))
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent);
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent);
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: return GET_METRIC_Y (hhea, caretSlopeRise);
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: return GET_METRIC_X (hhea, caretSlopeRun);
|
||||
case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET: return GET_METRIC_X (hhea, caretOffset);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE: return GET_METRIC_X (vhea, caretSlopeRise);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN: return GET_METRIC_Y (vhea, caretSlopeRun);
|
||||
case HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET: return GET_METRIC_Y (vhea, caretOffset);
|
||||
case HB_OT_METRICS_TAG_X_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sxHeight);
|
||||
case HB_OT_METRICS_TAG_CAP_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sCapHeight);
|
||||
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE: return GET_METRIC_X (OS2, ySubscriptXSize);
|
||||
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE: return GET_METRIC_Y (OS2, ySubscriptYSize);
|
||||
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET: return GET_METRIC_X (OS2, ySubscriptXOffset);
|
||||
case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET: return GET_METRIC_Y (OS2, ySubscriptYOffset);
|
||||
case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE: return GET_METRIC_X (OS2, ySuperscriptXSize);
|
||||
case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE: return GET_METRIC_Y (OS2, ySuperscriptYSize);
|
||||
case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET: return GET_METRIC_X (OS2, ySuperscriptXOffset);
|
||||
case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET: return GET_METRIC_Y (OS2, ySuperscriptYOffset);
|
||||
case HB_OT_METRICS_TAG_STRIKEOUT_SIZE: return GET_METRIC_Y (OS2, yStrikeoutSize);
|
||||
case HB_OT_METRICS_TAG_STRIKEOUT_OFFSET: return GET_METRIC_Y (OS2, yStrikeoutPosition);
|
||||
case HB_OT_METRICS_TAG_UNDERLINE_SIZE: return GET_METRIC_Y (post->table, underlineThickness);
|
||||
case HB_OT_METRICS_TAG_UNDERLINE_OFFSET: return GET_METRIC_Y (post->table, underlinePosition);
|
||||
|
||||
/* Private tags */
|
||||
case _HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER_OS2: return GET_METRIC_Y (OS2, sTypoAscender);
|
||||
case _HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER_HHEA: return GET_METRIC_Y (hhea, ascender);
|
||||
case _HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER_OS2: return GET_METRIC_Y (OS2, sTypoDescender);
|
||||
case _HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER_HHEA: return GET_METRIC_Y (hhea, descender);
|
||||
case _HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP_OS2: return GET_METRIC_Y (OS2, sTypoLineGap);
|
||||
case _HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP_HHEA: return GET_METRIC_Y (hhea, lineGap);
|
||||
#undef GET_METRIC_Y
|
||||
#undef GET_METRIC_X
|
||||
#undef GET_VAR
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
/**
|
||||
* hb_ot_metrics_get_variation:
|
||||
* @font:
|
||||
* @metrics_tag:
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
float
|
||||
hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
|
||||
{
|
||||
return font->face->table.MVAR->get_var (metrics_tag, font->coords, font->num_coords);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_metrics_get_x_variation:
|
||||
* @font:
|
||||
* @metrics_tag:
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
hb_position_t
|
||||
hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
|
||||
{
|
||||
return font->em_scalef_x (hb_ot_metrics_get_variation (font, metrics_tag));
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ot_metrics_get_y_variation:
|
||||
* @font:
|
||||
* @metrics_tag:
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
hb_position_t
|
||||
hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
|
||||
{
|
||||
return font->em_scalef_y (hb_ot_metrics_get_variation (font, metrics_tag));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_H_IN
|
||||
#error "Include <hb-ot.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef HB_OT_METRICS_H
|
||||
#define HB_OT_METRICS_H
|
||||
|
||||
#include "hb.h"
|
||||
#include "hb-ot-name.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
/**
|
||||
* hb_ot_metrics_tag_t:
|
||||
* @HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER: horizontal ascender.
|
||||
* @HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER: horizontal descender.
|
||||
* @HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP: horizontal line gap.
|
||||
* @HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: horizontal clipping ascent.
|
||||
* @HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: horizontal clipping descent.
|
||||
* @HB_OT_METRICS_TAG_VERTICAL_ASCENDER: vertical ascender.
|
||||
* @HB_OT_METRICS_TAG_VERTICAL_DESCENDER: vertical descender.
|
||||
* @HB_OT_METRICS_TAG_VERTICAL_LINE_GAP: vertical line gap.
|
||||
* @HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE: horizontal caret rise.
|
||||
* @HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN: horizontal caret run.
|
||||
* @HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET: horizontal caret offset.
|
||||
* @HB_OT_METRICS_TAG_VERTICAL_CARET_RISE: vertical caret rise.
|
||||
* @HB_OT_METRICS_TAG_VERTICAL_CARET_RUN: vertical caret run.
|
||||
* @HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET: vertical caret offset.
|
||||
* @HB_OT_METRICS_TAG_X_HEIGHT: x height.
|
||||
* @HB_OT_METRICS_TAG_CAP_HEIGHT: cap height.
|
||||
* @HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE: subscript em x size.
|
||||
* @HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE: subscript em y size.
|
||||
* @HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET: subscript em x offset.
|
||||
* @HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET: subscript em y offset.
|
||||
* @HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE: superscript em x size.
|
||||
* @HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE: superscript em y size.
|
||||
* @HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET: superscript em x offset.
|
||||
* @HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET: superscript em y offset.
|
||||
* @HB_OT_METRICS_TAG_STRIKEOUT_SIZE: strikeout size.
|
||||
* @HB_OT_METRICS_TAG_STRIKEOUT_OFFSET: strikeout offset.
|
||||
* @HB_OT_METRICS_TAG_UNDERLINE_SIZE: underline size.
|
||||
* @HB_OT_METRICS_TAG_UNDERLINE_OFFSET: underline offset.
|
||||
*
|
||||
* From https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags
|
||||
*
|
||||
* Since: 2.6.0
|
||||
**/
|
||||
typedef enum {
|
||||
HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER = HB_TAG ('h','a','s','c'),
|
||||
HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER = HB_TAG ('h','d','s','c'),
|
||||
HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP = HB_TAG ('h','l','g','p'),
|
||||
HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT = HB_TAG ('h','c','l','a'),
|
||||
HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT = HB_TAG ('h','c','l','d'),
|
||||
HB_OT_METRICS_TAG_VERTICAL_ASCENDER = HB_TAG ('v','a','s','c'),
|
||||
HB_OT_METRICS_TAG_VERTICAL_DESCENDER = HB_TAG ('v','d','s','c'),
|
||||
HB_OT_METRICS_TAG_VERTICAL_LINE_GAP = HB_TAG ('v','l','g','p'),
|
||||
HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE = HB_TAG ('h','c','r','s'),
|
||||
HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN = HB_TAG ('h','c','r','n'),
|
||||
HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET = HB_TAG ('h','c','o','f'),
|
||||
HB_OT_METRICS_TAG_VERTICAL_CARET_RISE = HB_TAG ('v','c','r','s'),
|
||||
HB_OT_METRICS_TAG_VERTICAL_CARET_RUN = HB_TAG ('v','c','r','n'),
|
||||
HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET = HB_TAG ('v','c','o','f'),
|
||||
HB_OT_METRICS_TAG_X_HEIGHT = HB_TAG ('x','h','g','t'),
|
||||
HB_OT_METRICS_TAG_CAP_HEIGHT = HB_TAG ('c','p','h','t'),
|
||||
HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE = HB_TAG ('s','b','x','s'),
|
||||
HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE = HB_TAG ('s','b','y','s'),
|
||||
HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET = HB_TAG ('s','b','x','o'),
|
||||
HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET = HB_TAG ('s','b','y','o'),
|
||||
HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE = HB_TAG ('s','p','x','s'),
|
||||
HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE = HB_TAG ('s','p','y','s'),
|
||||
HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET = HB_TAG ('s','p','x','o'),
|
||||
HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET = HB_TAG ('s','p','y','o'),
|
||||
HB_OT_METRICS_TAG_STRIKEOUT_SIZE = HB_TAG ('s','t','r','s'),
|
||||
HB_OT_METRICS_TAG_STRIKEOUT_OFFSET = HB_TAG ('s','t','r','o'),
|
||||
HB_OT_METRICS_TAG_UNDERLINE_SIZE = HB_TAG ('u','n','d','s'),
|
||||
HB_OT_METRICS_TAG_UNDERLINE_OFFSET = HB_TAG ('u','n','d','o'),
|
||||
|
||||
_HB_OT_METRICS_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_ot_metrics_tag_t;
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
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 float
|
||||
hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
|
||||
|
||||
HB_EXTERN hb_position_t
|
||||
hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
|
||||
|
||||
HB_EXTERN hb_position_t
|
||||
hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_OT_METRICS_H */
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_METRICS_HH
|
||||
#define HB_OT_METRICS_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
HB_INTERNAL bool
|
||||
_hb_ot_metrics_get_position_common (hb_font_t *font,
|
||||
hb_ot_metrics_tag_t metrics_tag,
|
||||
hb_position_t *position /* OUT. May be NULL. */);
|
||||
|
||||
#endif /* HB_OT_METRICS_HH */
|
|
@ -59,6 +59,10 @@ struct OS2V1Tail
|
|||
|
||||
struct OS2V2Tail
|
||||
{
|
||||
bool has_data () const { return sxHeight || sCapHeight; }
|
||||
|
||||
const OS2V2Tail * operator -> () const { return this; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -77,6 +81,23 @@ struct OS2V2Tail
|
|||
|
||||
struct OS2V5Tail
|
||||
{
|
||||
inline bool get_optical_size (unsigned int *lower, unsigned int *upper) const
|
||||
{
|
||||
unsigned int lower_optical_size = usLowerOpticalPointSize;
|
||||
unsigned int upper_optical_size = usUpperOpticalPointSize;
|
||||
|
||||
/* Per https://docs.microsoft.com/en-us/typography/opentype/spec/os2#lps */
|
||||
if (lower_optical_size < upper_optical_size &&
|
||||
lower_optical_size >= 1 && lower_optical_size <= 0xFFFE &&
|
||||
upper_optical_size >= 2 && upper_optical_size <= 0xFFFF)
|
||||
{
|
||||
*lower = lower_optical_size;
|
||||
*upper = upper_optical_size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -94,7 +115,7 @@ struct OS2
|
|||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_OS2;
|
||||
|
||||
bool has_data () const { return this != &Null (OS2); }
|
||||
bool has_data () const { return usWeightClass || usWidthClass || usFirstCharIndex || usLastCharIndex; }
|
||||
|
||||
const OS2V1Tail &v1 () const { return version >= 1 ? v1X : Null (OS2V1Tail); }
|
||||
const OS2V2Tail &v2 () const { return version >= 2 ? v2X : Null (OS2V2Tail); }
|
||||
|
@ -113,9 +134,9 @@ struct OS2
|
|||
OBLIQUE = 1u<<9
|
||||
};
|
||||
|
||||
bool is_italic () const { return fsSelection & ITALIC; }
|
||||
bool is_oblique () const { return fsSelection & OBLIQUE; }
|
||||
bool is_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
|
||||
bool is_italic () const { return fsSelection & ITALIC; }
|
||||
bool is_oblique () const { return fsSelection & OBLIQUE; }
|
||||
bool use_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
|
||||
|
||||
enum width_class_t {
|
||||
FWIDTH_ULTRA_CONDENSED = 1, /* 50% */
|
||||
|
@ -192,13 +213,14 @@ struct OS2
|
|||
}
|
||||
|
||||
static void find_min_and_max_codepoint (const hb_set_t *codepoints,
|
||||
uint16_t *min_cp, /* OUT */
|
||||
uint16_t *max_cp /* OUT */)
|
||||
uint16_t *min_cp, /* OUT */
|
||||
uint16_t *max_cp /* OUT */)
|
||||
{
|
||||
*min_cp = codepoints->get_min ();
|
||||
*max_cp = codepoints->get_max ();
|
||||
}
|
||||
|
||||
/* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 */
|
||||
enum font_page_t {
|
||||
HEBREW_FONT_PAGE = 0xB100, // Hebrew Windows 3.1 font page
|
||||
SIMP_ARABIC_FONT_PAGE = 0xB200, // Simplified Arabic Windows 3.1 font page
|
||||
|
@ -208,8 +230,6 @@ struct OS2
|
|||
TRAD_FARSI_FONT_PAGE = 0xBB00, // Traditional Farsi Windows 3.1 font page
|
||||
THAI_FONT_PAGE = 0xDE00 // Thai Windows 3.1 font page
|
||||
};
|
||||
|
||||
// https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
|
||||
font_page_t get_font_page () const
|
||||
{ return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }
|
||||
|
||||
|
|
|
@ -178,6 +178,8 @@ struct post
|
|||
return false;
|
||||
}
|
||||
|
||||
hb_blob_ptr_t<post> table;
|
||||
|
||||
protected:
|
||||
|
||||
unsigned int get_glyph_count () const
|
||||
|
@ -237,7 +239,6 @@ struct post
|
|||
}
|
||||
|
||||
private:
|
||||
hb_blob_ptr_t<post> table;
|
||||
uint32_t version;
|
||||
const ArrayOf<HBUINT16> *glyphNameIndex;
|
||||
hb_vector_t<uint32_t> index_to_offset;
|
||||
|
@ -245,6 +246,8 @@ struct post
|
|||
hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
|
||||
};
|
||||
|
||||
bool has_data () const { return version.to_int (); }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex-arabic.hh"
|
||||
#include "hb-ot-shape.hh"
|
||||
|
||||
|
@ -710,3 +713,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
|
|||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
|
||||
true, /* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex.hh"
|
||||
|
||||
|
||||
|
@ -44,3 +48,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
|
|||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
|
||||
true, /* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex.hh"
|
||||
|
||||
|
||||
|
@ -430,3 +434,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
|
|||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
|
||||
false, /* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex.hh"
|
||||
|
||||
|
||||
|
@ -176,3 +180,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
|
|||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
|
||||
true, /* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -395,13 +395,13 @@ static const int indic_syllable_machine_en_main = 39;
|
|||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
info[i].syllable() = (syllable_serial << 4) | indic_##syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables (hb_buffer_t *buffer)
|
||||
find_syllables_indic (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act;
|
||||
int cs;
|
||||
|
@ -569,4 +569,6 @@ _again:
|
|||
|
||||
}
|
||||
|
||||
#undef found_syllable
|
||||
|
||||
#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
|
||||
|
|
|
@ -96,13 +96,13 @@ main := |*
|
|||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
info[i].syllable() = (syllable_serial << 4) | indic_##syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables (hb_buffer_t *buffer)
|
||||
find_syllables_indic (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act;
|
||||
int cs;
|
||||
|
@ -121,4 +121,6 @@ find_syllables (hb_buffer_t *buffer)
|
|||
}%%
|
||||
}
|
||||
|
||||
#undef found_syllable
|
||||
|
||||
#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
* # Date: 2018-07-30, 19:40:00 GMT [KW]
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex-indic.hh"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -487,4 +491,6 @@ hb_indic_get_categories (hb_codepoint_t u)
|
|||
#undef IMC_TR
|
||||
#undef IMC_VOL
|
||||
|
||||
|
||||
#endif
|
||||
/* == End of generated table == */
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex-indic.hh"
|
||||
#include "hb-ot-shape-complex-vowel-constraints.hh"
|
||||
#include "hb-ot-layout.hh"
|
||||
|
@ -140,49 +144,45 @@ indic_features[] =
|
|||
* Must be in the same order as the indic_features array.
|
||||
*/
|
||||
enum {
|
||||
_NUKT,
|
||||
_AKHN,
|
||||
RPHF,
|
||||
_RKRF,
|
||||
PREF,
|
||||
BLWF,
|
||||
ABVF,
|
||||
HALF,
|
||||
PSTF,
|
||||
_VATU,
|
||||
_CJCT,
|
||||
_INDIC_NUKT,
|
||||
_INDIC_AKHN,
|
||||
INDIC_RPHF,
|
||||
_INDIC_RKRF,
|
||||
INDIC_PREF,
|
||||
INDIC_BLWF,
|
||||
INDIC_ABVF,
|
||||
INDIC_HALF,
|
||||
INDIC_PSTF,
|
||||
_INDIC_VATU,
|
||||
_INDIC_CJCT,
|
||||
|
||||
INIT,
|
||||
_PRES,
|
||||
_ABVS,
|
||||
_BLWS,
|
||||
_PSTS,
|
||||
_HALN,
|
||||
INDIC_INIT,
|
||||
_INDIC_PRES,
|
||||
_INDIC_ABVS,
|
||||
_INDIC_BLWS,
|
||||
_INDIC_PSTS,
|
||||
_INDIC_HALN,
|
||||
|
||||
_DIST,
|
||||
_ABVM,
|
||||
_BLWM,
|
||||
_INDIC_DIST,
|
||||
_INDIC_ABVM,
|
||||
_INDIC_BLWM,
|
||||
|
||||
INDIC_NUM_FEATURES,
|
||||
INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */
|
||||
INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
|
||||
};
|
||||
|
||||
static void
|
||||
setup_syllables (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
setup_syllables_indic (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
initial_reordering (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
initial_reordering_indic (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
final_reordering (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
clear_syllables (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
final_reordering_indic (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
static void
|
||||
collect_features_indic (hb_ot_shape_planner_t *plan)
|
||||
|
@ -190,7 +190,7 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
|
|||
hb_ot_map_builder_t *map = &plan->map;
|
||||
|
||||
/* Do this before any lookups have been applied. */
|
||||
map->add_gsub_pause (setup_syllables);
|
||||
map->add_gsub_pause (setup_syllables_indic);
|
||||
|
||||
map->enable_feature (HB_TAG('l','o','c','l'));
|
||||
/* The Indic specs do not require ccmp, but we apply it here since if
|
||||
|
@ -199,14 +199,14 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
|
|||
|
||||
|
||||
unsigned int i = 0;
|
||||
map->add_gsub_pause (initial_reordering);
|
||||
map->add_gsub_pause (initial_reordering_indic);
|
||||
|
||||
for (; i < INDIC_BASIC_FEATURES; i++) {
|
||||
map->add_feature (indic_features[i]);
|
||||
map->add_gsub_pause (nullptr);
|
||||
}
|
||||
|
||||
map->add_gsub_pause (final_reordering);
|
||||
map->add_gsub_pause (final_reordering_indic);
|
||||
|
||||
for (; i < INDIC_NUM_FEATURES; i++)
|
||||
map->add_feature (indic_features[i]);
|
||||
|
@ -214,7 +214,7 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
|
|||
map->enable_feature (HB_TAG('c','a','l','t'));
|
||||
map->enable_feature (HB_TAG('c','l','i','g'));
|
||||
|
||||
map->add_gsub_pause (clear_syllables);
|
||||
map->add_gsub_pause (_hb_clear_syllables);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -224,32 +224,6 @@ override_features_indic (hb_ot_shape_planner_t *plan)
|
|||
}
|
||||
|
||||
|
||||
struct would_substitute_feature_t
|
||||
{
|
||||
void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
|
||||
{
|
||||
zero_context = zero_context_;
|
||||
map->get_stage_lookups (0/*GSUB*/,
|
||||
map->get_feature_stage (0/*GSUB*/, feature_tag),
|
||||
&lookups, &count);
|
||||
}
|
||||
|
||||
bool would_substitute (const hb_codepoint_t *glyphs,
|
||||
unsigned int glyphs_count,
|
||||
hb_face_t *face) const
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
const hb_ot_map_t::lookup_map_t *lookups;
|
||||
unsigned int count;
|
||||
bool zero_context;
|
||||
};
|
||||
|
||||
struct indic_shape_plan_t
|
||||
{
|
||||
bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
|
||||
|
@ -281,10 +255,10 @@ struct indic_shape_plan_t
|
|||
#endif
|
||||
mutable hb_atomic_int_t virama_glyph;
|
||||
|
||||
would_substitute_feature_t rphf;
|
||||
would_substitute_feature_t pref;
|
||||
would_substitute_feature_t blwf;
|
||||
would_substitute_feature_t pstf;
|
||||
hb_indic_would_substitute_feature_t rphf;
|
||||
hb_indic_would_substitute_feature_t pref;
|
||||
hb_indic_would_substitute_feature_t blwf;
|
||||
hb_indic_would_substitute_feature_t pstf;
|
||||
|
||||
hb_mask_t mask_array[INDIC_NUM_FEATURES];
|
||||
};
|
||||
|
@ -367,13 +341,13 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan,
|
|||
}
|
||||
|
||||
|
||||
enum syllable_type_t {
|
||||
consonant_syllable,
|
||||
vowel_syllable,
|
||||
standalone_cluster,
|
||||
symbol_cluster,
|
||||
broken_cluster,
|
||||
non_indic_cluster,
|
||||
enum indic_syllable_type_t {
|
||||
indic_consonant_syllable,
|
||||
indic_vowel_syllable,
|
||||
indic_standalone_cluster,
|
||||
indic_symbol_cluster,
|
||||
indic_broken_cluster,
|
||||
indic_non_indic_cluster,
|
||||
};
|
||||
|
||||
#include "hb-ot-shape-complex-indic-machine.hh"
|
||||
|
@ -397,11 +371,11 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
|
||||
static void
|
||||
setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
find_syllables (buffer);
|
||||
find_syllables_indic (buffer);
|
||||
foreach_syllable (buffer, start, end)
|
||||
buffer->unsafe_to_break (start, end);
|
||||
}
|
||||
|
@ -418,9 +392,9 @@ compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
|
|||
|
||||
|
||||
static void
|
||||
update_consonant_positions (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
update_consonant_positions_indic (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
|
||||
|
||||
|
@ -493,7 +467,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
* and has more than one consonant, Ra is excluded from candidates for
|
||||
* base consonants. */
|
||||
unsigned int limit = start;
|
||||
if (indic_plan->mask_array[RPHF] &&
|
||||
if (indic_plan->mask_array[INDIC_RPHF] &&
|
||||
start + 3 <= end &&
|
||||
(
|
||||
(indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) ||
|
||||
|
@ -829,13 +803,13 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
|
||||
/* Reph */
|
||||
for (unsigned int i = start; i < end && info[i].indic_position() == POS_RA_TO_BECOME_REPH; i++)
|
||||
info[i].mask |= indic_plan->mask_array[RPHF];
|
||||
info[i].mask |= indic_plan->mask_array[INDIC_RPHF];
|
||||
|
||||
/* Pre-base */
|
||||
mask = indic_plan->mask_array[HALF];
|
||||
mask = indic_plan->mask_array[INDIC_HALF];
|
||||
if (!indic_plan->is_old_spec &&
|
||||
indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST)
|
||||
mask |= indic_plan->mask_array[BLWF];
|
||||
mask |= indic_plan->mask_array[INDIC_BLWF];
|
||||
for (unsigned int i = start; i < base; i++)
|
||||
info[i].mask |= mask;
|
||||
/* Base */
|
||||
|
@ -843,7 +817,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
if (base < end)
|
||||
info[base].mask |= mask;
|
||||
/* Post-base */
|
||||
mask = indic_plan->mask_array[BLWF] | indic_plan->mask_array[ABVF] | indic_plan->mask_array[PSTF];
|
||||
mask = indic_plan->mask_array[INDIC_BLWF] |
|
||||
indic_plan->mask_array[INDIC_ABVF] |
|
||||
indic_plan->mask_array[INDIC_PSTF];
|
||||
for (unsigned int i = base + 1; i < end; i++)
|
||||
info[i].mask |= mask;
|
||||
}
|
||||
|
@ -875,13 +851,13 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
(i + 2 == base ||
|
||||
info[i+2].indic_category() != OT_ZWJ))
|
||||
{
|
||||
info[i ].mask |= indic_plan->mask_array[BLWF];
|
||||
info[i+1].mask |= indic_plan->mask_array[BLWF];
|
||||
info[i ].mask |= indic_plan->mask_array[INDIC_BLWF];
|
||||
info[i+1].mask |= indic_plan->mask_array[INDIC_BLWF];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int pref_len = 2;
|
||||
if (indic_plan->mask_array[PREF] && base + pref_len < end)
|
||||
if (indic_plan->mask_array[INDIC_PREF] && base + pref_len < end)
|
||||
{
|
||||
/* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
|
||||
for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
|
||||
|
@ -891,7 +867,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
if (indic_plan->pref.would_substitute (glyphs, pref_len, face))
|
||||
{
|
||||
for (unsigned int j = 0; j < pref_len; j++)
|
||||
info[i++].mask |= indic_plan->mask_array[PREF];
|
||||
info[i++].mask |= indic_plan->mask_array[INDIC_PREF];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -912,7 +888,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
|
||||
/* A ZWNJ disables HALF. */
|
||||
if (non_joiner)
|
||||
info[j].mask &= ~indic_plan->mask_array[HALF];
|
||||
info[j].mask &= ~indic_plan->mask_array[INDIC_HALF];
|
||||
|
||||
} while (j > start && !is_consonant (info[j]));
|
||||
}
|
||||
|
@ -941,34 +917,34 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
|
|||
}
|
||||
|
||||
static void
|
||||
initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
hb_face_t *face,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start, unsigned int end)
|
||||
initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
|
||||
hb_face_t *face,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start, unsigned int end)
|
||||
{
|
||||
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
|
||||
indic_syllable_type_t syllable_type = (indic_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
|
||||
switch (syllable_type)
|
||||
{
|
||||
case vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */
|
||||
case consonant_syllable:
|
||||
case indic_vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */
|
||||
case indic_consonant_syllable:
|
||||
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
|
||||
break;
|
||||
|
||||
case broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
|
||||
case standalone_cluster:
|
||||
case indic_broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
|
||||
case indic_standalone_cluster:
|
||||
initial_reordering_standalone_cluster (plan, face, buffer, start, end);
|
||||
break;
|
||||
|
||||
case symbol_cluster:
|
||||
case non_indic_cluster:
|
||||
case indic_symbol_cluster:
|
||||
case indic_non_indic_cluster:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
insert_dotted_circles_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
|
||||
return;
|
||||
|
@ -979,7 +955,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if ((info[i].syllable() & 0x0F) == broken_cluster)
|
||||
if ((info[i].syllable() & 0x0F) == indic_broken_cluster)
|
||||
{
|
||||
has_broken_syllables = true;
|
||||
break;
|
||||
|
@ -1004,8 +980,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
while (buffer->idx < buffer->len && buffer->successful)
|
||||
{
|
||||
unsigned int syllable = buffer->cur().syllable();
|
||||
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
|
||||
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
|
||||
indic_syllable_type_t syllable_type = (indic_syllable_type_t) (syllable & 0x0F);
|
||||
if (unlikely (last_syllable != syllable && syllable_type == indic_broken_cluster))
|
||||
{
|
||||
last_syllable = syllable;
|
||||
|
||||
|
@ -1029,21 +1005,21 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
|
||||
static void
|
||||
initial_reordering (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
initial_reordering_indic (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
update_consonant_positions (plan, font, buffer);
|
||||
insert_dotted_circles (plan, font, buffer);
|
||||
update_consonant_positions_indic (plan, font, buffer);
|
||||
insert_dotted_circles_indic (plan, font, buffer);
|
||||
|
||||
foreach_syllable (buffer, start, end)
|
||||
initial_reordering_syllable (plan, font->face, buffer, start, end);
|
||||
initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
|
||||
}
|
||||
|
||||
static void
|
||||
final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start, unsigned int end)
|
||||
final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start, unsigned int end)
|
||||
{
|
||||
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
@ -1079,7 +1055,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
|||
* syllable.
|
||||
*/
|
||||
|
||||
bool try_pref = !!indic_plan->mask_array[PREF];
|
||||
bool try_pref = !!indic_plan->mask_array[INDIC_PREF];
|
||||
|
||||
/* Find base again */
|
||||
unsigned int base;
|
||||
|
@ -1089,7 +1065,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
|||
if (try_pref && base + 1 < end)
|
||||
{
|
||||
for (unsigned int i = base + 1; i < end; i++)
|
||||
if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
|
||||
if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
|
||||
{
|
||||
if (!(_hb_glyph_info_substituted (&info[i]) &&
|
||||
_hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
|
||||
|
@ -1411,7 +1387,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
|||
if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
|
||||
{
|
||||
for (unsigned int i = base + 1; i < end; i++)
|
||||
if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
|
||||
if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
|
||||
{
|
||||
/* 1. Only reorder a glyph produced by substitution during application
|
||||
* of the <pref> feature. (Note that a font may shape a Ra consonant with
|
||||
|
@ -1474,7 +1450,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
|||
if (!start ||
|
||||
!(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) &
|
||||
FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
|
||||
info[start].mask |= indic_plan->mask_array[INIT];
|
||||
info[start].mask |= indic_plan->mask_array[INDIC_INIT];
|
||||
else
|
||||
buffer->unsafe_to_break (start - 1, start + 1);
|
||||
}
|
||||
|
@ -1504,33 +1480,21 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
|||
|
||||
|
||||
static void
|
||||
final_reordering (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
final_reordering_indic (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
if (unlikely (!count)) return;
|
||||
|
||||
foreach_syllable (buffer, start, end)
|
||||
final_reordering_syllable (plan, buffer, start, end);
|
||||
final_reordering_syllable_indic (plan, buffer, start, end);
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
info[i].syllable() = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
preprocess_text_indic (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
|
@ -1648,3 +1612,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
|
|||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
|
||||
false, /* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -64,7 +64,14 @@ enum indic_category_t {
|
|||
OT_Ra = 16,
|
||||
OT_CM = 17, /* Consonant-Medial. */
|
||||
OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
|
||||
OT_CS = 19
|
||||
OT_CS = 19,
|
||||
|
||||
/* The following are used by Khmer & Myanmar shapers. Defined
|
||||
* here for them to share. */
|
||||
OT_VAbv = 26,
|
||||
OT_VBlw = 27,
|
||||
OT_VPre = 28,
|
||||
OT_VPst = 29,
|
||||
};
|
||||
|
||||
#define MEDIAL_FLAGS (FLAG (OT_CM))
|
||||
|
@ -398,5 +405,31 @@ set_indic_properties (hb_glyph_info_t &info)
|
|||
info.indic_position() = pos;
|
||||
}
|
||||
|
||||
struct hb_indic_would_substitute_feature_t
|
||||
{
|
||||
void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
|
||||
{
|
||||
zero_context = zero_context_;
|
||||
map->get_stage_lookups (0/*GSUB*/,
|
||||
map->get_feature_stage (0/*GSUB*/, feature_tag),
|
||||
&lookups, &count);
|
||||
}
|
||||
|
||||
bool would_substitute (const hb_codepoint_t *glyphs,
|
||||
unsigned int glyphs_count,
|
||||
hb_face_t *face) const
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
const hb_ot_map_t::lookup_map_t *lookups;
|
||||
unsigned int count;
|
||||
bool zero_context;
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_OT_SHAPE_COMPLEX_INDIC_HH */
|
||||
|
|
|
@ -226,13 +226,13 @@ static const int khmer_syllable_machine_en_main = 20;
|
|||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables (hb_buffer_t *buffer)
|
||||
find_syllables_khmer (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
|
||||
int cs;
|
||||
|
@ -367,4 +367,6 @@ _again:
|
|||
|
||||
}
|
||||
|
||||
#undef found_syllable
|
||||
|
||||
#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */
|
||||
|
|
|
@ -83,13 +83,13 @@ main := |*
|
|||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables (hb_buffer_t *buffer)
|
||||
find_syllables_khmer (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
|
||||
int cs;
|
||||
|
@ -108,4 +108,6 @@ find_syllables (hb_buffer_t *buffer)
|
|||
}%%
|
||||
}
|
||||
|
||||
#undef found_syllable
|
||||
|
||||
#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex-khmer.hh"
|
||||
#include "hb-ot-layout.hh"
|
||||
|
||||
|
@ -65,37 +69,33 @@ khmer_features[] =
|
|||
* Must be in the same order as the khmer_features array.
|
||||
*/
|
||||
enum {
|
||||
PREF,
|
||||
BLWF,
|
||||
ABVF,
|
||||
PSTF,
|
||||
CFAR,
|
||||
KHMER_PREF,
|
||||
KHMER_BLWF,
|
||||
KHMER_ABVF,
|
||||
KHMER_PSTF,
|
||||
KHMER_CFAR,
|
||||
|
||||
_PRES,
|
||||
_ABVS,
|
||||
_BLWS,
|
||||
_PSTS,
|
||||
_KHMER_PRES,
|
||||
_KHMER_ABVS,
|
||||
_KHMER_BLWS,
|
||||
_KHMER_PSTS,
|
||||
|
||||
_DIST,
|
||||
_ABVM,
|
||||
_BLWM,
|
||||
_KHMER_DIST,
|
||||
_KHMER_ABVM,
|
||||
_KHMER_BLWM,
|
||||
|
||||
KHMER_NUM_FEATURES,
|
||||
KHMER_BASIC_FEATURES = _PRES, /* Don't forget to update this! */
|
||||
KHMER_BASIC_FEATURES = _KHMER_PRES, /* Don't forget to update this! */
|
||||
};
|
||||
|
||||
static void
|
||||
setup_syllables (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
setup_syllables_khmer (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
reorder (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
clear_syllables (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
reorder_khmer (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
static void
|
||||
collect_features_khmer (hb_ot_shape_planner_t *plan)
|
||||
|
@ -103,8 +103,8 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
|
|||
hb_ot_map_builder_t *map = &plan->map;
|
||||
|
||||
/* Do this before any lookups have been applied. */
|
||||
map->add_gsub_pause (setup_syllables);
|
||||
map->add_gsub_pause (reorder);
|
||||
map->add_gsub_pause (setup_syllables_khmer);
|
||||
map->add_gsub_pause (reorder_khmer);
|
||||
|
||||
/* Testing suggests that Uniscribe does NOT pause between basic
|
||||
* features. Test with KhmerUI.ttf and the following three
|
||||
|
@ -123,7 +123,7 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
|
|||
for (; i < KHMER_BASIC_FEATURES; i++)
|
||||
map->add_feature (khmer_features[i]);
|
||||
|
||||
map->add_gsub_pause (clear_syllables);
|
||||
map->add_gsub_pause (_hb_clear_syllables);
|
||||
|
||||
for (; i < KHMER_NUM_FEATURES; i++)
|
||||
map->add_feature (khmer_features[i]);
|
||||
|
@ -149,32 +149,6 @@ override_features_khmer (hb_ot_shape_planner_t *plan)
|
|||
}
|
||||
|
||||
|
||||
struct would_substitute_feature_t
|
||||
{
|
||||
void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
|
||||
{
|
||||
zero_context = zero_context_;
|
||||
map->get_stage_lookups (0/*GSUB*/,
|
||||
map->get_feature_stage (0/*GSUB*/, feature_tag),
|
||||
&lookups, &count);
|
||||
}
|
||||
|
||||
bool would_substitute (const hb_codepoint_t *glyphs,
|
||||
unsigned int glyphs_count,
|
||||
hb_face_t *face) const
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
const hb_ot_map_t::lookup_map_t *lookups;
|
||||
unsigned int count;
|
||||
bool zero_context;
|
||||
};
|
||||
|
||||
struct khmer_shape_plan_t
|
||||
{
|
||||
bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
|
||||
|
@ -198,7 +172,7 @@ struct khmer_shape_plan_t
|
|||
|
||||
mutable hb_codepoint_t virama_glyph;
|
||||
|
||||
would_substitute_feature_t pref;
|
||||
hb_indic_would_substitute_feature_t pref;
|
||||
|
||||
hb_mask_t mask_array[KHMER_NUM_FEATURES];
|
||||
};
|
||||
|
@ -228,10 +202,10 @@ data_destroy_khmer (void *data)
|
|||
}
|
||||
|
||||
|
||||
enum syllable_type_t {
|
||||
consonant_syllable,
|
||||
broken_cluster,
|
||||
non_khmer_cluster,
|
||||
enum khmer_syllable_type_t {
|
||||
khmer_consonant_syllable,
|
||||
khmer_broken_cluster,
|
||||
khmer_non_khmer_cluster,
|
||||
};
|
||||
|
||||
#include "hb-ot-shape-complex-khmer-machine.hh"
|
||||
|
@ -253,11 +227,11 @@ setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
|
||||
static void
|
||||
setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
find_syllables (buffer);
|
||||
find_syllables_khmer (buffer);
|
||||
foreach_syllable (buffer, start, end)
|
||||
buffer->unsafe_to_break (start, end);
|
||||
}
|
||||
|
@ -278,7 +252,9 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
/* Setup masks. */
|
||||
{
|
||||
/* Post-base */
|
||||
hb_mask_t mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
|
||||
hb_mask_t mask = khmer_plan->mask_array[KHMER_BLWF] |
|
||||
khmer_plan->mask_array[KHMER_ABVF] |
|
||||
khmer_plan->mask_array[KHMER_PSTF];
|
||||
for (unsigned int i = start + 1; i < end; i++)
|
||||
info[i].mask |= mask;
|
||||
}
|
||||
|
@ -305,7 +281,7 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
if (info[i + 1].khmer_category() == OT_Ra)
|
||||
{
|
||||
for (unsigned int j = 0; j < 2; j++)
|
||||
info[i + j].mask |= khmer_plan->mask_array[PREF];
|
||||
info[i + j].mask |= khmer_plan->mask_array[KHMER_PREF];
|
||||
|
||||
/* Move the Coeng,Ro sequence to the start. */
|
||||
buffer->merge_clusters (start, i + 2);
|
||||
|
@ -321,9 +297,9 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
* U+1784,U+17D2,U+179A,U+17D2,U+1782
|
||||
* U+1784,U+17D2,U+1782,U+17D2,U+179A
|
||||
*/
|
||||
if (khmer_plan->mask_array[CFAR])
|
||||
if (khmer_plan->mask_array[KHMER_CFAR])
|
||||
for (unsigned int j = i + 2; j < end; j++)
|
||||
info[j].mask |= khmer_plan->mask_array[CFAR];
|
||||
info[j].mask |= khmer_plan->mask_array[KHMER_CFAR];
|
||||
|
||||
num_coengs = 2; /* Done. */
|
||||
}
|
||||
|
@ -342,28 +318,28 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
}
|
||||
|
||||
static void
|
||||
initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
|
||||
hb_face_t *face,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start, unsigned int end)
|
||||
reorder_syllable_khmer (const hb_ot_shape_plan_t *plan,
|
||||
hb_face_t *face,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start, unsigned int end)
|
||||
{
|
||||
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
|
||||
khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
|
||||
switch (syllable_type)
|
||||
{
|
||||
case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
|
||||
case consonant_syllable:
|
||||
case khmer_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
|
||||
case khmer_consonant_syllable:
|
||||
reorder_consonant_syllable (plan, face, buffer, start, end);
|
||||
break;
|
||||
|
||||
case non_khmer_cluster:
|
||||
case khmer_non_khmer_cluster:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
insert_dotted_circles_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
|
||||
return;
|
||||
|
@ -374,7 +350,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if ((info[i].syllable() & 0x0F) == broken_cluster)
|
||||
if ((info[i].syllable() & 0x0F) == khmer_broken_cluster)
|
||||
{
|
||||
has_broken_syllables = true;
|
||||
break;
|
||||
|
@ -399,8 +375,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
while (buffer->idx < buffer->len && buffer->successful)
|
||||
{
|
||||
unsigned int syllable = buffer->cur().syllable();
|
||||
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
|
||||
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
|
||||
khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (syllable & 0x0F);
|
||||
if (unlikely (last_syllable != syllable && syllable_type == khmer_broken_cluster))
|
||||
{
|
||||
last_syllable = syllable;
|
||||
|
||||
|
@ -424,29 +400,18 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
|
||||
static void
|
||||
reorder (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
reorder_khmer (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
insert_dotted_circles (plan, font, buffer);
|
||||
insert_dotted_circles_khmer (plan, font, buffer);
|
||||
|
||||
foreach_syllable (buffer, start, end)
|
||||
initial_reordering_syllable (plan, font->face, buffer, start, end);
|
||||
reorder_syllable_khmer (plan, font->face, buffer, start, end);
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
info[i].syllable() = 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
decompose_khmer (const hb_ot_shape_normalize_context_t *c,
|
||||
|
@ -502,3 +467,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_khmer =
|
|||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
|
||||
false, /* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,11 +43,10 @@ enum khmer_category_t
|
|||
OT_Robatic = 20,
|
||||
OT_Xgroup = 21,
|
||||
OT_Ygroup = 22,
|
||||
|
||||
OT_VAbv = 26,
|
||||
OT_VBlw = 27,
|
||||
OT_VPre = 28,
|
||||
OT_VPst = 29,
|
||||
//OT_VAbv = 26,
|
||||
//OT_VBlw = 27,
|
||||
//OT_VPre = 28,
|
||||
//OT_VPst = 29,
|
||||
};
|
||||
|
||||
static inline void
|
||||
|
@ -100,10 +99,10 @@ set_khmer_properties (hb_glyph_info_t &info)
|
|||
if (cat == (khmer_category_t) OT_M)
|
||||
switch ((int) pos)
|
||||
{
|
||||
case POS_PRE_C: cat = OT_VPre; break;
|
||||
case POS_BELOW_C: cat = OT_VBlw; break;
|
||||
case POS_ABOVE_C: cat = OT_VAbv; break;
|
||||
case POS_POST_C: cat = OT_VPst; break;
|
||||
case POS_PRE_C: cat = (khmer_category_t) OT_VPre; break;
|
||||
case POS_BELOW_C: cat = (khmer_category_t) OT_VBlw; break;
|
||||
case POS_ABOVE_C: cat = (khmer_category_t) OT_VAbv; break;
|
||||
case POS_POST_C: cat = (khmer_category_t) OT_VPst; break;
|
||||
default: assert (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -304,13 +304,13 @@ static const int myanmar_syllable_machine_en_main = 0;
|
|||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
info[i].syllable() = (syllable_serial << 4) | myanmar_##syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables (hb_buffer_t *buffer)
|
||||
find_syllables_myanmar (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
|
||||
int cs;
|
||||
|
|
|
@ -97,13 +97,13 @@ main := |*
|
|||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
info[i].syllable() = (syllable_serial << 4) | myanmar_##syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables (hb_buffer_t *buffer)
|
||||
find_syllables_myanmar (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
|
||||
int cs;
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex-myanmar.hh"
|
||||
|
||||
|
||||
|
@ -32,7 +36,7 @@
|
|||
*/
|
||||
|
||||
static const hb_tag_t
|
||||
basic_features[] =
|
||||
myanmar_basic_features[] =
|
||||
{
|
||||
/*
|
||||
* Basic features.
|
||||
|
@ -44,7 +48,7 @@ basic_features[] =
|
|||
HB_TAG('p','s','t','f'),
|
||||
};
|
||||
static const hb_tag_t
|
||||
other_features[] =
|
||||
myanmar_other_features[] =
|
||||
{
|
||||
/*
|
||||
* Other features.
|
||||
|
@ -56,7 +60,7 @@ other_features[] =
|
|||
HB_TAG('p','s','t','s'),
|
||||
};
|
||||
static const hb_tag_t
|
||||
positioning_features[] =
|
||||
myanmar_positioning_features[] =
|
||||
{
|
||||
/*
|
||||
* Positioning features.
|
||||
|
@ -76,15 +80,11 @@ positioning_features[] =
|
|||
};
|
||||
|
||||
static void
|
||||
setup_syllables (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
reorder (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
clear_syllables (const hb_ot_shape_plan_t *plan,
|
||||
reorder_myanmar (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
|
@ -94,7 +94,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
|
|||
hb_ot_map_builder_t *map = &plan->map;
|
||||
|
||||
/* Do this before any lookups have been applied. */
|
||||
map->add_gsub_pause (setup_syllables);
|
||||
map->add_gsub_pause (setup_syllables_myanmar);
|
||||
|
||||
map->enable_feature (HB_TAG('l','o','c','l'));
|
||||
/* The Indic specs do not require ccmp, but we apply it here since if
|
||||
|
@ -102,21 +102,21 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
|
|||
map->enable_feature (HB_TAG('c','c','m','p'));
|
||||
|
||||
|
||||
map->add_gsub_pause (reorder);
|
||||
map->add_gsub_pause (reorder_myanmar);
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_basic_features); i++)
|
||||
{
|
||||
map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
|
||||
map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ);
|
||||
map->add_gsub_pause (nullptr);
|
||||
}
|
||||
|
||||
map->add_gsub_pause (clear_syllables);
|
||||
map->add_gsub_pause (_hb_clear_syllables);
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
|
||||
map->enable_feature (other_features[i], F_MANUAL_ZWJ);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
|
||||
map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
|
||||
map->enable_feature (positioning_features[i]);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_positioning_features); i++)
|
||||
map->enable_feature (myanmar_positioning_features[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -126,11 +126,11 @@ override_features_myanmar (hb_ot_shape_planner_t *plan)
|
|||
}
|
||||
|
||||
|
||||
enum syllable_type_t {
|
||||
consonant_syllable,
|
||||
punctuation_cluster,
|
||||
broken_cluster,
|
||||
non_myanmar_cluster,
|
||||
enum myanmar_syllable_type_t {
|
||||
myanmar_consonant_syllable,
|
||||
myanmar_punctuation_cluster,
|
||||
myanmar_broken_cluster,
|
||||
myanmar_non_myanmar_cluster,
|
||||
};
|
||||
|
||||
#include "hb-ot-shape-complex-myanmar-machine.hh"
|
||||
|
@ -154,11 +154,11 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
|
||||
static void
|
||||
setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
find_syllables (buffer);
|
||||
find_syllables_myanmar (buffer);
|
||||
foreach_syllable (buffer, start, end)
|
||||
buffer->unsafe_to_break (start, end);
|
||||
}
|
||||
|
@ -274,29 +274,29 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
|
|||
}
|
||||
|
||||
static void
|
||||
initial_reordering_syllable (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_face_t *face HB_UNUSED,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start, unsigned int end)
|
||||
reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_face_t *face HB_UNUSED,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start, unsigned int end)
|
||||
{
|
||||
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
|
||||
myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
|
||||
switch (syllable_type) {
|
||||
|
||||
case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
|
||||
case consonant_syllable:
|
||||
case myanmar_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
|
||||
case myanmar_consonant_syllable:
|
||||
initial_reordering_consonant_syllable (buffer, start, end);
|
||||
break;
|
||||
|
||||
case punctuation_cluster:
|
||||
case non_myanmar_cluster:
|
||||
case myanmar_punctuation_cluster:
|
||||
case myanmar_non_myanmar_cluster:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
insert_dotted_circles_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
|
||||
return;
|
||||
|
@ -307,7 +307,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if ((info[i].syllable() & 0x0F) == broken_cluster)
|
||||
if ((info[i].syllable() & 0x0F) == myanmar_broken_cluster)
|
||||
{
|
||||
has_broken_syllables = true;
|
||||
break;
|
||||
|
@ -332,8 +332,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
while (buffer->idx < buffer->len && buffer->successful)
|
||||
{
|
||||
unsigned int syllable = buffer->cur().syllable();
|
||||
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
|
||||
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
|
||||
myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (syllable & 0x0F);
|
||||
if (unlikely (last_syllable != syllable && syllable_type == myanmar_broken_cluster))
|
||||
{
|
||||
last_syllable = syllable;
|
||||
|
||||
|
@ -351,30 +351,19 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
|
||||
static void
|
||||
reorder (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
reorder_myanmar (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
insert_dotted_circles (plan, font, buffer);
|
||||
insert_dotted_circles_myanmar (plan, font, buffer);
|
||||
|
||||
foreach_syllable (buffer, start, end)
|
||||
initial_reordering_syllable (plan, font->face, buffer, start, end);
|
||||
reorder_syllable_myanmar (plan, font->face, buffer, start, end);
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
info[i].syllable() = 0;
|
||||
}
|
||||
|
||||
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
|
||||
{
|
||||
|
@ -415,3 +404,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi =
|
|||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
|
||||
false, /* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -49,10 +49,10 @@ enum myanmar_category_t {
|
|||
OT_MW = 23, /* Various consonant medial types */
|
||||
OT_MY = 24, /* Various consonant medial types */
|
||||
OT_PT = 25, /* Pwo and other tones */
|
||||
OT_VAbv = 26,
|
||||
OT_VBlw = 27,
|
||||
OT_VPre = 28,
|
||||
OT_VPst = 29,
|
||||
//OT_VAbv = 26,
|
||||
//OT_VBlw = 27,
|
||||
//OT_VPre = 28,
|
||||
//OT_VPst = 29,
|
||||
OT_VS = 30, /* Variation selectors */
|
||||
OT_P = 31, /* Punctuation */
|
||||
OT_D = 32, /* Digits except zero */
|
||||
|
@ -155,11 +155,11 @@ set_myanmar_properties (hb_glyph_info_t &info)
|
|||
{
|
||||
switch ((int) pos)
|
||||
{
|
||||
case POS_PRE_C: cat = OT_VPre;
|
||||
case POS_PRE_C: cat = (myanmar_category_t) OT_VPre;
|
||||
pos = POS_PRE_M; break;
|
||||
case POS_ABOVE_C: cat = OT_VAbv; break;
|
||||
case POS_BELOW_C: cat = OT_VBlw; break;
|
||||
case POS_POST_C: cat = OT_VPst; break;
|
||||
case POS_ABOVE_C: cat = (myanmar_category_t) OT_VAbv; break;
|
||||
case POS_BELOW_C: cat = (myanmar_category_t) OT_VBlw; break;
|
||||
case POS_POST_C: cat = (myanmar_category_t) OT_VPst; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex.hh"
|
||||
|
||||
|
||||
|
@ -385,3 +389,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
|
|||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
|
||||
false,/* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -380,13 +380,13 @@ static const int use_syllable_machine_en_main = 5;
|
|||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
info[i].syllable() = (syllable_serial << 4) | use_##syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables (hb_buffer_t *buffer)
|
||||
find_syllables_use (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act;
|
||||
int cs;
|
||||
|
|
|
@ -165,13 +165,13 @@ main := |*
|
|||
HB_STMT_START { \
|
||||
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
|
||||
for (unsigned int i = ts; i < te; i++) \
|
||||
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
|
||||
info[i].syllable() = (syllable_serial << 4) | use_##syllable_type; \
|
||||
syllable_serial++; \
|
||||
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
|
||||
} HB_STMT_END
|
||||
|
||||
static void
|
||||
find_syllables (hb_buffer_t *buffer)
|
||||
find_syllables_use (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int p, pe, eof, ts, te, act;
|
||||
int cs;
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
* UnicodeData.txt does not have a header.
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex-use.hh"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -851,4 +855,6 @@ hb_use_get_category (hb_codepoint_t u)
|
|||
#undef VMPst
|
||||
#undef VMAbv
|
||||
|
||||
|
||||
#endif
|
||||
/* == End of generated table == */
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex-use.hh"
|
||||
#include "hb-ot-shape-complex-arabic.hh"
|
||||
#include "hb-ot-shape-complex-vowel-constraints.hh"
|
||||
|
@ -40,7 +44,7 @@
|
|||
*/
|
||||
|
||||
static const hb_tag_t
|
||||
basic_features[] =
|
||||
use_basic_features[] =
|
||||
{
|
||||
/*
|
||||
* Basic features.
|
||||
|
@ -55,28 +59,23 @@ basic_features[] =
|
|||
HB_TAG('c','j','c','t'),
|
||||
};
|
||||
static const hb_tag_t
|
||||
arabic_features[] =
|
||||
use_topographical_features[] =
|
||||
{
|
||||
HB_TAG('i','s','o','l'),
|
||||
HB_TAG('i','n','i','t'),
|
||||
HB_TAG('m','e','d','i'),
|
||||
HB_TAG('f','i','n','a'),
|
||||
/* The spec doesn't specify these but we apply anyway, since our Arabic shaper
|
||||
* does. These are only used in Syriac spec. */
|
||||
HB_TAG('m','e','d','2'),
|
||||
HB_TAG('f','i','n','2'),
|
||||
HB_TAG('f','i','n','3'),
|
||||
};
|
||||
/* Same order as arabic_features. Don't need Syriac stuff.*/
|
||||
/* Same order as use_topographical_features. */
|
||||
enum joining_form_t {
|
||||
ISOL,
|
||||
INIT,
|
||||
MEDI,
|
||||
FINA,
|
||||
_NONE
|
||||
USE_ISOL,
|
||||
USE_INIT,
|
||||
USE_MEDI,
|
||||
USE_FINA,
|
||||
_USE_NONE
|
||||
};
|
||||
static const hb_tag_t
|
||||
other_features[] =
|
||||
use_other_features[] =
|
||||
{
|
||||
/*
|
||||
* Other features.
|
||||
|
@ -90,7 +89,7 @@ other_features[] =
|
|||
HB_TAG('p','s','t','s'),
|
||||
};
|
||||
static const hb_tag_t
|
||||
positioning_features[] =
|
||||
use_positioning_features[] =
|
||||
{
|
||||
/*
|
||||
* Positioning features.
|
||||
|
@ -102,29 +101,21 @@ positioning_features[] =
|
|||
};
|
||||
|
||||
static void
|
||||
setup_syllables (const hb_ot_shape_plan_t *plan,
|
||||
setup_syllables_use (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
record_rphf_use (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
clear_substitution_flags (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
record_rphf (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
record_pref (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
reorder (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
clear_syllables (const hb_ot_shape_plan_t *plan,
|
||||
record_pref_use (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
static void
|
||||
reorder_use (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
static void
|
||||
collect_features_use (hb_ot_shape_planner_t *plan)
|
||||
|
@ -132,7 +123,7 @@ collect_features_use (hb_ot_shape_planner_t *plan)
|
|||
hb_ot_map_builder_t *map = &plan->map;
|
||||
|
||||
/* Do this before any lookups have been applied. */
|
||||
map->add_gsub_pause (setup_syllables);
|
||||
map->add_gsub_pause (setup_syllables_use);
|
||||
|
||||
/* "Default glyph pre-processing group" */
|
||||
map->enable_feature (HB_TAG('l','o','c','l'));
|
||||
|
@ -141,32 +132,32 @@ collect_features_use (hb_ot_shape_planner_t *plan)
|
|||
map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ);
|
||||
|
||||
/* "Reordering group" */
|
||||
map->add_gsub_pause (clear_substitution_flags);
|
||||
map->add_gsub_pause (_hb_clear_substitution_flags);
|
||||
map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ);
|
||||
map->add_gsub_pause (record_rphf);
|
||||
map->add_gsub_pause (clear_substitution_flags);
|
||||
map->add_gsub_pause (record_rphf_use);
|
||||
map->add_gsub_pause (_hb_clear_substitution_flags);
|
||||
map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ);
|
||||
map->add_gsub_pause (record_pref);
|
||||
map->add_gsub_pause (record_pref_use);
|
||||
|
||||
/* "Orthographic unit shaping group" */
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
|
||||
map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (use_basic_features); i++)
|
||||
map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ);
|
||||
|
||||
map->add_gsub_pause (reorder);
|
||||
map->add_gsub_pause (clear_syllables);
|
||||
map->add_gsub_pause (reorder_use);
|
||||
map->add_gsub_pause (_hb_clear_syllables);
|
||||
|
||||
/* "Topographical features" */
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
|
||||
map->add_feature (arabic_features[i]);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)
|
||||
map->add_feature (use_topographical_features[i]);
|
||||
map->add_gsub_pause (nullptr);
|
||||
|
||||
/* "Standard typographic presentation" */
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
|
||||
map->enable_feature (other_features[i], F_MANUAL_ZWJ);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (use_other_features); i++)
|
||||
map->enable_feature (use_other_features[i], F_MANUAL_ZWJ);
|
||||
|
||||
/* "Positional feature application" */
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
|
||||
map->enable_feature (positioning_features[i]);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (use_positioning_features); i++)
|
||||
map->enable_feature (use_positioning_features[i]);
|
||||
}
|
||||
|
||||
struct use_shape_plan_t
|
||||
|
@ -243,16 +234,16 @@ data_destroy_use (void *data)
|
|||
free (data);
|
||||
}
|
||||
|
||||
enum syllable_type_t {
|
||||
independent_cluster,
|
||||
virama_terminated_cluster,
|
||||
sakot_terminated_cluster,
|
||||
standard_cluster,
|
||||
number_joiner_terminated_cluster,
|
||||
numeral_cluster,
|
||||
symbol_cluster,
|
||||
broken_cluster,
|
||||
non_cluster,
|
||||
enum use_syllable_type_t {
|
||||
use_independent_cluster,
|
||||
use_virama_terminated_cluster,
|
||||
use_sakot_terminated_cluster,
|
||||
use_standard_cluster,
|
||||
use_number_joiner_terminated_cluster,
|
||||
use_numeral_cluster,
|
||||
use_symbol_cluster,
|
||||
use_broken_cluster,
|
||||
use_non_cluster,
|
||||
};
|
||||
|
||||
#include "hb-ot-shape-complex-use-machine.hh"
|
||||
|
@ -309,11 +300,11 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
|
|||
if (use_plan->arabic_plan)
|
||||
return;
|
||||
|
||||
static_assert ((INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4), "");
|
||||
static_assert ((USE_INIT < 4 && USE_ISOL < 4 && USE_MEDI < 4 && USE_FINA < 4), "");
|
||||
hb_mask_t masks[4], all_masks = 0;
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
{
|
||||
masks[i] = plan->map.get_1_mask (arabic_features[i]);
|
||||
masks[i] = plan->map.get_1_mask (use_topographical_features[i]);
|
||||
if (masks[i] == plan->map.get_global_mask ())
|
||||
masks[i] = 0;
|
||||
all_masks |= masks[i];
|
||||
|
@ -323,39 +314,39 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
|
|||
hb_mask_t other_masks = ~all_masks;
|
||||
|
||||
unsigned int last_start = 0;
|
||||
joining_form_t last_form = _NONE;
|
||||
joining_form_t last_form = _USE_NONE;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
foreach_syllable (buffer, start, end)
|
||||
{
|
||||
syllable_type_t syllable_type = (syllable_type_t) (info[start].syllable() & 0x0F);
|
||||
use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F);
|
||||
switch (syllable_type)
|
||||
{
|
||||
case independent_cluster:
|
||||
case symbol_cluster:
|
||||
case non_cluster:
|
||||
case use_independent_cluster:
|
||||
case use_symbol_cluster:
|
||||
case use_non_cluster:
|
||||
/* These don't join. Nothing to do. */
|
||||
last_form = _NONE;
|
||||
last_form = _USE_NONE;
|
||||
break;
|
||||
|
||||
case virama_terminated_cluster:
|
||||
case sakot_terminated_cluster:
|
||||
case standard_cluster:
|
||||
case number_joiner_terminated_cluster:
|
||||
case numeral_cluster:
|
||||
case broken_cluster:
|
||||
case use_virama_terminated_cluster:
|
||||
case use_sakot_terminated_cluster:
|
||||
case use_standard_cluster:
|
||||
case use_number_joiner_terminated_cluster:
|
||||
case use_numeral_cluster:
|
||||
case use_broken_cluster:
|
||||
|
||||
bool join = last_form == FINA || last_form == ISOL;
|
||||
bool join = last_form == USE_FINA || last_form == USE_ISOL;
|
||||
|
||||
if (join)
|
||||
{
|
||||
/* Fixup previous syllable's form. */
|
||||
last_form = last_form == FINA ? MEDI : INIT;
|
||||
last_form = last_form == USE_FINA ? USE_MEDI : USE_INIT;
|
||||
for (unsigned int i = last_start; i < start; i++)
|
||||
info[i].mask = (info[i].mask & other_masks) | masks[last_form];
|
||||
}
|
||||
|
||||
/* Form for this syllable. */
|
||||
last_form = join ? FINA : ISOL;
|
||||
last_form = join ? USE_FINA : USE_ISOL;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
info[i].mask = (info[i].mask & other_masks) | masks[last_form];
|
||||
|
||||
|
@ -367,11 +358,11 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
|
|||
}
|
||||
|
||||
static void
|
||||
setup_syllables (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
setup_syllables_use (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
find_syllables (buffer);
|
||||
find_syllables_use (buffer);
|
||||
foreach_syllable (buffer, start, end)
|
||||
buffer->unsafe_to_break (start, end);
|
||||
setup_rphf_mask (plan, buffer);
|
||||
|
@ -379,20 +370,9 @@ setup_syllables (const hb_ot_shape_plan_t *plan,
|
|||
}
|
||||
|
||||
static void
|
||||
clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
_hb_glyph_info_clear_substituted (&info[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
record_rphf (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
record_rphf_use (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
|
||||
|
||||
|
@ -413,9 +393,9 @@ record_rphf (const hb_ot_shape_plan_t *plan,
|
|||
}
|
||||
|
||||
static void
|
||||
record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
|
@ -432,22 +412,22 @@ record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
|
||||
static inline bool
|
||||
is_halant (const hb_glyph_info_t &info)
|
||||
is_halant_use (const hb_glyph_info_t &info)
|
||||
{
|
||||
return (info.use_category() == USE_H || info.use_category() == USE_HVM) &&
|
||||
!_hb_glyph_info_ligated (&info);
|
||||
}
|
||||
|
||||
static void
|
||||
reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
|
||||
reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
|
||||
{
|
||||
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
|
||||
use_syllable_type_t syllable_type = (use_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
|
||||
/* Only a few syllable types need reordering. */
|
||||
if (unlikely (!(FLAG_UNSAFE (syllable_type) &
|
||||
(FLAG (virama_terminated_cluster) |
|
||||
FLAG (sakot_terminated_cluster) |
|
||||
FLAG (standard_cluster) |
|
||||
FLAG (broken_cluster) |
|
||||
(FLAG (use_virama_terminated_cluster) |
|
||||
FLAG (use_sakot_terminated_cluster) |
|
||||
FLAG (use_standard_cluster) |
|
||||
FLAG (use_broken_cluster) |
|
||||
0))))
|
||||
return;
|
||||
|
||||
|
@ -478,7 +458,7 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
|
|||
for (unsigned int i = start + 1; i < end; i++)
|
||||
{
|
||||
bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
|
||||
is_halant (info[i]);
|
||||
is_halant_use (info[i]);
|
||||
if (is_post_base_glyph || i == end - 1)
|
||||
{
|
||||
/* If we hit a post-base glyph, move before it; otherwise move to the
|
||||
|
@ -502,7 +482,7 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
|
|||
for (unsigned int i = start; i < end; i++)
|
||||
{
|
||||
uint32_t flag = FLAG_UNSAFE (info[i].use_category());
|
||||
if (is_halant (info[i]))
|
||||
if (is_halant_use (info[i]))
|
||||
{
|
||||
/* If we hit a halant, move after it; otherwise move to the beginning, and
|
||||
* shift things in between forward. */
|
||||
|
@ -522,9 +502,9 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
|
|||
}
|
||||
|
||||
static inline void
|
||||
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
insert_dotted_circles_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
|
||||
return;
|
||||
|
@ -535,7 +515,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
unsigned int count = buffer->len;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if ((info[i].syllable() & 0x0F) == broken_cluster)
|
||||
if ((info[i].syllable() & 0x0F) == use_broken_cluster)
|
||||
{
|
||||
has_broken_syllables = true;
|
||||
break;
|
||||
|
@ -555,8 +535,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
while (buffer->idx < buffer->len && buffer->successful)
|
||||
{
|
||||
unsigned int syllable = buffer->cur().syllable();
|
||||
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
|
||||
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
|
||||
use_syllable_type_t syllable_type = (use_syllable_type_t) (syllable & 0x0F);
|
||||
if (unlikely (last_syllable != syllable && syllable_type == use_broken_cluster))
|
||||
{
|
||||
last_syllable = syllable;
|
||||
|
||||
|
@ -580,29 +560,18 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
|
||||
static void
|
||||
reorder (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
reorder_use (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
insert_dotted_circles (plan, font, buffer);
|
||||
insert_dotted_circles_use (plan, font, buffer);
|
||||
|
||||
foreach_syllable (buffer, start, end)
|
||||
reorder_syllable (buffer, start, end);
|
||||
reorder_syllable_use (buffer, start, end);
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_font_t *font HB_UNUSED,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
info[i].syllable() = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
preprocess_text_use (const hb_ot_shape_plan_t *plan,
|
||||
|
@ -643,3 +612,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
|
|||
HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
|
||||
false, /* fallback_position */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
* # Date: 2019-01-28, 22:16:47 GMT
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-complex-vowel-constraints.hh"
|
||||
|
||||
static void
|
||||
|
@ -440,4 +444,6 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
/* == End of generated functions == */
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-fallback.hh"
|
||||
#include "hb-kern.hh"
|
||||
|
||||
|
@ -587,3 +591,6 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#include "hb-ot-shape-normalize.hh"
|
||||
#include "hb-ot-shape-complex.hh"
|
||||
#include "hb-ot-shape.hh"
|
||||
|
@ -469,3 +473,6 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
|
|||
buffer->swap_buffers ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,14 @@
|
|||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_SHAPE
|
||||
|
||||
#ifdef HB_NO_OT_LAYOUT
|
||||
#error "Cannot compile 'ot' shaper with HB_NO_OT_LAYOUT."
|
||||
#endif
|
||||
|
||||
#include "hb-shaper-impl.hh"
|
||||
|
||||
#include "hb-ot-shape.hh"
|
||||
|
@ -55,7 +63,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
|
|||
const hb_feature_t *user_features,
|
||||
unsigned int num_user_features);
|
||||
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
static inline bool
|
||||
_hb_apply_morx (hb_face_t *face)
|
||||
{
|
||||
|
@ -78,7 +86,7 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
|
|||
props (*props),
|
||||
map (face, props),
|
||||
aat_map (face, props)
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
, apply_morx (_hb_apply_morx (face))
|
||||
#endif
|
||||
{
|
||||
|
@ -98,7 +106,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
plan.props = props;
|
||||
plan.shaper = shaper;
|
||||
map.compile (plan.map, key);
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (apply_morx)
|
||||
aat_map.compile (plan.aat_map);
|
||||
#endif
|
||||
|
@ -117,7 +125,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
plan.kern_mask = plan.map.get_mask (kern_tag);
|
||||
plan.requested_kerning = !!plan.kern_mask;
|
||||
#endif
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
|
||||
plan.requested_tracking = !!plan.trak_mask;
|
||||
#endif
|
||||
|
@ -137,7 +145,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
* Decide who does substitutions. GSUB, morx, or fallback.
|
||||
*/
|
||||
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
plan.apply_morx = apply_morx;
|
||||
#endif
|
||||
|
||||
|
@ -147,13 +155,13 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
|
||||
if (0)
|
||||
;
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
else if (hb_options ().aat && hb_aat_layout_has_positioning (face))
|
||||
plan.apply_kerx = true;
|
||||
#endif
|
||||
else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face))
|
||||
plan.apply_gpos = true;
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
else if (hb_aat_layout_has_positioning (face))
|
||||
plan.apply_kerx = true;
|
||||
#endif
|
||||
|
@ -161,7 +169,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
if (!plan.apply_kerx && !has_gpos_kern)
|
||||
{
|
||||
/* Apparently Apple applies kerx if GPOS kern was not applied. */
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (hb_aat_layout_has_positioning (face))
|
||||
plan.apply_kerx = true;
|
||||
else
|
||||
|
@ -192,7 +200,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
|||
plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
|
||||
script_fallback_mark_positioning;
|
||||
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
/* Currently we always apply trak. */
|
||||
plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
|
||||
#endif
|
||||
|
@ -203,7 +211,7 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face,
|
|||
const hb_shape_plan_key_t *key)
|
||||
{
|
||||
map.init ();
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
aat_map.init ();
|
||||
#endif
|
||||
|
||||
|
@ -233,7 +241,7 @@ hb_ot_shape_plan_t::fini ()
|
|||
shaper->data_destroy (const_cast<void *> (data));
|
||||
|
||||
map.fini ();
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
aat_map.fini ();
|
||||
#endif
|
||||
}
|
||||
|
@ -242,7 +250,7 @@ void
|
|||
hb_ot_shape_plan_t::substitute (hb_font_t *font,
|
||||
hb_buffer_t *buffer) const
|
||||
{
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (unlikely (apply_morx))
|
||||
hb_aat_layout_substitute (this, font, buffer);
|
||||
else
|
||||
|
@ -256,7 +264,7 @@ hb_ot_shape_plan_t::position (hb_font_t *font,
|
|||
{
|
||||
if (this->apply_gpos)
|
||||
map.position (this, font, buffer);
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
else if (this->apply_kerx)
|
||||
hb_aat_layout_position (this, font, buffer);
|
||||
#endif
|
||||
|
@ -267,7 +275,7 @@ hb_ot_shape_plan_t::position (hb_font_t *font,
|
|||
else
|
||||
_hb_ot_shape_fallback_kern (this, font, buffer);
|
||||
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (this->apply_trak)
|
||||
hb_aat_layout_track (this, font, buffer);
|
||||
#endif
|
||||
|
@ -332,7 +340,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
|
|||
/* Random! */
|
||||
map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
|
||||
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
/* Tracking. We enable dummy feature here just to allow disabling
|
||||
* AAT 'trak' table using features.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1303 */
|
||||
|
@ -370,7 +378,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
|
|||
feature->value);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (planner->apply_morx)
|
||||
{
|
||||
hb_aat_map_builder_t *aat_map = &planner->aat_map;
|
||||
|
@ -471,6 +479,7 @@ hb_set_unicode_props (hb_buffer_t *buffer)
|
|||
{
|
||||
_hb_glyph_info_set_continuation (&info[i]);
|
||||
}
|
||||
#ifndef HB_NO_EMOJI_SEQUENCES
|
||||
else if (unlikely (_hb_glyph_info_is_zwj (&info[i])))
|
||||
{
|
||||
_hb_glyph_info_set_continuation (&info[i]);
|
||||
|
@ -482,6 +491,7 @@ hb_set_unicode_props (hb_buffer_t *buffer)
|
|||
_hb_glyph_info_set_continuation (&info[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Or part of the Other_Grapheme_Extend that is not marks.
|
||||
* As of Unicode 11 that is just:
|
||||
*
|
||||
|
@ -819,7 +829,7 @@ static inline void
|
|||
hb_ot_substitute_post (const hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_hide_default_ignorables (c->buffer, c->font);
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (c->plan->apply_morx)
|
||||
hb_aat_layout_remove_deleted_glyphs (c->buffer);
|
||||
#endif
|
||||
|
@ -956,7 +966,7 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
|
|||
/* Finish off. Has to follow a certain order. */
|
||||
hb_ot_layout_position_finish_advances (c->font, c->buffer);
|
||||
hb_ot_zero_width_default_ignorables (c->buffer);
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
if (c->plan->apply_morx)
|
||||
hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
|
||||
#endif
|
||||
|
@ -1146,3 +1156,6 @@ hb_ot_shape_glyphs_closure (hb_font_t *font,
|
|||
|
||||
hb_shape_plan_destroy (shape_plan);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -78,7 +78,7 @@ struct hb_ot_shape_plan_t
|
|||
#else
|
||||
static constexpr hb_mask_t kern_mask = 0;
|
||||
#endif
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
hb_mask_t trak_mask;
|
||||
#else
|
||||
static constexpr hb_mask_t trak_mask = 0;
|
||||
|
@ -89,7 +89,7 @@ struct hb_ot_shape_plan_t
|
|||
#else
|
||||
static constexpr bool requested_kerning = false;
|
||||
#endif
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
bool requested_tracking : 1;
|
||||
#else
|
||||
static constexpr bool requested_tracking = false;
|
||||
|
@ -111,7 +111,7 @@ struct hb_ot_shape_plan_t
|
|||
#else
|
||||
static constexpr bool apply_kern = false;
|
||||
#endif
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
bool apply_kerx : 1;
|
||||
bool apply_morx : 1;
|
||||
bool apply_trak : 1;
|
||||
|
@ -149,7 +149,7 @@ struct hb_ot_shape_planner_t
|
|||
hb_segment_properties_t props;
|
||||
hb_ot_map_builder_t map;
|
||||
hb_aat_map_builder_t aat_map;
|
||||
#ifndef HB_NO_SHAPE_AAT
|
||||
#ifndef HB_NO_AAT_SHAPE
|
||||
bool apply_morx : 1;
|
||||
#else
|
||||
static constexpr bool apply_morx = false;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OT_TAG
|
||||
|
||||
|
||||
/* hb_script_t */
|
||||
|
||||
|
@ -548,3 +550,6 @@ main ()
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -237,7 +237,7 @@ struct fvar
|
|||
v = (v - axis.default_value) / (axis.default_value - axis.min_value);
|
||||
else
|
||||
v = (v - axis.default_value) / (axis.max_value - axis.default_value);
|
||||
return (int) (v * 16384.f + (v >= 0.f ? .5f : -.5f));
|
||||
return roundf (v * 16384.f);
|
||||
}
|
||||
|
||||
unsigned int get_instance_count () const { return instanceCount; }
|
||||
|
|
|
@ -68,7 +68,7 @@ hb_ot_var_get_axis_count (hb_face_t *face);
|
|||
typedef enum { /*< flags >*/
|
||||
HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x00000001u,
|
||||
|
||||
_HB_OT_VAR_AXIS_FLAG_MAX_VALUE= 0x7FFFFFFFu /*< skip >*/
|
||||
_HB_OT_VAR_AXIS_FLAG_MAX_VALUE= HB_TAG_MAX_SIGNED /*< skip >*/
|
||||
} hb_ot_var_axis_flags_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -85,7 +85,7 @@ struct VORG
|
|||
this->vertYOrigins.len = it.len ();
|
||||
|
||||
+ it
|
||||
| hb_apply ([c] (const VertOriginMetric& _) { c->copy (_);})
|
||||
| hb_apply ([c] (const VertOriginMetric& _) { c->copy (_); })
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "hb-ot-font.h"
|
||||
#include "hb-ot-layout.h"
|
||||
#include "hb-ot-math.h"
|
||||
#include "hb-ot-meta.h"
|
||||
#include "hb-ot-metrics.h"
|
||||
#include "hb-ot-name.h"
|
||||
#include "hb-ot-shape.h"
|
||||
#include "hb-ot-var.h"
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче