зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset a3f5d01bee73 (bug 1631118) for Wr failures at /css/css-fonts/font-feature-settings-tibetan.html on a CLOSED TREE
This commit is contained in:
Родитель
7738900e5b
Коммит
a43b568040
|
@ -2,9 +2,8 @@ HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
|
|||
For parts of HarfBuzz that are licensed under different licenses see individual
|
||||
files names COPYING in subdirectories where applicable.
|
||||
|
||||
Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc.
|
||||
Copyright © 2018,2019,2020 Ebrahim Byagowi
|
||||
Copyright © 2019,2020 Facebook, Inc.
|
||||
Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019 Google, Inc.
|
||||
Copyright © 2019 Facebook, Inc.
|
||||
Copyright © 2012 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
|
|
|
@ -18,17 +18,6 @@ EXTRA_DIST = \
|
|||
TESTING.md \
|
||||
CMakeLists.txt \
|
||||
replace-enum-strings.cmake \
|
||||
meson.build \
|
||||
meson_options.txt \
|
||||
subprojects/expat.wrap \
|
||||
subprojects/fontconfig.wrap \
|
||||
subprojects/freetype2.wrap \
|
||||
subprojects/glib.wrap \
|
||||
subprojects/libffi.wrap \
|
||||
subprojects/proxy-libintl.wrap \
|
||||
subprojects/zlib.wrap \
|
||||
meson-cc-tests/intel-atomic-primitives-test.c \
|
||||
meson-cc-tests/solaris-atomic-operations.c \
|
||||
mingw-configure.sh \
|
||||
mingw-ldd.py \
|
||||
mingw32.sh \
|
||||
|
|
|
@ -1,23 +1,3 @@
|
|||
Overview of changes leading to 2.6.6
|
||||
Tuesday, May 12, 2020
|
||||
====================================
|
||||
- A fix in AAT kerning for Geeza Pro.
|
||||
- Better support for resource fork fonts on macOS.
|
||||
|
||||
|
||||
Overview of changes leading to 2.6.5
|
||||
Friday, April 17, 2020
|
||||
====================================
|
||||
- Add experimental meson build system. Autotools is still the primary
|
||||
and supported build system.
|
||||
- AAT is now always preferred for horizontal scripts when both AAT and OT
|
||||
layout tables exist at the same time.
|
||||
- Subsetter improvements.
|
||||
- New API:
|
||||
+hb_ft_font_lock_face()
|
||||
+hb_ft_font_unlock_face()
|
||||
|
||||
|
||||
Overview of changes leading to 2.6.4
|
||||
Monday, October 29, 2019
|
||||
====================================
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
This directory contains the HarfBuzz source from the upstream repo:
|
||||
https://github.com/harfbuzz/harfbuzz
|
||||
|
||||
Current version: 2.6.6 [commit 42025680cb0a30eba4ed48d125586a4dda3c973e]
|
||||
Current version: 2.6.4 [commit 3a74ee528255cc027d84b204a87b5c25e47bff79]
|
||||
|
||||
UPDATING:
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ Documentation: https://harfbuzz.github.io
|
|||
|
||||
|
||||
<details>
|
||||
<summary>Packaging status of HarfBuzz</summary>
|
||||
<summary>Packaging status of HarfBuzz</summary
|
||||
|
||||
[![Packaging status](https://repology.org/badge/vertical-allrepos/harfbuzz.svg?header=harfbuzz)](https://repology.org/project/harfbuzz/versions)
|
||||
[![Packaging status](https://repology.org/badge/vertical-allrepos/harfbuzz.svg?header=harfbuzz)](https://repology.org/project/harfbuzz/versions)
|
||||
|
||||
</details>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AC_PREREQ([2.64])
|
||||
AC_INIT([HarfBuzz],
|
||||
[2.6.6],
|
||||
[2.6.4],
|
||||
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||
[harfbuzz],
|
||||
[http://harfbuzz.org/])
|
||||
|
@ -23,7 +23,7 @@ AC_PROG_CC
|
|||
AC_PROG_CC_C99
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CXX
|
||||
AX_CXX_COMPILE_STDCXX(11)
|
||||
AX_CXX_COMPILE_STDCXX(11,, optional)
|
||||
AC_SYS_LARGEFILE
|
||||
PKG_PROG_PKG_CONFIG([0.20])
|
||||
AM_MISSING_PROG([RAGEL], [ragel])
|
||||
|
@ -77,8 +77,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
|
|||
])
|
||||
|
||||
# Functions and headers
|
||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty roundf)
|
||||
AC_CHECK_HEADERS(unistd.h sys/mman.h stdbool.h)
|
||||
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l roundf)
|
||||
AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h stdbool.h)
|
||||
|
||||
# Compiler flags
|
||||
AC_CANONICAL_HOST
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
# IndicShapingInvalidCluster.txt
|
||||
# Date: 2015-03-12, 21:17:00 GMT [AG]
|
||||
# Date: 2019-11-08, 23:22:00 GMT [AG]
|
||||
#
|
||||
# This file defines the following property:
|
||||
#
|
||||
# Indic_Shaping_Invalid_Cluster
|
||||
#
|
||||
# Scope: This file enumerates sequences of characters that should be treated as invalid clusters
|
||||
# Copied from https://docs.microsoft.com/en-us/typography/script-development/use
|
||||
# On October 23, 2018; with documentd dated 02/07/2018.
|
||||
|
||||
0905 0946 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN SHORT E
|
||||
0905 093E ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AA
|
||||
|
@ -55,7 +48,6 @@
|
|||
0B05 0B3E ; # ORIYA LETTER A, ORIYA VOWEL SIGN AA
|
||||
0B0F 0B57 ; # ORIYA LETTER E, ORIYA AU LENGTH MARK
|
||||
0B13 0B57 ; # ORIYA LETTER O, ORIYA AU LENGTH MARK
|
||||
0B85 0BC2 ; # TAMIL LETTER A, TAMIL VOWEL SIGN UU
|
||||
0C12 0C55 ; # TELUGU LETTER O, TELUGU LENGTH MARK
|
||||
0C12 0C4C ; # TELUGU LETTER O, TELUGU VOWEL SIGN AU
|
||||
0C3F 0C55 ; # TELUGU VOWEL SIGN I, TELUGU LENGTH MARK
|
|
@ -13,8 +13,6 @@ TESTS =
|
|||
check_PROGRAMS =
|
||||
|
||||
EXTRA_DIST += harfbuzz.cc
|
||||
EXTRA_DIST += meson.build
|
||||
EXTRA_DIST += fix_get_types.py
|
||||
|
||||
# Convenience targets:
|
||||
lib: $(BUILT_SOURCES) libharfbuzz.la
|
||||
|
@ -52,7 +50,12 @@ endif
|
|||
if HAVE_FREETYPE
|
||||
HBCFLAGS += $(FREETYPE_CFLAGS)
|
||||
HBLIBS += $(FREETYPE_LIBS)
|
||||
HBDEPS += $(FREETYPE_DEPS)
|
||||
# XXX
|
||||
# The following creates a recursive dependency on FreeType if FreeType is
|
||||
# built with HarfBuzz support enabled. Newer pkg-config handles that just
|
||||
# fine but pkg-config 0.26 as shipped in Ubuntu 14.04 crashes. Remove
|
||||
# in a year or two, or otherwise work around it...
|
||||
#HBDEPS += $(FREETYPE_DEPS)
|
||||
HBSOURCES += $(HB_FT_sources)
|
||||
HBHEADERS += $(HB_FT_headers)
|
||||
endif
|
||||
|
@ -150,7 +153,6 @@ cmake_DATA = harfbuzz-config.cmake
|
|||
EXTRA_DIST += hb-version.h.in harfbuzz.pc.in harfbuzz-config.cmake.in
|
||||
|
||||
lib_LTLIBRARIES += libharfbuzz-subset.la
|
||||
libharfbuzz_subset_la_LINK = $(chosen_linker) $(libharfbuzz_subset_la_LDFLAGS)
|
||||
libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources)
|
||||
libharfbuzz_subset_la_CPPFLAGS = $(HBCFLAGS) $(CODE_COVERAGE_CFLAGS)
|
||||
libharfbuzz_subset_la_LDFLAGS = $(base_link_flags) $(export_symbols_subset) $(CODE_COVERAGE_LDFLAGS)
|
||||
|
@ -288,7 +290,7 @@ ucd-table: gen-ucd-table.py ucd.nounihan.grouped.zip hb-common.h
|
|||
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 ms-use/IndicShapingInvalidCluster.txt Scripts.txt
|
||||
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)
|
||||
|
||||
|
@ -332,7 +334,6 @@ noinst_PROGRAMS = \
|
|||
test-buffer-serialize \
|
||||
test-ot-meta \
|
||||
test-ot-name \
|
||||
test-ot-glyphname \
|
||||
test-gpos-size-params \
|
||||
test-gsub-would-substitute \
|
||||
$(NULL)
|
||||
|
@ -358,10 +359,6 @@ test_ot_name_SOURCES = test-ot-name.cc
|
|||
test_ot_name_CPPFLAGS = $(HBCFLAGS)
|
||||
test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_ot_glyphname_SOURCES = test-ot-glyphname.cc
|
||||
test_ot_glyphname_CPPFLAGS = $(HBCFLAGS)
|
||||
test_ot_glyphname_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_gpos_size_params_SOURCES = test-gpos-size-params.cc
|
||||
test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
|
||||
test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
@ -370,6 +367,31 @@ test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
|
|||
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
||||
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
||||
|
||||
if HAVE_FREETYPE
|
||||
if HAVE_CAIRO_FT
|
||||
noinst_PROGRAMS += test-ot-color
|
||||
test_ot_color_SOURCES = test-ot-color.cc
|
||||
test_ot_color_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS)
|
||||
test_ot_color_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS)
|
||||
endif # HAVE_CAIRO_FT
|
||||
endif # HAVE_FREETYPE
|
||||
|
||||
dist_check_SCRIPTS = \
|
||||
check-c-linkage-decls.sh \
|
||||
check-externs.sh \
|
||||
check-header-guards.sh \
|
||||
check-includes.sh \
|
||||
check-static-inits.sh \
|
||||
check-symbols.sh \
|
||||
$(NULL)
|
||||
TESTS += $(dist_check_SCRIPTS)
|
||||
|
||||
if !WITH_LIBSTDCXX
|
||||
dist_check_SCRIPTS += \
|
||||
check-libstdc++.sh \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
check_PROGRAMS += \
|
||||
dump-indic-data \
|
||||
dump-khmer-data \
|
||||
|
@ -389,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-array test-iter test-meta test-number test-ot-tag test-unicode-ranges test-bimap
|
||||
COMPILED_TESTS = test-algs test-iter test-meta test-number test-ot-tag test-unicode-ranges test-bimap
|
||||
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
|
||||
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
check_PROGRAMS += $(COMPILED_TESTS)
|
||||
|
@ -399,10 +421,6 @@ test_algs_SOURCES = test-algs.cc hb-static.cc
|
|||
test_algs_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_algs_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
test_array_SOURCES = test-array.cc
|
||||
test_array_CPPFLAGS = $(HBCFLAGS)
|
||||
test_array_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_iter_SOURCES = test-iter.cc hb-static.cc
|
||||
test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_iter_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
@ -427,25 +445,8 @@ test_bimap_SOURCES = test-bimap.cc hb-static.cc
|
|||
test_bimap_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
|
||||
test_bimap_LDADD = $(COMPILED_TESTS_LDADD)
|
||||
|
||||
dist_check_SCRIPTS = \
|
||||
check-c-linkage-decls.sh \
|
||||
check-externs.sh \
|
||||
check-header-guards.sh \
|
||||
check-includes.sh \
|
||||
check-static-inits.sh \
|
||||
check-symbols.sh \
|
||||
$(NULL)
|
||||
TESTS += $(dist_check_SCRIPTS)
|
||||
|
||||
if !WITH_LIBSTDCXX
|
||||
dist_check_SCRIPTS += \
|
||||
check-libstdc++.sh \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
TESTS_ENVIRONMENT = \
|
||||
srcdir="$(srcdir)" \
|
||||
builddir="$(builddir)" \
|
||||
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
|
||||
HBSOURCES="$(HBSOURCES)" \
|
||||
HBHEADERS="$(HBHEADERS)" \
|
||||
|
@ -455,16 +456,7 @@ if HAVE_INTROSPECTION
|
|||
|
||||
-include $(INTROSPECTION_MAKEFILE)
|
||||
INTROSPECTION_GIRS = HarfBuzz-0.0.gir # What does the 0 mean anyway?!
|
||||
INTROSPECTION_SCANNER_ARGS = \
|
||||
-I$(srcdir) \
|
||||
--warn-all --verbose \
|
||||
--namespace=HarfBuzz \
|
||||
--nsversion=0.0 \
|
||||
--symbol-prefix=hb \
|
||||
--symbol-prefix=hb_gobject \
|
||||
--identifier-prefix=hb_ \
|
||||
--pkg-export=harfbuzz-gobject \
|
||||
--c-include=hb-gobject.h
|
||||
INTROSPECTION_SCANNER_ARGS = -I$(srcdir) -n hb --identifier-prefix=hb_ --warn-all
|
||||
INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
|
||||
INTROSPECTION_SCANNER_ENV = CC="$(CC)"
|
||||
|
||||
|
|
|
@ -35,8 +35,6 @@ HB_BASE_sources = \
|
|||
hb-config.hh \
|
||||
hb-debug.hh \
|
||||
hb-dispatch.hh \
|
||||
hb-draw.cc \
|
||||
hb-draw.hh \
|
||||
hb-face.cc \
|
||||
hb-face.hh \
|
||||
hb-fallback-shape.cc \
|
||||
|
@ -59,7 +57,6 @@ HB_BASE_sources = \
|
|||
hb-ot-cff-common.hh \
|
||||
hb-ot-cff1-table.cc \
|
||||
hb-ot-cff1-table.hh \
|
||||
hb-ot-cff1-std-str.hh \
|
||||
hb-ot-cff2-table.cc \
|
||||
hb-ot-cff2-table.hh \
|
||||
hb-ot-cmap-table.hh \
|
||||
|
@ -195,7 +192,6 @@ HB_BASE_headers = \
|
|||
hb-buffer.h \
|
||||
hb-common.h \
|
||||
hb-deprecated.h \
|
||||
hb-draw.h \
|
||||
hb-face.h \
|
||||
hb-font.h \
|
||||
hb-map.h \
|
||||
|
|
|
@ -22,7 +22,8 @@ fi
|
|||
|
||||
tested=false
|
||||
# harfbuzz-icu links to libstdc++ because icu does.
|
||||
for soname in harfbuzz harfbuzz-subset harfbuzz-gobject; do
|
||||
# harfbuzz-subset uses libstdc++.
|
||||
for soname in harfbuzz harfbuzz-gobject; do
|
||||
for suffix in so dylib; do
|
||||
so=$libs/lib$soname.$suffix
|
||||
if ! test -f "$so"; then continue; fi
|
||||
|
|
|
@ -4,7 +4,7 @@ LC_ALL=C
|
|||
export LC_ALL
|
||||
|
||||
test -z "$srcdir" && srcdir=.
|
||||
test -z "$builddir" && builddir=.
|
||||
test -z "$libs" && libs=.libs
|
||||
stat=0
|
||||
|
||||
if which objdump 2>/dev/null >/dev/null; then
|
||||
|
@ -14,21 +14,18 @@ else
|
|||
exit 77
|
||||
fi
|
||||
|
||||
OBJS=$(find $builddir/ -name '*.o')
|
||||
OBJS=$libs/*.o
|
||||
if test "x`echo $OBJS`" = "x$OBJS" 2>/dev/null >/dev/null; then
|
||||
echo "check-static-inits.sh: object files not found; skipping test"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
tested=false
|
||||
|
||||
echo "Checking that no object file has static initializers"
|
||||
for obj in $OBJS; do
|
||||
if objdump -t "$obj" | grep '[.][cd]tors' | grep -v '\<00*\>'; then
|
||||
echo "Ouch, $obj has static initializers/finalizers"
|
||||
stat=1
|
||||
fi
|
||||
tested=true
|
||||
done
|
||||
|
||||
echo "Checking that no object file has lazy static C++ constructors/destructors or other such stuff"
|
||||
|
@ -38,12 +35,6 @@ for obj in $OBJS; do
|
|||
echo "Ouch, $obj has lazy static C++ constructors/destructors or other such stuff"
|
||||
stat=1
|
||||
fi
|
||||
tested=true
|
||||
done
|
||||
|
||||
if ! $tested; then
|
||||
echo "check-static-inits.sh: no objects found; skipping test"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
exit $stat
|
||||
|
|
|
@ -4,11 +4,10 @@ LC_ALL=C
|
|||
export LC_ALL
|
||||
|
||||
test -z "$srcdir" && srcdir=.
|
||||
test -z "$builddir" && builddir=.
|
||||
test -z "$libs" && libs=.libs
|
||||
stat=0
|
||||
|
||||
IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_.*\|llvm_.*\|flush_fn_list\|writeout_fn_list'
|
||||
IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_.*\|llvm_.*'
|
||||
|
||||
if which nm 2>/dev/null >/dev/null; then
|
||||
:
|
||||
|
@ -27,7 +26,7 @@ for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
|
|||
symprefix=
|
||||
if test $suffix = dylib; then symprefix=_; fi
|
||||
|
||||
EXPORTED_SYMBOLS=`nm "$so" | grep ' [BCDGIRST] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`
|
||||
EXPORTED_SYMBOLS=`nm "$so" | grep ' [BCDGINRST] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`
|
||||
|
||||
prefix=$symprefix`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'`
|
||||
|
||||
|
@ -37,7 +36,7 @@ for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
|
|||
stat=1
|
||||
fi
|
||||
|
||||
def=$builddir/$soname.def
|
||||
def=$soname.def
|
||||
if ! test -f "$def"; then
|
||||
echo "'$def' not found; skipping"
|
||||
else
|
||||
|
@ -48,9 +47,9 @@ for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do
|
|||
# cheat: copy the last line from the def file!
|
||||
tail -n1 "$def"
|
||||
} | c++filt | diff "$def" - >&2 || stat=1
|
||||
|
||||
tested=true
|
||||
fi
|
||||
|
||||
tested=true
|
||||
done
|
||||
done
|
||||
if ! $tested; then
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import re
|
||||
import argparse
|
||||
|
||||
if __name__=='__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('input')
|
||||
parser.add_argument('output')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.input, 'r') as inp:
|
||||
with open(args.output, 'w') as out:
|
||||
for l in inp.readlines():
|
||||
l = re.sub('_t_get_type', '_get_type', l)
|
||||
l = re.sub('_T \(', ' (', l)
|
||||
out.write(l)
|
|
@ -1,15 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function, division, absolute_import
|
||||
|
||||
import io, os.path, sys
|
||||
|
||||
if len (sys.argv) != 4:
|
||||
print ("""usage: ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
|
||||
|
||||
Input files, as of Unicode 12:
|
||||
* https://unicode.org/Public/UCD/latest/ucd/ArabicShaping.txt
|
||||
* https://unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
|
||||
* https://unicode.org/Public/UCD/latest/ucd/Blocks.txt
|
||||
""", file=sys.stderr)
|
||||
print ("usage: ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt", file=sys.stderr)
|
||||
sys.exit (1)
|
||||
|
||||
files = [io.open (x, encoding='utf-8') for x in sys.argv[1:]]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function, division, absolute_import
|
||||
|
||||
import io, os, re, sys
|
||||
|
||||
|
@ -13,35 +15,10 @@ for h in header_paths:
|
|||
if h.endswith (".h"):
|
||||
with io.open (h, encoding='utf-8') as f: headers_content.append (f.read ())
|
||||
|
||||
symbols = sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M))
|
||||
if '--experimental-api' not in sys.argv:
|
||||
# Move these to harfbuzz-sections.txt when got stable
|
||||
experimental_symbols = \
|
||||
"""hb_font_draw_glyph
|
||||
hb_draw_funcs_t
|
||||
hb_draw_close_path_func_t
|
||||
hb_draw_cubic_to_func_t
|
||||
hb_draw_line_to_func_t
|
||||
hb_draw_move_to_func_t
|
||||
hb_draw_quadratic_to_func_t
|
||||
hb_draw_funcs_create
|
||||
hb_draw_funcs_destroy
|
||||
hb_draw_funcs_is_immutable
|
||||
hb_draw_funcs_make_immutable
|
||||
hb_draw_funcs_reference
|
||||
hb_draw_funcs_set_close_path_func
|
||||
hb_draw_funcs_set_cubic_to_func
|
||||
hb_draw_funcs_set_line_to_func
|
||||
hb_draw_funcs_set_move_to_func
|
||||
hb_draw_funcs_set_quadratic_to_func
|
||||
hb_font_get_var_coords_design
|
||||
hb_ot_layout_closure_lookups
|
||||
hb_ot_layout_closure_features""".splitlines ()
|
||||
symbols = [x for x in symbols if x not in experimental_symbols]
|
||||
symbols = "\n".join (symbols)
|
||||
symbols = "\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M)))
|
||||
|
||||
result = symbols if os.environ.get('PLAIN_LIST', '') else """EXPORTS
|
||||
%s
|
||||
LIBRARY lib%s-0.dll""" % (symbols, output_file.replace ('src/', '').replace ('.def', ''))
|
||||
LIBRARY lib%s-0.dll""" % (symbols, output_file.replace ('.def', ''))
|
||||
|
||||
with open (output_file, "w") as f: f.write (result)
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/python
|
||||
|
||||
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
|
||||
|
||||
Input file, as of Unicode 12:
|
||||
* https://www.unicode.org/Public/emoji/12.0/emoji-data.txt""", file=sys.stderr)
|
||||
print("usage: ./gen-emoji-table.py emoji-data.txt", file=sys.stderr)
|
||||
sys.exit (1)
|
||||
|
||||
f = open(sys.argv[1])
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function, division, absolute_import
|
||||
|
||||
import io, sys
|
||||
|
||||
if len (sys.argv) != 4:
|
||||
print ("""usage: ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
|
||||
|
||||
Input files, as of Unicode 12:
|
||||
* https://unicode.org/Public/UCD/latest/ucd/IndicSyllabicCategory.txt
|
||||
* https://unicode.org/Public/UCD/latest/ucd/IndicPositionalCategory.txt
|
||||
* https://unicode.org/Public/UCD/latest/ucd/Blocks.txt""", file=sys.stderr)
|
||||
print ("usage: ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt", file=sys.stderr)
|
||||
sys.exit (1)
|
||||
|
||||
ALLOWED_SINGLES = [0x00A0, 0x25CC]
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/python
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Generates the code for a sorted unicode range array as used in hb-ot-os2-unicode-ranges.hh
|
||||
# Input is a tab seperated list of unicode ranges from the otspec
|
||||
# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur).
|
||||
|
||||
from __future__ import print_function, division, absolute_import
|
||||
|
||||
import io
|
||||
import re
|
||||
import sys
|
||||
|
||||
try:
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf-8')
|
||||
except NameError:
|
||||
pass # Python 3
|
||||
|
||||
print ("""static OS2Range _hb_os2_unicode_ranges[] =
|
||||
{""")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/python
|
||||
|
||||
"""Generator of the mapping from OpenType tags to BCP 47 tags and vice
|
||||
versa.
|
||||
|
@ -18,11 +18,18 @@ first BCP 47 tag happens to be the chosen disambiguated tag. In that
|
|||
case, the fallback behavior will choose the right tag anyway.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import collections
|
||||
from html.parser import HTMLParser
|
||||
def write (s):
|
||||
sys.stdout.flush ()
|
||||
sys.stdout.buffer.write (s.encode ('utf-8'))
|
||||
try:
|
||||
from HTMLParser import HTMLParser
|
||||
def write (s):
|
||||
print (s.encode ('utf-8'), end='')
|
||||
except ImportError:
|
||||
from html.parser import HTMLParser
|
||||
def write (s):
|
||||
sys.stdout.flush ()
|
||||
sys.stdout.buffer.write (s.encode ('utf-8'))
|
||||
import io
|
||||
import itertools
|
||||
import re
|
||||
|
@ -30,16 +37,16 @@ import sys
|
|||
import unicodedata
|
||||
|
||||
if len (sys.argv) != 3:
|
||||
print ('''usage: ./gen-tag-table.py languagetags language-subtag-registry
|
||||
|
||||
Input files, as of Unicode 12:
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
|
||||
* https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry''', file=sys.stderr)
|
||||
print ('usage: ./gen-tag-table.py languagetags language-subtag-registry', file=sys.stderr)
|
||||
sys.exit (1)
|
||||
|
||||
from html import unescape
|
||||
def html_unescape (parser, entity):
|
||||
return unescape (entity)
|
||||
try:
|
||||
from html import unescape
|
||||
def html_unescape (parser, entity):
|
||||
return unescape (entity)
|
||||
except ImportError:
|
||||
def html_unescape (parser, entity):
|
||||
return parser.unescape (entity)
|
||||
|
||||
def expect (condition, message=None):
|
||||
if not condition:
|
||||
|
@ -47,7 +54,7 @@ def expect (condition, message=None):
|
|||
raise AssertionError
|
||||
raise AssertionError (message)
|
||||
|
||||
# from https://www-01.sil.org/iso639-3/iso-639-3.tab
|
||||
# from http://www-01.sil.org/iso639-3/iso-639-3.tab
|
||||
ISO_639_3_TO_1 = {
|
||||
'aar': 'aa',
|
||||
'abk': 'ab',
|
||||
|
@ -747,7 +754,7 @@ ot.add_language ('und-Syre', 'SYRE')
|
|||
ot.add_language ('und-Syrj', 'SYRJ')
|
||||
ot.add_language ('und-Syrn', 'SYRN')
|
||||
|
||||
bcp_47.names['xst'] = "Silt'e"
|
||||
bcp_47.names['xst'] = u"Silt'e"
|
||||
bcp_47.scopes['xst'] = ' (retired code)'
|
||||
bcp_47.macrolanguages['xst'] = {'stv', 'wle'}
|
||||
|
||||
|
@ -854,7 +861,7 @@ def hb_tag (tag):
|
|||
Returns:
|
||||
A snippet of C++ representing ``tag``.
|
||||
"""
|
||||
return "HB_TAG('%s','%s','%s','%s')" % tuple (('%-4s' % tag)[:4])
|
||||
return u"HB_TAG('%s','%s','%s','%s')" % tuple (('%-4s' % tag)[:4])
|
||||
|
||||
def get_variant_set (name):
|
||||
"""Return a set of variant language names from a name.
|
||||
|
@ -866,7 +873,7 @@ def get_variant_set (name):
|
|||
Returns:
|
||||
A set of normalized language names.
|
||||
"""
|
||||
return set (unicodedata.normalize ('NFD', n.replace ('\u2019', "'"))
|
||||
return set (unicodedata.normalize ('NFD', n.replace ('\u2019', u"'"))
|
||||
.encode ('ASCII', 'ignore')
|
||||
.strip ()
|
||||
for n in re.split ('[\n(),]', name) if n)
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function, division, absolute_import
|
||||
|
||||
import io, os.path, sys, re
|
||||
import logging
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
|
||||
|
||||
if len (sys.argv) not in (2, 3):
|
||||
print("""usage: ./gen-ucd-table ucd.nounihan.grouped.xml [/path/to/hb-common.h]
|
||||
|
||||
Input file, as of Unicode 12:
|
||||
* https://unicode.org/Public/UCD/latest/ucdxml/ucd.nounihan.grouped.zip""", file=sys.stderr)
|
||||
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
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
# flake8: noqa
|
||||
|
||||
from __future__ import print_function, division, absolute_import
|
||||
|
||||
import io
|
||||
import sys
|
||||
|
||||
if len (sys.argv) != 5:
|
||||
print ("""usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
|
||||
|
||||
Input file, as of Unicode 12:
|
||||
* https://unicode.org/Public/UCD/latest/ucd/IndicSyllabicCategory.txt
|
||||
* https://unicode.org/Public/UCD/latest/ucd/IndicPositionalCategory.txt
|
||||
* https://unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
|
||||
* https://unicode.org/Public/UCD/latest/ucd/Blocks.txt""", file=sys.stderr)
|
||||
print ("usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt", file=sys.stderr)
|
||||
sys.exit (1)
|
||||
|
||||
BLACKLISTED_BLOCKS = ["Thai", "Lao"]
|
||||
|
@ -151,13 +147,18 @@ property_names = [
|
|||
'Overstruck',
|
||||
]
|
||||
|
||||
try:
|
||||
basestring
|
||||
except NameError:
|
||||
basestring = str
|
||||
|
||||
class PropertyValue(object):
|
||||
def __init__(self, name_):
|
||||
self.name = name_
|
||||
def __str__(self):
|
||||
return self.name
|
||||
def __eq__(self, other):
|
||||
return self.name == (other if isinstance(other, str) else other.name)
|
||||
return self.name == (other if isinstance(other, basestring) else other.name)
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
def __hash__(self):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/python
|
||||
|
||||
"""Generator of the function to prohibit certain vowel sequences.
|
||||
|
||||
|
@ -6,23 +6,26 @@ It creates ``_hb_preprocess_text_vowel_constraints``, which inserts dotted
|
|||
circles into sequences prohibited by the USE script development spec.
|
||||
This function should be used as the ``preprocess_text`` of an
|
||||
``hb_ot_complex_shaper_t``.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import collections
|
||||
from html.parser import HTMLParser
|
||||
def write (s):
|
||||
sys.stdout.flush ()
|
||||
sys.stdout.buffer.write (s.encode ('utf-8'))
|
||||
try:
|
||||
from HTMLParser import HTMLParser
|
||||
def write (s):
|
||||
print (s.encode ('utf-8'), end='')
|
||||
except ImportError:
|
||||
from html.parser import HTMLParser
|
||||
def write (s):
|
||||
sys.stdout.flush ()
|
||||
sys.stdout.buffer.write (s.encode ('utf-8'))
|
||||
import itertools
|
||||
import io
|
||||
import sys
|
||||
|
||||
if len (sys.argv) != 3:
|
||||
print ("""usage: ./gen-vowel-constraints.py ms-use/IndicShapingInvalidCluster.txt Scripts.txt
|
||||
|
||||
Input file, as of Unicode 12:
|
||||
* https://unicode.org/Public/UCD/latest/ucd/Scripts.txt""", file=sys.stderr)
|
||||
print ('usage: ./gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt', file=sys.stderr)
|
||||
sys.exit (1)
|
||||
|
||||
with io.open (sys.argv[2], encoding='utf-8') as f:
|
||||
|
@ -81,8 +84,7 @@ class ConstraintSet (object):
|
|||
else:
|
||||
self._c[first] = ConstraintSet (rest)
|
||||
|
||||
@staticmethod
|
||||
def _indent (depth):
|
||||
def _indent (self, depth):
|
||||
return (' ' * depth).replace (' ', '\t')
|
||||
|
||||
def __str__ (self, index=0, depth=4):
|
||||
|
@ -90,20 +92,17 @@ class ConstraintSet (object):
|
|||
indent = self._indent (depth)
|
||||
if isinstance (self._c, list):
|
||||
if len (self._c) == 0:
|
||||
assert index == 2, 'Cannot use `matched` for this constraint; the general case has not been implemented'
|
||||
s.append ('{}matched = true;\n'.format (indent))
|
||||
elif len (self._c) == 1:
|
||||
assert index == 1, 'Cannot use `matched` for this constraint; the general case has not been implemented'
|
||||
s.append ('{}matched = 0x{:04X}u == buffer->cur ({}).codepoint;\n'.format (indent, next (iter (self._c)), index or ''))
|
||||
else:
|
||||
s.append ('{}if (0x{:04X}u == buffer->cur ({}).codepoint &&\n'.format (indent, self._c[0], index or ''))
|
||||
if index:
|
||||
s.append ('{}buffer->idx + {} < count &&\n'.format (self._indent (depth + 2), index + 1))
|
||||
s.append ('{}if (0x{:04X}u == buffer->cur ({}).codepoint &&\n'.format (indent, self._c[0], index))
|
||||
s.append ('{}buffer->idx + {} < count &&\n'.format (self._indent (depth + 2), len (self._c)))
|
||||
for i, cp in enumerate (self._c[1:], start=1):
|
||||
s.append ('{}0x{:04X}u == buffer->cur ({}).codepoint{}\n'.format (
|
||||
self._indent (depth + 2), cp, index + i, ')' if i == len (self._c) - 1 else ' &&'))
|
||||
s.append ('{}{{\n'.format (indent))
|
||||
for i in range (index + 1):
|
||||
for i in range (len (self._c)):
|
||||
s.append ('{}buffer->next_glyph ();\n'.format (self._indent (depth + 1)))
|
||||
s.append ('{}_output_dotted_circle (buffer);\n'.format (self._indent (depth + 1)))
|
||||
s.append ('{}}}\n'.format (indent))
|
||||
|
@ -129,12 +128,7 @@ class ConstraintSet (object):
|
|||
|
||||
constraints = {}
|
||||
with io.open (sys.argv[1], encoding='utf-8') as f:
|
||||
constraints_header = []
|
||||
while True:
|
||||
line = f.readline ().strip ()
|
||||
if line == '#':
|
||||
break
|
||||
constraints_header.append(line)
|
||||
constraints_header = [f.readline ().strip () for i in range (2)]
|
||||
for line in f:
|
||||
j = line.find ('#')
|
||||
if j >= 0:
|
||||
|
@ -153,7 +147,7 @@ print ('/* == Start of generated functions == */')
|
|||
print ('/*')
|
||||
print (' * The following functions are generated by running:')
|
||||
print (' *')
|
||||
print (' * %s ms-use/IndicShapingInvalidCluster.txt Scripts.txt' % sys.argv[0])
|
||||
print (' * %s use Scripts.txt' % sys.argv[0])
|
||||
print (' *')
|
||||
print (' * on files with these headers:')
|
||||
print (' *')
|
||||
|
@ -191,7 +185,7 @@ print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB
|
|||
print ('\t\t\t\t hb_buffer_t *buffer,')
|
||||
print ('\t\t\t\t hb_font_t *font HB_UNUSED)')
|
||||
print ('{')
|
||||
print ('#ifdef HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS')
|
||||
print ('#if defined(HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS)')
|
||||
print (' return;')
|
||||
print ('#endif')
|
||||
print (' if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)')
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include "hb-buffer-serialize.cc"
|
||||
#include "hb-buffer.cc"
|
||||
#include "hb-common.cc"
|
||||
#include "hb-draw.cc"
|
||||
#include "hb-face.cc"
|
||||
#include "hb-fallback-shape.cc"
|
||||
#include "hb-font.cc"
|
||||
|
|
|
@ -65,7 +65,7 @@ struct FontDescriptor
|
|||
protected:
|
||||
Tag tag; /* The 4-byte table tag name. */
|
||||
union {
|
||||
HBFixed value; /* The value for the descriptor tag. */
|
||||
HBFixed value; /* The value for the descriptor tag. */
|
||||
HBUINT32 nalfType; /* If the tag is `nalf`, see non_alphabetic_value_t */
|
||||
} u;
|
||||
public:
|
||||
|
@ -80,10 +80,10 @@ struct fdsc
|
|||
Weight = HB_TAG ('w','g','h','t'),
|
||||
/* Percent weight relative to regular weight.
|
||||
* (defaul value: 1.0) */
|
||||
Width = HB_TAG ('w','d','t','h'),
|
||||
Width = HB_TAG ('w','d','t','h'),
|
||||
/* Percent width relative to regular width.
|
||||
* (default value: 1.0) */
|
||||
Slant = HB_TAG ('s','l','n','t'),
|
||||
Slant = HB_TAG ('s','l','n','t'),
|
||||
/* Angle of slant in degrees, where positive
|
||||
* is clockwise from straight up.
|
||||
* (default value: 0.0) */
|
||||
|
@ -108,7 +108,7 @@ struct fdsc
|
|||
}
|
||||
|
||||
protected:
|
||||
HBFixed version; /* Version number of the font descriptors
|
||||
HBFixed version; /* Version number of the font descriptors
|
||||
* table (0x00010000 for the current version). */
|
||||
LArrayOf<FontDescriptor>
|
||||
descriptors; /* List of tagged-coordinate pairs style descriptors
|
||||
|
|
|
@ -66,7 +66,7 @@ struct ankr
|
|||
{
|
||||
const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
|
||||
if (!offset)
|
||||
return Null (Anchor);
|
||||
return Null(Anchor);
|
||||
const GlyphAnchors &anchors = &(this+anchorData) + *offset;
|
||||
return anchors[i];
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ struct ankr
|
|||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Version number (set to zero) */
|
||||
HBUINT16 version; /* Version number (set to zero) */
|
||||
HBUINT16 flags; /* Flags (currently unused; set to zero) */
|
||||
LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors>>>
|
||||
lookupTable; /* Offset to the table's lookup table */
|
||||
|
|
|
@ -303,7 +303,7 @@ struct LookupFormat10
|
|||
const typename T::type get_value_or_null (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
if (!(firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount))
|
||||
return Null (T);
|
||||
return Null(T);
|
||||
|
||||
const HBUINT8 *p = &valueArrayZ[(glyph_id - firstGlyph) * valueSize];
|
||||
|
||||
|
@ -358,7 +358,7 @@ struct Lookup
|
|||
case 10: return u.format10.get_value_or_null (glyph_id);
|
||||
default:
|
||||
const T *v = get_value (glyph_id, num_glyphs);
|
||||
return v ? *v : Null (T);
|
||||
return v ? *v : Null(T);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -825,7 +825,7 @@ struct hb_aat_apply_context_t :
|
|||
HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
|
||||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_,
|
||||
hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
|
||||
hb_blob_t *blob = const_cast<hb_blob_t *> (&Null(hb_blob_t)));
|
||||
|
||||
HB_INTERNAL ~hb_aat_apply_context_t ();
|
||||
|
||||
|
|
|
@ -129,11 +129,6 @@ struct FeatureName
|
|||
|
||||
hb_ot_name_id_t get_feature_name_id () const { return nameIndex; }
|
||||
|
||||
bool is_exclusive () const { return featureFlags & Exclusive; }
|
||||
|
||||
/* A FeatureName with no settings is meaningless */
|
||||
bool has_data () const { return nSettings; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -144,7 +139,7 @@ struct FeatureName
|
|||
protected:
|
||||
HBUINT16 feature; /* Feature type. */
|
||||
HBUINT16 nSettings; /* The number of records in the setting name array. */
|
||||
LNNOffsetTo<UnsizedArrayOf<SettingName>>
|
||||
LOffsetTo<UnsizedArrayOf<SettingName>, false>
|
||||
settingTableZ; /* Offset in bytes from the beginning of this table to
|
||||
* this feature's setting name array. The actual type of
|
||||
* record this offset refers to will depend on the
|
||||
|
@ -177,9 +172,6 @@ struct feat
|
|||
return featureNameCount;
|
||||
}
|
||||
|
||||
bool exposes_feature (hb_aat_layout_feature_type_t feature_type) const
|
||||
{ return get_feature (feature_type).has_data (); }
|
||||
|
||||
const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
|
||||
{ return namesZ.bsearch (featureNameCount, feature_type); }
|
||||
|
||||
|
|
|
@ -51,10 +51,10 @@ struct ActionSubrecordHeader
|
|||
return_trace (likely (c->check_struct (this)));
|
||||
}
|
||||
|
||||
HBUINT16 actionClass; /* The JustClass value associated with this
|
||||
HBUINT16 actionClass; /* The JustClass value associated with this
|
||||
* ActionSubrecord. */
|
||||
HBUINT16 actionType; /* The type of postcompensation action. */
|
||||
HBUINT16 actionLength; /* Length of this ActionSubrecord record, which
|
||||
HBUINT16 actionType; /* The type of postcompensation action. */
|
||||
HBUINT16 actionLength; /* Length of this ActionSubrecord record, which
|
||||
* must be a multiple of 4. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
|
@ -70,11 +70,11 @@ struct DecompositionAction
|
|||
|
||||
ActionSubrecordHeader
|
||||
header;
|
||||
HBFixed lowerLimit; /* If the distance factor is less than this value,
|
||||
HBFixed lowerLimit; /* If the distance factor is less than this value,
|
||||
* then the ligature is decomposed. */
|
||||
HBFixed upperLimit; /* If the distance factor is greater than this value,
|
||||
HBFixed upperLimit; /* If the distance factor is greater than this value,
|
||||
* then the ligature is decomposed. */
|
||||
HBUINT16 order; /* Numerical order in which this ligature will
|
||||
HBUINT16 order; /* Numerical order in which this ligature will
|
||||
* be decomposed; you may want infrequent ligatures
|
||||
* to decompose before more frequent ones. The ligatures
|
||||
* on the line of text will decompose in increasing
|
||||
|
@ -118,14 +118,14 @@ struct ConditionalAddGlyphAction
|
|||
protected:
|
||||
ActionSubrecordHeader
|
||||
header;
|
||||
HBFixed substThreshold; /* Distance growth factor (in ems) at which
|
||||
HBFixed substThreshold; /* Distance growth factor (in ems) at which
|
||||
* this glyph is replaced and the growth factor
|
||||
* recalculated. */
|
||||
HBGlyphID addGlyph; /* Glyph to be added as kashida. If this value is
|
||||
HBGlyphID addGlyph; /* Glyph to be added as kashida. If this value is
|
||||
* 0xFFFF, no extra glyph will be added. Note that
|
||||
* generally when a glyph is added, justification
|
||||
* will need to be redone. */
|
||||
HBGlyphID substGlyph; /* Glyph to be substituted for this glyph if the
|
||||
HBGlyphID substGlyph; /* Glyph to be substituted for this glyph if the
|
||||
* growth factor equals or exceeds the value of
|
||||
* substThreshold. */
|
||||
public:
|
||||
|
@ -143,16 +143,16 @@ struct DuctileGlyphAction
|
|||
protected:
|
||||
ActionSubrecordHeader
|
||||
header;
|
||||
HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
|
||||
HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
|
||||
* This would normally be 0x64756374 ('duct'),
|
||||
* but you may use any axis the font contains. */
|
||||
HBFixed minimumLimit; /* The lowest value for the ductility axis tha
|
||||
HBFixed minimumLimit; /* The lowest value for the ductility axis tha
|
||||
* still yields an acceptable appearance. Normally
|
||||
* this will be 1.0. */
|
||||
HBFixed noStretchValue; /* This is the default value that corresponds to
|
||||
HBFixed noStretchValue; /* This is the default value that corresponds to
|
||||
* no change in appearance. Normally, this will
|
||||
* be 1.0. */
|
||||
HBFixed maximumLimit; /* The highest value for the ductility axis that
|
||||
HBFixed maximumLimit; /* The highest value for the ductility axis that
|
||||
* still yields an acceptable appearance. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (22);
|
||||
|
@ -169,8 +169,8 @@ struct RepeatedAddGlyphAction
|
|||
protected:
|
||||
ActionSubrecordHeader
|
||||
header;
|
||||
HBUINT16 flags; /* Currently unused; set to 0. */
|
||||
HBGlyphID glyph; /* Glyph that should be added if the distance factor
|
||||
HBUINT16 flags; /* Currently unused; set to 0. */
|
||||
HBGlyphID glyph; /* Glyph that should be added if the distance factor
|
||||
* is growing. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (10);
|
||||
|
@ -271,14 +271,14 @@ struct JustWidthDeltaEntry
|
|||
};
|
||||
|
||||
protected:
|
||||
HBFixed beforeGrowLimit;/* The ratio by which the advance width of the
|
||||
HBFixed beforeGrowLimit;/* The ratio by which the advance width of the
|
||||
* glyph is permitted to grow on the left or top side. */
|
||||
HBFixed beforeShrinkLimit;
|
||||
HBFixed beforeShrinkLimit;
|
||||
/* The ratio by which the advance width of the
|
||||
* glyph is permitted to shrink on the left or top side. */
|
||||
HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph
|
||||
HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph
|
||||
* is permitted to shrink on the left or top side. */
|
||||
HBFixed afterShrinkLimit;
|
||||
HBFixed afterShrinkLimit;
|
||||
/* The ratio by which the advance width of the glyph
|
||||
* is at most permitted to shrink on the right or
|
||||
* bottom side. */
|
||||
|
@ -361,7 +361,7 @@ struct JustificationHeader
|
|||
OffsetTo<JustificationCategory>
|
||||
justClassTable; /* Offset to the justification category state table. */
|
||||
OffsetTo<WidthDeltaCluster>
|
||||
wdcTable; /* Offset from start of justification table to start
|
||||
wdcTable; /* Offset from start of justification table to start
|
||||
* of the subtable containing the width delta factors
|
||||
* for the glyphs in your font.
|
||||
*
|
||||
|
@ -372,7 +372,7 @@ struct JustificationHeader
|
|||
*
|
||||
* The postcompensation subtable, if present in the font. */
|
||||
Lookup<OffsetTo<WidthDeltaCluster>>
|
||||
lookupTable; /* Lookup table associating glyphs with width delta
|
||||
lookupTable; /* Lookup table associating glyphs with width delta
|
||||
* clusters. See the description of Width Delta Clusters
|
||||
* table for details on how to interpret the lookup values. */
|
||||
|
||||
|
@ -397,7 +397,7 @@ struct just
|
|||
protected:
|
||||
FixedVersion<>version; /* Version of the justification table
|
||||
* (0x00010000u for version 1.0). */
|
||||
HBUINT16 format; /* Format of the justification table (set to 0). */
|
||||
HBUINT16 format; /* Format of the justification table (set to 0). */
|
||||
OffsetTo<JustificationHeader>
|
||||
horizData; /* Byte offset from the start of the justification table
|
||||
* to the header for tables that contain justification
|
||||
|
|
|
@ -281,28 +281,35 @@ struct KerxSubTableFormat1
|
|||
|
||||
hb_glyph_position_t &o = buffer->pos[idx];
|
||||
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||
/* Testing shows that CoreText only applies kern (cross-stream or not)
|
||||
* if none has been applied by previous subtables. That is, it does
|
||||
* NOT seem to accumulate as otherwise implied by specs. */
|
||||
|
||||
/* The following flag is undocumented in the spec, but described
|
||||
* in the 'kern' table example. */
|
||||
if (v == -0x8000)
|
||||
{
|
||||
o.attach_type() = ATTACH_TYPE_NONE;
|
||||
o.attach_chain() = 0;
|
||||
o.x_offset = o.y_offset = 0;
|
||||
}
|
||||
else if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||
{
|
||||
if (crossStream)
|
||||
{
|
||||
/* The following flag is undocumented in the spec, but described
|
||||
* in the 'kern' table example. */
|
||||
if (v == -0x8000)
|
||||
if (buffer->pos[idx].attach_type() && !buffer->pos[idx].y_offset)
|
||||
{
|
||||
o.attach_type() = ATTACH_TYPE_NONE;
|
||||
o.attach_chain() = 0;
|
||||
o.y_offset = 0;
|
||||
}
|
||||
else if (o.attach_type())
|
||||
{
|
||||
o.y_offset += c->font->em_scale_y (v);
|
||||
o.y_offset = c->font->em_scale_y (v);
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
}
|
||||
}
|
||||
else if (buffer->info[idx].mask & kern_mask)
|
||||
{
|
||||
o.x_advance += c->font->em_scale_x (v);
|
||||
o.x_offset += c->font->em_scale_x (v);
|
||||
if (!buffer->pos[idx].x_offset)
|
||||
{
|
||||
buffer->pos[idx].x_advance += c->font->em_scale_x (v);
|
||||
buffer->pos[idx].x_offset += c->font->em_scale_x (v);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -310,22 +317,19 @@ struct KerxSubTableFormat1
|
|||
if (crossStream)
|
||||
{
|
||||
/* CoreText doesn't do crossStream kerning in vertical. We do. */
|
||||
if (v == -0x8000)
|
||||
if (buffer->pos[idx].attach_type() && !buffer->pos[idx].x_offset)
|
||||
{
|
||||
o.attach_type() = ATTACH_TYPE_NONE;
|
||||
o.attach_chain() = 0;
|
||||
o.x_offset = 0;
|
||||
}
|
||||
else if (o.attach_type())
|
||||
{
|
||||
o.x_offset += c->font->em_scale_x (v);
|
||||
o.x_offset = c->font->em_scale_x (v);
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
}
|
||||
}
|
||||
else if (buffer->info[idx].mask & kern_mask)
|
||||
{
|
||||
o.y_advance += c->font->em_scale_y (v);
|
||||
o.y_offset += c->font->em_scale_y (v);
|
||||
if (!buffer->pos[idx].y_offset)
|
||||
{
|
||||
buffer->pos[idx].y_advance += c->font->em_scale_y (v);
|
||||
buffer->pos[idx].y_offset += c->font->em_scale_y (v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -948,10 +948,8 @@ struct Chain
|
|||
hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType;
|
||||
hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting;
|
||||
retry:
|
||||
// Check whether this type/setting pair was requested in the map, and if so, apply its flags.
|
||||
// (The search here only looks at the type and setting fields of feature_info_t.)
|
||||
hb_aat_map_builder_t::feature_info_t info = { type, setting, false, 0 };
|
||||
if (map->features.bsearch (info))
|
||||
const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type);
|
||||
if (info && info->setting == setting)
|
||||
{
|
||||
flags &= feature.disableFlags;
|
||||
flags |= feature.enableFlags;
|
||||
|
|
|
@ -160,8 +160,8 @@ struct opbd
|
|||
* Format 0 indicates distance and Format 1 indicates
|
||||
* control point. */
|
||||
union {
|
||||
opbdFormat0 format0;
|
||||
opbdFormat1 format1;
|
||||
opbdFormat0 format0;
|
||||
opbdFormat1 format1;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (8);
|
||||
|
|
|
@ -62,7 +62,7 @@ struct TrackTableEntry
|
|||
}
|
||||
|
||||
protected:
|
||||
HBFixed track; /* Track value for this record. */
|
||||
HBFixed track; /* Track value for this record. */
|
||||
NameID trackNameID; /* The 'name' table index for this track.
|
||||
* (a short word or phrase like "loose"
|
||||
* or "very tight") */
|
||||
|
@ -141,7 +141,7 @@ struct TrackData
|
|||
protected:
|
||||
HBUINT16 nTracks; /* Number of separate tracks included in this table. */
|
||||
HBUINT16 nSizes; /* Number of point sizes included in this table. */
|
||||
LNNOffsetTo<UnsizedArrayOf<HBFixed>>
|
||||
LOffsetTo<UnsizedArrayOf<HBFixed>, false>
|
||||
sizeTable; /* Offset from start of the tracking table to
|
||||
* Array[nSizes] of size values.. */
|
||||
UnsizedArrayOf<TrackTableEntry>
|
||||
|
@ -210,8 +210,8 @@ struct trak
|
|||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version of the tracking table
|
||||
* (0x00010000u for version 1.0). */
|
||||
HBUINT16 format; /* Format of the tracking table (set to 0). */
|
||||
* (0x00010000u for version 1.0). */
|
||||
HBUINT16 format; /* Format of the tracking table (set to 0). */
|
||||
OffsetTo<TrackData>
|
||||
horizData; /* Offset from start of tracking table to TrackData
|
||||
* for horizontal text (or 0 if none). */
|
||||
|
|
|
@ -55,7 +55,7 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p
|
|||
face (font->face),
|
||||
buffer (buffer_),
|
||||
sanitizer (),
|
||||
ankr_table (&Null (AAT::ankr)),
|
||||
ankr_table (&Null(AAT::ankr)),
|
||||
lookup_index (0),
|
||||
debug_depth (0)
|
||||
{
|
||||
|
@ -172,7 +172,11 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
|
|||
const hb_aat_feature_mapping_t *
|
||||
hb_aat_layout_find_feature_mapping (hb_tag_t tag)
|
||||
{
|
||||
return hb_sorted_array (feature_mappings).bsearch (tag);
|
||||
return (const hb_aat_feature_mapping_t *) hb_bsearch (&tag,
|
||||
feature_mappings,
|
||||
ARRAY_LENGTH (feature_mappings),
|
||||
sizeof (feature_mappings[0]),
|
||||
hb_aat_feature_mapping_t::cmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -39,8 +39,14 @@ struct hb_aat_feature_mapping_t
|
|||
hb_aat_layout_feature_selector_t selectorToEnable;
|
||||
hb_aat_layout_feature_selector_t selectorToDisable;
|
||||
|
||||
int cmp (hb_tag_t key) const
|
||||
{ return key < otFeatureTag ? -1 : key > otFeatureTag ? 1 : 0; }
|
||||
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
|
||||
{
|
||||
hb_tag_t key = * (unsigned int *) key_;
|
||||
const hb_aat_feature_mapping_t * entry = (const hb_aat_feature_mapping_t *) entry_;
|
||||
return key < entry->otFeatureTag ? -1 :
|
||||
key > entry->otFeatureTag ? 1 :
|
||||
0;
|
||||
}
|
||||
};
|
||||
|
||||
HB_INTERNAL const hb_aat_feature_mapping_t *
|
||||
|
|
|
@ -33,48 +33,25 @@
|
|||
#include "hb-aat-map.hh"
|
||||
|
||||
#include "hb-aat-layout.hh"
|
||||
#include "hb-aat-layout-feat-table.hh"
|
||||
|
||||
|
||||
void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned value)
|
||||
void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
|
||||
unsigned int value)
|
||||
{
|
||||
if (!face->table.feat->has_data ()) return;
|
||||
|
||||
if (tag == HB_TAG ('a','a','l','t'))
|
||||
{
|
||||
if (!face->table.feat->exposes_feature (HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES))
|
||||
return;
|
||||
feature_info_t *info = features.push();
|
||||
info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
|
||||
info->setting = (hb_aat_layout_feature_selector_t) value;
|
||||
info->seq = features.length;
|
||||
info->is_exclusive = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
|
||||
if (!mapping) return;
|
||||
|
||||
const AAT::FeatureName* feature = &face->table.feat->get_feature (mapping->aatFeatureType);
|
||||
if (!feature->has_data ())
|
||||
{
|
||||
/* Special case: Chain::compile_flags will fall back to the deprecated version of
|
||||
* small-caps if necessary, so we need to check for that possibility.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/2307 */
|
||||
if (mapping->aatFeatureType == HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE &&
|
||||
mapping->selectorToEnable == HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS)
|
||||
{
|
||||
feature = &face->table.feat->get_feature (HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE);
|
||||
if (!feature->has_data ()) return;
|
||||
}
|
||||
else return;
|
||||
}
|
||||
|
||||
feature_info_t *info = features.push();
|
||||
info->type = mapping->aatFeatureType;
|
||||
info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
|
||||
info->seq = features.length;
|
||||
info->is_exclusive = feature->is_exclusive ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -86,11 +63,7 @@ hb_aat_map_builder_t::compile (hb_aat_map_t &m)
|
|||
features.qsort ();
|
||||
unsigned int j = 0;
|
||||
for (unsigned int i = 1; i < features.length; i++)
|
||||
if (features[i].type != features[j].type ||
|
||||
/* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
|
||||
* respectively, so we mask out the low-order bit when checking for "duplicates"
|
||||
* (selectors referring to the same feature setting) here. */
|
||||
(!features[i].is_exclusive && ((features[i].setting & ~1) != (features[j].setting & ~1))))
|
||||
if (features[i].type != features[j].type)
|
||||
features[++j] = features[i];
|
||||
features.shrink (j + 1);
|
||||
}
|
||||
|
|
|
@ -64,24 +64,19 @@ struct hb_aat_map_builder_t
|
|||
{
|
||||
hb_aat_layout_feature_type_t type;
|
||||
hb_aat_layout_feature_selector_t setting;
|
||||
bool is_exclusive;
|
||||
unsigned seq; /* For stable sorting only. */
|
||||
|
||||
HB_INTERNAL static int cmp (const void *pa, const void *pb)
|
||||
{
|
||||
const feature_info_t *a = (const feature_info_t *) pa;
|
||||
const feature_info_t *b = (const feature_info_t *) pb;
|
||||
if (a->type != b->type) return (a->type < b->type ? -1 : 1);
|
||||
if (!a->is_exclusive &&
|
||||
(a->setting & ~1) != (b->setting & ~1)) return (a->setting < b->setting ? -1 : 1);
|
||||
return (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
|
||||
return (a->type != b->type) ? (a->type < b->type ? -1 : 1) :
|
||||
(a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
|
||||
}
|
||||
|
||||
/* compares type & setting only, not is_exclusive flag or seq number */
|
||||
int cmp (const feature_info_t& f) const
|
||||
int cmp (hb_aat_layout_feature_type_t ty) const
|
||||
{
|
||||
return (f.type != type) ? (f.type < type ? -1 : 1) :
|
||||
(f.setting != setting) ? (f.setting < setting ? -1 : 1) : 0;
|
||||
return (type != ty) ? (type < ty ? -1 : 1) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -360,13 +360,6 @@ struct
|
|||
(hb_forward<T> (a) >= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
|
||||
}
|
||||
HB_FUNCOBJ (hb_max);
|
||||
struct
|
||||
{
|
||||
template <typename T, typename T2, typename T3> constexpr auto
|
||||
operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN
|
||||
(hb_min (hb_max (hb_forward<T> (x), hb_forward<T2> (min)), hb_forward<T3> (max)))
|
||||
}
|
||||
HB_FUNCOBJ (hb_clamp);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -493,7 +486,7 @@ template <typename T>
|
|||
static inline HB_CONST_FUNC unsigned int
|
||||
hb_ctz (T v)
|
||||
{
|
||||
if (unlikely (!v)) return 8 * sizeof (T);
|
||||
if (unlikely (!v)) return 0;
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
|
@ -607,6 +600,12 @@ hb_memset (void *s, int c, unsigned int n)
|
|||
return memset (s, c, n);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
|
||||
{
|
||||
return (size > 0) && (count >= ((unsigned int) -1) / size);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
hb_ceil_to_4 (unsigned int v)
|
||||
{
|
||||
|
@ -634,91 +633,30 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Overflow checking.
|
||||
*/
|
||||
|
||||
/* Consider __builtin_mul_overflow use here also */
|
||||
static inline bool
|
||||
hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
|
||||
{
|
||||
return (size > 0) && (count >= ((unsigned int) -1) / size);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sort and search.
|
||||
*/
|
||||
|
||||
template <typename K, typename V, typename ...Ts>
|
||||
static int
|
||||
_hb_cmp_method (const void *pkey, const void *pval, Ts... ds)
|
||||
template <typename ...Ts>
|
||||
static inline void *
|
||||
hb_bsearch (const void *key, const void *base,
|
||||
size_t nmemb, size_t size,
|
||||
int (*compar)(const void *_key, const void *_item, Ts... _ds),
|
||||
Ts... ds)
|
||||
{
|
||||
const K& key = * (const K*) pkey;
|
||||
const V& val = * (const V*) pval;
|
||||
|
||||
return val.cmp (key, ds...);
|
||||
}
|
||||
|
||||
template <typename V, typename K, typename ...Ts>
|
||||
static inline bool
|
||||
hb_bsearch_impl (unsigned *pos, /* Out */
|
||||
const K& key,
|
||||
V* base, size_t nmemb, size_t stride,
|
||||
int (*compar)(const void *_key, const void *_item, Ts... _ds),
|
||||
Ts... ds)
|
||||
{
|
||||
/* This is our *only* bsearch implementation. */
|
||||
|
||||
int min = 0, max = (int) nmemb - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = ((unsigned int) min + (unsigned int) max) / 2;
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
V* p = (V*) (((const char *) base) + (mid * stride));
|
||||
#pragma GCC diagnostic pop
|
||||
int c = compar ((const void *) hb_addressof (key), (const void *) p, ds...);
|
||||
const void *p = (const void *) (((const char *) base) + (mid * size));
|
||||
int c = compar (key, p, ds...);
|
||||
if (c < 0)
|
||||
max = mid - 1;
|
||||
else if (c > 0)
|
||||
min = mid + 1;
|
||||
else
|
||||
{
|
||||
*pos = mid;
|
||||
return true;
|
||||
}
|
||||
return (void *) p;
|
||||
}
|
||||
*pos = min;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename V, typename K>
|
||||
static inline V*
|
||||
hb_bsearch (const K& key, V* base,
|
||||
size_t nmemb, size_t stride = sizeof (V),
|
||||
int (*compar)(const void *_key, const void *_item) = _hb_cmp_method<K, V>)
|
||||
{
|
||||
unsigned pos;
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar) ?
|
||||
(V*) (((const char *) base) + (pos * stride)) : nullptr;
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
template <typename V, typename K, typename ...Ts>
|
||||
static inline V*
|
||||
hb_bsearch (const K& key, V* base,
|
||||
size_t nmemb, size_t stride,
|
||||
int (*compar)(const void *_key, const void *_item, Ts... _ds),
|
||||
Ts... ds)
|
||||
{
|
||||
unsigned pos;
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar, ds...) ?
|
||||
(V*) (((const char *) base) + (pos * stride)) : nullptr;
|
||||
#pragma GCC diagnostic pop
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -171,24 +171,6 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
|
||||
unsigned int get_size () const { return length * this->get_item_size (); }
|
||||
|
||||
/*
|
||||
* Reverse the order of items in this array in the range [start, end).
|
||||
*/
|
||||
void reverse (unsigned start = 0, unsigned end = -1)
|
||||
{
|
||||
start = hb_min (start, length);
|
||||
end = hb_min (end, length);
|
||||
|
||||
if (end < start + 2)
|
||||
return;
|
||||
|
||||
for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--) {
|
||||
Type temp = arrayZ[rhs];
|
||||
arrayZ[rhs] = arrayZ[lhs];
|
||||
arrayZ[lhs] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
|
||||
{
|
||||
if (!start_offset && !seg_count)
|
||||
|
@ -217,11 +199,10 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
template <typename T,
|
||||
unsigned P = sizeof (Type),
|
||||
hb_enable_if (P == 1)>
|
||||
bool check_range (const T *p, unsigned int size = T::static_size) const
|
||||
bool in_range (const T *p, unsigned int size = T::static_size) const
|
||||
{
|
||||
return arrayZ <= ((const char *) p)
|
||||
&& ((const char *) p) <= arrayZ + length
|
||||
&& (unsigned int) (arrayZ + length - (const char *) p) >= size;
|
||||
return ((const char *) p) >= arrayZ
|
||||
&& ((const char *) p + size) <= arrayZ + length;
|
||||
}
|
||||
|
||||
/* Only call if you allocated the underlying array using malloc() or similar. */
|
||||
|
@ -319,15 +300,23 @@ struct hb_sorted_array_t :
|
|||
hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
|
||||
unsigned int to_store = (unsigned int) -1) const
|
||||
{
|
||||
unsigned pos;
|
||||
|
||||
if (bsearch_impl (x, &pos))
|
||||
int min = 0, max = (int) this->length - 1;
|
||||
const Type *array = this->arrayZ;
|
||||
while (min <= max)
|
||||
{
|
||||
if (i)
|
||||
*i = pos;
|
||||
return true;
|
||||
int mid = ((unsigned int) min + (unsigned int) max) / 2;
|
||||
int c = array[mid].cmp (x);
|
||||
if (c < 0)
|
||||
max = mid - 1;
|
||||
else if (c > 0)
|
||||
min = mid + 1;
|
||||
else
|
||||
{
|
||||
if (i)
|
||||
*i = mid;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
{
|
||||
switch (not_found)
|
||||
|
@ -340,22 +329,14 @@ struct hb_sorted_array_t :
|
|||
break;
|
||||
|
||||
case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
|
||||
*i = pos;
|
||||
if (max < 0 || (max < (int) this->length && array[max].cmp (x) > 0))
|
||||
max++;
|
||||
*i = max;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <typename T>
|
||||
bool bsearch_impl (const T &x, unsigned *pos) const
|
||||
{
|
||||
return hb_bsearch_impl (pos,
|
||||
x,
|
||||
this->arrayZ,
|
||||
this->length,
|
||||
sizeof (Type),
|
||||
_hb_cmp_method<T, Type>);
|
||||
}
|
||||
};
|
||||
template <typename T> inline hb_sorted_array_t<T>
|
||||
hb_sorted_array (T *array, unsigned int length)
|
||||
|
|
|
@ -151,9 +151,9 @@ struct hb_inc_bimap_t : hb_bimap_t
|
|||
|
||||
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
|
||||
work[rhs] = back_map[rhs];
|
||||
|
||||
|
||||
work.qsort (cmp_id);
|
||||
|
||||
|
||||
clear ();
|
||||
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
|
||||
set (work[rhs], rhs);
|
||||
|
|
|
@ -25,6 +25,18 @@
|
|||
* Red Hat Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1308
|
||||
* http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
|
||||
* https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html
|
||||
*/
|
||||
#if !defined(_POSIX_C_SOURCE) && !defined(_MSC_VER) && !defined(__NetBSD__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-macros"
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include "hb.hh"
|
||||
#include "hb-blob.hh"
|
||||
|
||||
|
@ -189,7 +201,7 @@ hb_blob_copy_writable_or_fail (hb_blob_t *blob)
|
|||
hb_blob_t *
|
||||
hb_blob_get_empty ()
|
||||
{
|
||||
return const_cast<hb_blob_t *> (&Null (hb_blob_t));
|
||||
return const_cast<hb_blob_t *> (&Null(hb_blob_t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -476,9 +488,6 @@ hb_blob_t::try_make_writable ()
|
|||
|
||||
#ifndef HB_NO_OPEN
|
||||
#ifdef HAVE_MMAP
|
||||
# if !defined(HB_NO_RESOURCE_FORK) && defined(__APPLE__)
|
||||
# include <sys/paths.h>
|
||||
# endif
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <fcntl.h>
|
||||
|
@ -523,39 +532,6 @@ _hb_mapped_file_destroy (void *file_)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef _PATH_RSRCFORKSPEC
|
||||
static int
|
||||
_open_resource_fork (const char *file_name, hb_mapped_file_t *file)
|
||||
{
|
||||
size_t name_len = strlen (file_name);
|
||||
size_t len = name_len + sizeof (_PATH_RSRCFORKSPEC);
|
||||
|
||||
char *rsrc_name = (char *) malloc (len);
|
||||
if (unlikely (!rsrc_name)) return -1;
|
||||
|
||||
strncpy (rsrc_name, file_name, name_len);
|
||||
strncpy (rsrc_name + name_len, _PATH_RSRCFORKSPEC,
|
||||
sizeof (_PATH_RSRCFORKSPEC) - 1);
|
||||
|
||||
int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0);
|
||||
free (rsrc_name);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
struct stat st;
|
||||
if (fstat (fd, &st) != -1)
|
||||
file->length = (unsigned long) st.st_size;
|
||||
else
|
||||
{
|
||||
close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_blob_create_from_file:
|
||||
* @file_name: font filename.
|
||||
|
@ -580,19 +556,6 @@ hb_blob_create_from_file (const char *file_name)
|
|||
if (unlikely (fstat (fd, &st) == -1)) goto fail;
|
||||
|
||||
file->length = (unsigned long) st.st_size;
|
||||
|
||||
#ifdef _PATH_RSRCFORKSPEC
|
||||
if (unlikely (file->length == 0))
|
||||
{
|
||||
int rfd = _open_resource_fork (file_name, file);
|
||||
if (rfd != -1)
|
||||
{
|
||||
close (fd);
|
||||
fd = rfd;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
file->contents = (char *) mmap (nullptr, file->length, PROT_READ,
|
||||
MAP_PRIVATE | MAP_NORESERVE, fd, 0);
|
||||
|
||||
|
@ -616,7 +579,7 @@ fail_without_close:
|
|||
HANDLE fd;
|
||||
unsigned int size = strlen (file_name) + 1;
|
||||
wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size);
|
||||
if (unlikely (!wchar_file_name)) goto fail_without_close;
|
||||
if (unlikely (wchar_file_name == nullptr)) goto fail_without_close;
|
||||
mbstowcs (wchar_file_name, file_name, size);
|
||||
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
|
||||
{
|
||||
|
@ -650,14 +613,14 @@ fail_without_close:
|
|||
file->length = (unsigned long) GetFileSize (fd, nullptr);
|
||||
file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||
#endif
|
||||
if (unlikely (!file->mapping)) goto fail;
|
||||
if (unlikely (file->mapping == nullptr)) goto fail;
|
||||
|
||||
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
|
||||
file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0);
|
||||
#else
|
||||
file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0);
|
||||
#endif
|
||||
if (unlikely (!file->contents)) goto fail;
|
||||
if (unlikely (file->contents == nullptr)) goto fail;
|
||||
|
||||
CloseHandle (fd);
|
||||
return hb_blob_create (file->contents, file->length,
|
||||
|
@ -675,10 +638,10 @@ fail_without_close:
|
|||
It's used as a fallback for systems without mmap or to read from pipes */
|
||||
unsigned long len = 0, allocated = BUFSIZ * 16;
|
||||
char *data = (char *) malloc (allocated);
|
||||
if (unlikely (!data)) return hb_blob_get_empty ();
|
||||
if (unlikely (data == nullptr)) return hb_blob_get_empty ();
|
||||
|
||||
FILE *fp = fopen (file_name, "rb");
|
||||
if (unlikely (!fp)) goto fread_fail_without_close;
|
||||
if (unlikely (fp == nullptr)) goto fread_fail_without_close;
|
||||
|
||||
while (!feof (fp))
|
||||
{
|
||||
|
@ -689,7 +652,7 @@ fail_without_close:
|
|||
can cover files like that but lets limit our fallback reader */
|
||||
if (unlikely (allocated > (2 << 28))) goto fread_fail;
|
||||
char *new_data = (char *) realloc (data, allocated);
|
||||
if (unlikely (!new_data)) goto fread_fail;
|
||||
if (unlikely (new_data == nullptr)) goto fread_fail;
|
||||
data = new_data;
|
||||
}
|
||||
|
||||
|
@ -703,7 +666,6 @@ fail_without_close:
|
|||
|
||||
len += addition;
|
||||
}
|
||||
fclose (fp);
|
||||
|
||||
return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data,
|
||||
(hb_destroy_func_t) free);
|
||||
|
|
|
@ -438,6 +438,13 @@ hb_buffer_t::set_masks (hb_mask_t value,
|
|||
if (!mask)
|
||||
return;
|
||||
|
||||
if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
info[i].mask = (info[i].mask & not_mask) | value;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
|
||||
|
@ -448,13 +455,27 @@ void
|
|||
hb_buffer_t::reverse_range (unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
if (end - start < 2)
|
||||
return;
|
||||
|
||||
hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end);
|
||||
for (i = start, j = end - 1; i < j; i++, j--) {
|
||||
hb_glyph_info_t t;
|
||||
|
||||
t = info[i];
|
||||
info[i] = info[j];
|
||||
info[j] = t;
|
||||
}
|
||||
|
||||
if (have_positions) {
|
||||
hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end);
|
||||
for (i = start, j = end - 1; i < j; i++, j--) {
|
||||
hb_glyph_position_t t;
|
||||
|
||||
t = pos[i];
|
||||
pos[i] = pos[j];
|
||||
pos[j] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,7 +612,7 @@ done:
|
|||
void
|
||||
hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
|
||||
{
|
||||
unsigned int cluster = UINT_MAX;
|
||||
unsigned int cluster = (unsigned int) -1;
|
||||
cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster);
|
||||
_unsafe_to_break_set_mask (info, start, end, cluster);
|
||||
}
|
||||
|
@ -607,7 +628,7 @@ hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int en
|
|||
assert (start <= out_len);
|
||||
assert (idx <= end);
|
||||
|
||||
unsigned int cluster = UINT_MAX;
|
||||
unsigned int cluster = (unsigned int) -1;
|
||||
cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster);
|
||||
cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster);
|
||||
_unsafe_to_break_set_mask (out_info, start, out_len, cluster);
|
||||
|
@ -715,7 +736,7 @@ hb_buffer_create ()
|
|||
hb_buffer_t *
|
||||
hb_buffer_get_empty ()
|
||||
{
|
||||
return const_cast<hb_buffer_t *> (&Null (hb_buffer_t));
|
||||
return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -937,7 +958,7 @@ hb_buffer_get_direction (hb_buffer_t *buffer)
|
|||
*
|
||||
* You can pass one of the predefined #hb_script_t values, or use
|
||||
* hb_script_from_string() or hb_script_from_iso15924_tag() to get the
|
||||
* corresponding script from an ISO 15924 script tag.
|
||||
* corresponding script from an ISO 15924 script tag.
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -980,7 +1001,7 @@ hb_buffer_get_script (hb_buffer_t *buffer)
|
|||
* are orthogonal to the scripts, and though they are related, they are
|
||||
* different concepts and should not be confused with each other.
|
||||
*
|
||||
* Use hb_language_from_string() to convert from BCP 47 language tags to
|
||||
* Use hb_language_from_string() to convert from BCP 47 language tags to
|
||||
* #hb_language_t.
|
||||
*
|
||||
* Since: 0.9.2
|
||||
|
@ -1717,7 +1738,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
|
|||
* @buffer: an #hb_buffer_t.
|
||||
* @source: source #hb_buffer_t.
|
||||
* @start: start index into source buffer to copy. Use 0 to copy from start of buffer.
|
||||
* @end: end index into source buffer to copy. Use @HB_FEATURE_GLOBAL_END to copy to end of buffer.
|
||||
* @end: end index into source buffer to copy. Use (unsigned int) -1 to copy to end of buffer.
|
||||
*
|
||||
* Append (part of) contents of another buffer to this buffer.
|
||||
*
|
||||
|
@ -1839,8 +1860,18 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
|
|||
|
||||
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
||||
|
||||
foreach_cluster (buffer, start, end)
|
||||
normalize_glyphs_cluster (buffer, start, end, backward);
|
||||
unsigned int count = buffer->len;
|
||||
if (unlikely (!count)) return;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
unsigned int start = 0;
|
||||
unsigned int end;
|
||||
for (end = start + 1; end < count; end++)
|
||||
if (info[start].cluster != info[end].cluster) {
|
||||
normalize_glyphs_cluster (buffer, start, end, backward);
|
||||
start = end;
|
||||
}
|
||||
normalize_glyphs_cluster (buffer, start, end, backward);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -365,7 +365,7 @@ hb_buffer_clear_contents (hb_buffer_t *buffer);
|
|||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_buffer_pre_allocate (hb_buffer_t *buffer,
|
||||
unsigned int size);
|
||||
unsigned int size);
|
||||
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
|
|
|
@ -228,10 +228,10 @@ struct hb_buffer_t
|
|||
/* Makes a copy of the glyph at idx to output and replace glyph_index */
|
||||
hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index)
|
||||
{
|
||||
if (unlikely (!make_room_for (0, 1))) return Crap (hb_glyph_info_t);
|
||||
if (unlikely (!make_room_for (0, 1))) return Crap(hb_glyph_info_t);
|
||||
|
||||
if (unlikely (idx == len && !out_len))
|
||||
return Crap (hb_glyph_info_t);
|
||||
return Crap(hb_glyph_info_t);
|
||||
|
||||
out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1];
|
||||
out_info[out_len].codepoint = glyph_index;
|
||||
|
@ -386,7 +386,7 @@ struct hb_buffer_t
|
|||
inf.cluster = cluster;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
int
|
||||
_unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
|
||||
unsigned int start, unsigned int end,
|
||||
unsigned int cluster) const
|
||||
|
|
|
@ -252,27 +252,30 @@ struct number_t
|
|||
struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
|
||||
{
|
||||
// encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
|
||||
template <typename T, typename V>
|
||||
static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value)
|
||||
template <typename INTTYPE, int minVal, int maxVal>
|
||||
static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, int value)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
if (unlikely ((value < minVal || value > maxVal)))
|
||||
return_trace (false);
|
||||
|
||||
HBUINT8 *p = c->allocate_size<HBUINT8> (1);
|
||||
if (unlikely (!p)) return_trace (false);
|
||||
if (unlikely (p == nullptr)) return_trace (false);
|
||||
*p = intOp;
|
||||
|
||||
T *ip = c->allocate_size<T> (T::static_size);
|
||||
if (unlikely (!ip)) return_trace (false);
|
||||
return_trace (c->check_assign (*ip, value));
|
||||
INTTYPE *ip = c->allocate_size<INTTYPE> (INTTYPE::static_size);
|
||||
if (unlikely (ip == nullptr)) return_trace (false);
|
||||
*ip = (unsigned int) value;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
static bool serialize_int4 (hb_serialize_context_t *c, V value)
|
||||
{ return serialize_int<HBINT32> (c, OpCode_longintdict, value); }
|
||||
static bool serialize_int4 (hb_serialize_context_t *c, int value)
|
||||
{ return serialize_int<HBUINT32, 0, 0x7FFFFFFF> (c, OpCode_longintdict, value); }
|
||||
|
||||
template <typename V>
|
||||
static bool serialize_int2 (hb_serialize_context_t *c, V value)
|
||||
{ return serialize_int<HBINT16> (c, OpCode_shortint, value); }
|
||||
static bool serialize_int2 (hb_serialize_context_t *c, int value)
|
||||
{ return serialize_int<HBUINT16, 0, 0x7FFF> (c, OpCode_shortint, value); }
|
||||
|
||||
/* Defining null_size allows a Null object may be created. Should be safe because:
|
||||
* A descendent struct Dict uses a Null pointer to indicate a missing table,
|
||||
|
@ -405,7 +408,7 @@ struct cff_stack_t
|
|||
else
|
||||
{
|
||||
set_error ();
|
||||
return Crap (ELEM);
|
||||
return Crap(ELEM);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,7 +419,7 @@ struct cff_stack_t
|
|||
else
|
||||
{
|
||||
set_error ();
|
||||
return Crap (ELEM);
|
||||
return Crap(ELEM);
|
||||
}
|
||||
}
|
||||
void pop (unsigned int n)
|
||||
|
@ -432,7 +435,7 @@ struct cff_stack_t
|
|||
if (unlikely (count < 0))
|
||||
{
|
||||
set_error ();
|
||||
return Null (ELEM);
|
||||
return Null(ELEM);
|
||||
}
|
||||
return elements[count - 1];
|
||||
}
|
||||
|
@ -539,7 +542,7 @@ struct op_serializer_t
|
|||
TRACE_SERIALIZE (this);
|
||||
|
||||
HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
|
||||
if (unlikely (!d)) return_trace (false);
|
||||
if (unlikely (d == nullptr)) return_trace (false);
|
||||
memcpy (d, &opstr.str[0], opstr.str.length);
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
@ -76,13 +76,13 @@ struct biased_subrs_t
|
|||
|
||||
void fini () {}
|
||||
|
||||
unsigned int get_count () const { return subrs ? subrs->count : 0; }
|
||||
unsigned int get_count () const { return (subrs == nullptr) ? 0 : subrs->count; }
|
||||
unsigned int get_bias () const { return bias; }
|
||||
|
||||
byte_str_t operator [] (unsigned int index) const
|
||||
{
|
||||
if (unlikely (!subrs || index >= subrs->count))
|
||||
return Null (byte_str_t);
|
||||
if (unlikely ((subrs == nullptr) || index >= subrs->count))
|
||||
return Null(byte_str_t);
|
||||
else
|
||||
return (*subrs)[index];
|
||||
}
|
||||
|
@ -551,13 +551,8 @@ struct path_procs_t
|
|||
|
||||
static void rcurveline (ENV &env, PARAM& param)
|
||||
{
|
||||
unsigned int arg_count = env.argStack.get_count ();
|
||||
if (unlikely (arg_count < 8))
|
||||
return;
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int curve_limit = arg_count - 2;
|
||||
for (; i + 6 <= curve_limit; i += 6)
|
||||
for (; i + 6 <= env.argStack.get_count (); i += 6)
|
||||
{
|
||||
point_t pt1 = env.get_pt ();
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
|
@ -567,34 +562,34 @@ struct path_procs_t
|
|||
pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
}
|
||||
|
||||
point_t pt1 = env.get_pt ();
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
PATH::line (env, param, pt1);
|
||||
for (; i + 2 <= env.argStack.get_count (); i += 2)
|
||||
{
|
||||
point_t pt1 = env.get_pt ();
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
PATH::line (env, param, pt1);
|
||||
}
|
||||
}
|
||||
|
||||
static void rlinecurve (ENV &env, PARAM& param)
|
||||
{
|
||||
unsigned int arg_count = env.argStack.get_count ();
|
||||
if (unlikely (arg_count < 8))
|
||||
return;
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int line_limit = arg_count - 6;
|
||||
unsigned int line_limit = (env.argStack.get_count () % 6);
|
||||
for (; i + 2 <= line_limit; i += 2)
|
||||
{
|
||||
point_t pt1 = env.get_pt ();
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
PATH::line (env, param, pt1);
|
||||
}
|
||||
|
||||
point_t pt1 = env.get_pt ();
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
point_t pt2 = pt1;
|
||||
pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
|
||||
point_t pt3 = pt2;
|
||||
pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
for (; i + 6 <= env.argStack.get_count (); i += 6)
|
||||
{
|
||||
point_t pt1 = env.get_pt ();
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
point_t pt2 = pt1;
|
||||
pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
|
||||
point_t pt3 = pt2;
|
||||
pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
}
|
||||
}
|
||||
|
||||
static void vvcurveto (ENV &env, PARAM& param)
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#define HB_CFF_INTERP_DICT_COMMON_HH
|
||||
|
||||
#include "hb-cff-interp-common.hh"
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
namespace CFF {
|
||||
|
||||
|
@ -56,6 +58,19 @@ struct top_dict_values_t : dict_values_t<OPSTR>
|
|||
}
|
||||
void fini () { dict_values_t<OPSTR>::fini (); }
|
||||
|
||||
unsigned int calculate_serialized_op_size (const OPSTR& opstr) const
|
||||
{
|
||||
switch (opstr.op)
|
||||
{
|
||||
case OpCode_CharStrings:
|
||||
case OpCode_FDArray:
|
||||
return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
|
||||
|
||||
default:
|
||||
return opstr.str.length;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int charStringsOffset;
|
||||
unsigned int FDArrayOffset;
|
||||
};
|
||||
|
|
|
@ -80,7 +80,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
|
|||
{
|
||||
template <typename ACC>
|
||||
void init (const byte_str_t &str, ACC &acc, unsigned int fd,
|
||||
const int *coords_=nullptr, unsigned int num_coords_=0)
|
||||
const int *coords_=nullptr, unsigned int num_coords_=0)
|
||||
{
|
||||
SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
|
||||
|
||||
|
@ -90,7 +90,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
|
|||
seen_blend = false;
|
||||
seen_vsindex_ = false;
|
||||
scalars.init ();
|
||||
do_blend = num_coords && coords && varStore->size;
|
||||
do_blend = (coords != nullptr) && num_coords && (varStore != &Null(CFF2VariationStore));
|
||||
set_ivs (acc.privateDicts[fd].ivs);
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
|
|||
if (do_blend)
|
||||
{
|
||||
scalars.resize (region_count);
|
||||
varStore->varStore.get_scalars (get_ivs (), coords, num_coords,
|
||||
varStore->varStore.get_scalars (get_ivs (),
|
||||
(int *)coords, num_coords,
|
||||
&scalars[0], region_count);
|
||||
}
|
||||
seen_blend = true;
|
||||
|
|
|
@ -69,6 +69,7 @@ _hb_options_init ()
|
|||
if (0 == strncmp (c, name, p - c) && strlen (name) == static_cast<size_t>(p - c)) do { u.opts.symbol = true; } while (0)
|
||||
|
||||
OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
|
||||
OPTION ("aat", aat);
|
||||
|
||||
#undef OPTION
|
||||
|
||||
|
@ -332,14 +333,14 @@ retry:
|
|||
/**
|
||||
* hb_language_from_string:
|
||||
* @str: (array length=len) (element-type uint8_t): a string representing
|
||||
* a BCP 47 language tag
|
||||
* a BCP 47 language tag
|
||||
* @len: length of the @str, or -1 if it is %NULL-terminated.
|
||||
*
|
||||
* Converts @str representing a BCP 47 language tag to the corresponding
|
||||
* Converts @str representing a BCP 47 language tag to the corresponding
|
||||
* #hb_language_t.
|
||||
*
|
||||
* Return value: (transfer none):
|
||||
* The #hb_language_t corresponding to the BCP 47 language tag.
|
||||
* The #hb_language_t corresponding to the BCP 47 language tag.
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -421,12 +422,12 @@ hb_language_get_default ()
|
|||
|
||||
/**
|
||||
* hb_script_from_iso15924_tag:
|
||||
* @tag: an #hb_tag_t representing an ISO 15924 tag.
|
||||
* @tag: an #hb_tag_t representing an ISO 15924 tag.
|
||||
*
|
||||
* Converts an ISO 15924 script tag to a corresponding #hb_script_t.
|
||||
* Converts an ISO 15924 script tag to a corresponding #hb_script_t.
|
||||
*
|
||||
* Return value:
|
||||
* An #hb_script_t corresponding to the ISO 15924 tag.
|
||||
* An #hb_script_t corresponding to the ISO 15924 tag.
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -467,15 +468,15 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
|
|||
/**
|
||||
* hb_script_from_string:
|
||||
* @str: (array length=len) (element-type uint8_t): a string representing an
|
||||
* ISO 15924 tag.
|
||||
* ISO 15924 tag.
|
||||
* @len: length of the @str, or -1 if it is %NULL-terminated.
|
||||
*
|
||||
* Converts a string @str representing an ISO 15924 script tag to a
|
||||
* Converts a string @str representing an ISO 15924 script tag to a
|
||||
* corresponding #hb_script_t. Shorthand for hb_tag_from_string() then
|
||||
* hb_script_from_iso15924_tag().
|
||||
*
|
||||
* Return value:
|
||||
* An #hb_script_t corresponding to the ISO 15924 tag.
|
||||
* An #hb_script_t corresponding to the ISO 15924 tag.
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -492,7 +493,7 @@ hb_script_from_string (const char *str, int len)
|
|||
* See hb_script_from_iso15924_tag().
|
||||
*
|
||||
* Return value:
|
||||
* An #hb_tag_t representing an ISO 15924 script tag.
|
||||
* An #hb_tag_t representing an ISO 15924 script tag.
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
@ -589,6 +590,38 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
|||
}
|
||||
|
||||
|
||||
/* hb_user_data_array_t */
|
||||
|
||||
bool
|
||||
hb_user_data_array_t::set (hb_user_data_key_t *key,
|
||||
void * data,
|
||||
hb_destroy_func_t destroy,
|
||||
hb_bool_t replace)
|
||||
{
|
||||
if (!key)
|
||||
return false;
|
||||
|
||||
if (replace) {
|
||||
if (!data && !destroy) {
|
||||
items.remove (key, lock);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
hb_user_data_item_t item = {key, data, destroy};
|
||||
bool ret = !!items.replace_or_insert (item, lock, (bool) replace);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *
|
||||
hb_user_data_array_t::get (hb_user_data_key_t *key)
|
||||
{
|
||||
hb_user_data_item_t item = {nullptr, nullptr, nullptr};
|
||||
|
||||
return items.find (key, &item, lock) ? item.data : nullptr;
|
||||
}
|
||||
|
||||
|
||||
/* hb_version */
|
||||
|
||||
|
||||
|
@ -927,14 +960,14 @@ hb_feature_to_string (hb_feature_t *feature,
|
|||
len += 4;
|
||||
while (len && s[len - 1] == ' ')
|
||||
len--;
|
||||
if (feature->start != HB_FEATURE_GLOBAL_START || feature->end != HB_FEATURE_GLOBAL_END)
|
||||
if (feature->start != 0 || feature->end != (unsigned int) -1)
|
||||
{
|
||||
s[len++] = '[';
|
||||
if (feature->start)
|
||||
len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
|
||||
if (feature->end != feature->start + 1) {
|
||||
s[len++] = ':';
|
||||
if (feature->end != HB_FEATURE_GLOBAL_END)
|
||||
if (feature->end != (unsigned int) -1)
|
||||
len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
|
||||
}
|
||||
s[len++] = ']';
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
#define HB_NO_BITMAP
|
||||
#define HB_NO_CFF
|
||||
#define HB_NO_COLOR
|
||||
#define HB_NO_DRAW
|
||||
#define HB_NO_ERRNO
|
||||
#define HB_NO_FACE_COLLECT_UNICODES
|
||||
#define HB_NO_GETENV
|
||||
|
|
|
@ -278,32 +278,13 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
|
|||
CFRelease ((CGFontRef) data);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_create:
|
||||
* @cg_font: The CGFontRef to work upon
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified
|
||||
* CGFontRef.
|
||||
*
|
||||
* Return value: the new #hb_face_t face object
|
||||
*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
hb_face_t *
|
||||
hb_coretext_face_create (CGFontRef cg_font)
|
||||
{
|
||||
return hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_get_cg_font:
|
||||
* @face: The #hb_face_t to work upon
|
||||
*
|
||||
* Fetches the CGFontRef associated with an #hb_face_t
|
||||
* face object
|
||||
*
|
||||
* Return value: the CGFontRef found
|
||||
*
|
||||
/*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
CGFontRef
|
||||
|
@ -370,17 +351,10 @@ retry:
|
|||
return font->data.coretext;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_font_create:
|
||||
* @ct_font: The CTFontRef to work upon
|
||||
*
|
||||
* Creates an #hb_font_t font object from the specified
|
||||
* CTFontRef.
|
||||
*
|
||||
* Return value: the new #hb_font_t font object
|
||||
*
|
||||
|
||||
/*
|
||||
* Since: 1.7.2
|
||||
**/
|
||||
*/
|
||||
hb_font_t *
|
||||
hb_coretext_font_create (CTFontRef ct_font)
|
||||
{
|
||||
|
@ -401,17 +375,6 @@ hb_coretext_font_create (CTFontRef ct_font)
|
|||
return font;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_coretext_face_get_ct_font:
|
||||
* @font: #hb_font_t to work upon
|
||||
*
|
||||
* Fetches the CTFontRef associated with the specified
|
||||
* #hb_font_t font object.
|
||||
*
|
||||
* Return value: the CTFontRef found
|
||||
*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
CTFontRef
|
||||
hb_coretext_font_get_ct_font (hb_font_t *font)
|
||||
{
|
||||
|
@ -512,19 +475,13 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
hb_vector_t<feature_event_t> feature_events;
|
||||
for (unsigned int i = 0; i < num_features; i++)
|
||||
{
|
||||
active_feature_t feature;
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1010
|
||||
const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag);
|
||||
if (!mapping)
|
||||
continue;
|
||||
|
||||
active_feature_t feature;
|
||||
feature.rec.feature = mapping->aatFeatureType;
|
||||
feature.rec.setting = features[i].value ? mapping->selectorToEnable : mapping->selectorToDisable;
|
||||
#else
|
||||
feature.rec.feature = features[i].tag;
|
||||
feature.rec.setting = features[i].value;
|
||||
#endif
|
||||
feature.order = i;
|
||||
|
||||
feature_event_t *event;
|
||||
|
@ -573,7 +530,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
/* active_features.qsort (); */
|
||||
for (unsigned int j = 0; j < active_features.length; j++)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1010
|
||||
CFStringRef keys[] = {
|
||||
kCTFontFeatureTypeIdentifierKey,
|
||||
kCTFontFeatureSelectorIdentifierKey
|
||||
|
@ -582,17 +538,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature),
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting)
|
||||
};
|
||||
#else
|
||||
char tag[5] = {HB_UNTAG (active_features[j].rec.feature)};
|
||||
CFTypeRef keys[] = {
|
||||
kCTFontOpenTypeFeatureTag,
|
||||
kCTFontOpenTypeFeatureValue
|
||||
};
|
||||
CFTypeRef values[] = {
|
||||
CFStringCreateWithCString (kCFAllocatorDefault, tag, kCFStringEncodingASCII),
|
||||
CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting)
|
||||
};
|
||||
#endif
|
||||
static_assert ((ARRAY_LENGTH_CONST (keys) == ARRAY_LENGTH_CONST (values)), "");
|
||||
CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault,
|
||||
(const void **) keys,
|
||||
|
@ -660,7 +605,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
scratch_size -= _consumed; \
|
||||
} while (0)
|
||||
|
||||
ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, ((void)nullptr) /*nothing*/);
|
||||
ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, /*nothing*/);
|
||||
unsigned int chars_len = 0;
|
||||
for (unsigned int i = 0; i < buffer->len; i++) {
|
||||
hb_codepoint_t c = buffer->info[i].codepoint;
|
||||
|
@ -674,7 +619,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
|
|||
}
|
||||
}
|
||||
|
||||
ALLOCATE_ARRAY (unsigned int, log_clusters, chars_len, ((void)nullptr) /*nothing*/);
|
||||
ALLOCATE_ARRAY (unsigned int, log_clusters, chars_len, /*nothing*/);
|
||||
chars_len = 0;
|
||||
for (unsigned int i = 0; i < buffer->len; i++)
|
||||
{
|
||||
|
|
|
@ -40,40 +40,8 @@
|
|||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
/**
|
||||
* HB_CORETEXT_TAG_MORT:
|
||||
*
|
||||
* The #hb_tag_t tag for the `mort` (glyph metamorphosis) table,
|
||||
* which holds AAT features.
|
||||
*
|
||||
* For more information, see
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html
|
||||
*
|
||||
**/
|
||||
#define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t')
|
||||
|
||||
/**
|
||||
* HB_CORETEXT_TAG_MORX:
|
||||
*
|
||||
* The #hb_tag_t tag for the `morx` (extended glyph metamorphosis)
|
||||
* table, which holds AAT features.
|
||||
*
|
||||
* For more information, see
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html
|
||||
*
|
||||
**/
|
||||
#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
|
||||
|
||||
/**
|
||||
* HB_CORETEXT_TAG_KERX:
|
||||
*
|
||||
* The #hb_tag_t tag for the `kerx` (extended kerning) table, which
|
||||
* holds AAT kerning information.
|
||||
*
|
||||
* For more information, see
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kerx.html
|
||||
*
|
||||
**/
|
||||
#define HB_CORETEXT_TAG_KERX HB_TAG('k','e','r','x')
|
||||
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ struct hb_options_t
|
|||
bool unused : 1; /* In-case sign bit is here. */
|
||||
bool initialized : 1;
|
||||
bool uniscribe_bug_compatible : 1;
|
||||
bool aat : 1;
|
||||
};
|
||||
|
||||
union hb_options_union_t {
|
||||
|
@ -229,7 +230,7 @@ _hb_debug_msg<0> (const char *what HB_UNUSED,
|
|||
...) {}
|
||||
|
||||
#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
|
||||
#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, false, 0, 0, __VA_ARGS__)
|
||||
#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, false, 0, 0, __VA_ARGS__)
|
||||
#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
|
||||
|
||||
|
||||
|
|
|
@ -635,7 +635,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
|
|||
bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
|
||||
|
||||
const wchar_t localeName[20] = {0};
|
||||
if (buffer->props.language)
|
||||
if (buffer->props.language != nullptr)
|
||||
mbstowcs ((wchar_t*) localeName,
|
||||
hb_language_to_string (buffer->props.language), 20);
|
||||
|
||||
|
|
|
@ -1,261 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2019-2020 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_DRAW
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
|
||||
#include "hb-draw.hh"
|
||||
#include "hb-ot.h"
|
||||
#include "hb-ot-glyf-table.hh"
|
||||
#include "hb-ot-cff1-table.hh"
|
||||
#include "hb-ot-cff2-table.hh"
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_set_move_to_func:
|
||||
* @funcs: draw functions object
|
||||
* @move_to: move-to callback
|
||||
*
|
||||
* Sets move-to callback to the draw functions object.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
void
|
||||
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_move_to_func_t move_to)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
||||
funcs->move_to = move_to;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_set_line_to_func:
|
||||
* @funcs: draw functions object
|
||||
* @line_to: line-to callback
|
||||
*
|
||||
* Sets line-to callback to the draw functions object.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
void
|
||||
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_line_to_func_t line_to)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
||||
funcs->line_to = line_to;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_set_quadratic_to_func:
|
||||
* @funcs: draw functions object
|
||||
* @move_to: quadratic-to callback
|
||||
*
|
||||
* Sets quadratic-to callback to the draw functions object.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
void
|
||||
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_quadratic_to_func_t quadratic_to)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
||||
funcs->quadratic_to = quadratic_to;
|
||||
funcs->is_quadratic_to_set = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_set_cubic_to_func:
|
||||
* @funcs: draw functions
|
||||
* @cubic_to: cubic-to callback
|
||||
*
|
||||
* Sets cubic-to callback to the draw functions object.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
void
|
||||
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_cubic_to_func_t cubic_to)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
||||
funcs->cubic_to = cubic_to;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_set_close_path_func:
|
||||
* @funcs: draw functions object
|
||||
* @close_path: close-path callback
|
||||
*
|
||||
* Sets close-path callback to the draw functions object.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
void
|
||||
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_close_path_func_t close_path)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (funcs))) return;
|
||||
funcs->close_path = close_path;
|
||||
}
|
||||
|
||||
static void
|
||||
_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
|
||||
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
|
||||
void *user_data HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
|
||||
hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
|
||||
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
|
||||
void *user_data HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_close_path_nil (void *user_data HB_UNUSED) {}
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_create:
|
||||
*
|
||||
* Creates a new draw callbacks object.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
hb_draw_funcs_t *
|
||||
hb_draw_funcs_create ()
|
||||
{
|
||||
hb_draw_funcs_t *funcs;
|
||||
if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ())))
|
||||
return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
|
||||
|
||||
funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil;
|
||||
funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil;
|
||||
funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil;
|
||||
funcs->is_quadratic_to_set = false;
|
||||
funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil;
|
||||
funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil;
|
||||
return funcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_reference:
|
||||
* @funcs: draw functions
|
||||
*
|
||||
* Add to callbacks object refcount.
|
||||
*
|
||||
* Returns: The same object.
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
hb_draw_funcs_t *
|
||||
hb_draw_funcs_reference (hb_draw_funcs_t *funcs)
|
||||
{
|
||||
return hb_object_reference (funcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_destroy:
|
||||
* @funcs: draw functions
|
||||
*
|
||||
* Decreases refcount of callbacks object and deletes the object if it reaches
|
||||
* to zero.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
void
|
||||
hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
|
||||
{
|
||||
if (!hb_object_destroy (funcs)) return;
|
||||
|
||||
free (funcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_make_immutable:
|
||||
* @funcs: draw functions
|
||||
*
|
||||
* Makes funcs object immutable.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
void
|
||||
hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs)
|
||||
{
|
||||
if (hb_object_is_immutable (funcs))
|
||||
return;
|
||||
|
||||
hb_object_make_immutable (funcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_is_immutable:
|
||||
* @funcs: draw functions
|
||||
*
|
||||
* Checks whether funcs is immutable.
|
||||
*
|
||||
* Returns: If is immutable.
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs)
|
||||
{
|
||||
return hb_object_is_immutable (funcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_draw_glyph:
|
||||
* @font: a font object
|
||||
* @glyph: a glyph id
|
||||
* @funcs: draw callbacks object
|
||||
* @user_data: parameter you like be passed to the callbacks when are called
|
||||
*
|
||||
* Draw a glyph.
|
||||
*
|
||||
* Returns: Whether the font had the glyph and the operation completed successfully.
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
|
||||
const hb_draw_funcs_t *funcs,
|
||||
void *user_data)
|
||||
{
|
||||
if (unlikely (funcs == &Null (hb_draw_funcs_t) ||
|
||||
glyph >= font->face->get_num_glyphs ()))
|
||||
return false;
|
||||
|
||||
draw_helper_t draw_helper (funcs, user_data);
|
||||
if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true;
|
||||
#ifndef HB_NO_CFF
|
||||
if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true;
|
||||
if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2019-2020 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_H_IN
|
||||
#error "Include <hb.h> instead."
|
||||
#endif
|
||||
|
||||
#ifndef HB_DRAW_H
|
||||
#define HB_DRAW_H
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
typedef void (*hb_draw_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
|
||||
typedef void (*hb_draw_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
|
||||
typedef void (*hb_draw_quadratic_to_func_t) (hb_position_t control_x, hb_position_t control_y,
|
||||
hb_position_t to_x, hb_position_t to_y,
|
||||
void *user_data);
|
||||
typedef void (*hb_draw_cubic_to_func_t) (hb_position_t control1_x, hb_position_t control1_y,
|
||||
hb_position_t control2_x, hb_position_t control2_y,
|
||||
hb_position_t to_x, hb_position_t to_y,
|
||||
void *user_data);
|
||||
typedef void (*hb_draw_close_path_func_t) (void *user_data);
|
||||
|
||||
/**
|
||||
* hb_draw_funcs_t:
|
||||
*
|
||||
* Glyph draw callbacks.
|
||||
*
|
||||
* _move_to, _line_to and _cubic_to calls are nessecary to be defined but we
|
||||
* translate _quadratic_to calls to _cubic_to if the callback isn't defined.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
typedef struct hb_draw_funcs_t hb_draw_funcs_t;
|
||||
|
||||
HB_EXTERN void
|
||||
hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_move_to_func_t move_to);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_line_to_func_t line_to);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_quadratic_to_func_t quadratic_to);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_cubic_to_func_t cubic_to);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
|
||||
hb_draw_close_path_func_t close_path);
|
||||
|
||||
HB_EXTERN hb_draw_funcs_t *
|
||||
hb_draw_funcs_create (void);
|
||||
|
||||
HB_EXTERN hb_draw_funcs_t *
|
||||
hb_draw_funcs_reference (hb_draw_funcs_t *funcs);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_draw_funcs_destroy (hb_draw_funcs_t *funcs);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs);
|
||||
#endif
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_DRAW_H */
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2020 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_DRAW_HH
|
||||
#define HB_DRAW_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
struct hb_draw_funcs_t
|
||||
{
|
||||
hb_object_header_t header;
|
||||
|
||||
hb_draw_move_to_func_t move_to;
|
||||
hb_draw_line_to_func_t line_to;
|
||||
hb_draw_quadratic_to_func_t quadratic_to;
|
||||
bool is_quadratic_to_set;
|
||||
hb_draw_cubic_to_func_t cubic_to;
|
||||
hb_draw_close_path_func_t close_path;
|
||||
};
|
||||
|
||||
struct draw_helper_t
|
||||
{
|
||||
draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_)
|
||||
{
|
||||
funcs = funcs_;
|
||||
user_data = user_data_;
|
||||
path_open = false;
|
||||
path_start_x = current_x = path_start_y = current_y = 0;
|
||||
}
|
||||
~draw_helper_t () { end_path (); }
|
||||
|
||||
void move_to (hb_position_t x, hb_position_t y)
|
||||
{
|
||||
if (path_open) end_path ();
|
||||
current_x = path_start_x = x;
|
||||
current_y = path_start_y = y;
|
||||
}
|
||||
|
||||
void line_to (hb_position_t x, hb_position_t y)
|
||||
{
|
||||
if (equal_to_current (x, y)) return;
|
||||
if (!path_open) start_path ();
|
||||
funcs->line_to (x, y, user_data);
|
||||
current_x = x;
|
||||
current_y = y;
|
||||
}
|
||||
|
||||
void
|
||||
quadratic_to (hb_position_t control_x, hb_position_t control_y,
|
||||
hb_position_t to_x, hb_position_t to_y)
|
||||
{
|
||||
if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y))
|
||||
return;
|
||||
if (!path_open) start_path ();
|
||||
if (funcs->is_quadratic_to_set)
|
||||
funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data);
|
||||
else
|
||||
funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f),
|
||||
roundf ((current_y + 2.f * control_y) / 3.f),
|
||||
roundf ((to_x + 2.f * control_x) / 3.f),
|
||||
roundf ((to_y + 2.f * control_y) / 3.f),
|
||||
to_x, to_y, user_data);
|
||||
current_x = to_x;
|
||||
current_y = to_y;
|
||||
}
|
||||
|
||||
void
|
||||
cubic_to (hb_position_t control1_x, hb_position_t control1_y,
|
||||
hb_position_t control2_x, hb_position_t control2_y,
|
||||
hb_position_t to_x, hb_position_t to_y)
|
||||
{
|
||||
if (equal_to_current (control1_x, control1_y) &&
|
||||
equal_to_current (control2_x, control2_y) &&
|
||||
equal_to_current (to_x, to_y))
|
||||
return;
|
||||
if (!path_open) start_path ();
|
||||
funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data);
|
||||
current_x = to_x;
|
||||
current_y = to_y;
|
||||
}
|
||||
|
||||
void end_path ()
|
||||
{
|
||||
if (path_open)
|
||||
{
|
||||
if ((path_start_x != current_x) || (path_start_y != current_y))
|
||||
funcs->line_to (path_start_x, path_start_y, user_data);
|
||||
funcs->close_path (user_data);
|
||||
}
|
||||
path_open = false;
|
||||
path_start_x = current_x = path_start_y = current_y = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool equal_to_current (hb_position_t x, hb_position_t y)
|
||||
{ return current_x == x && current_y == y; }
|
||||
|
||||
void start_path ()
|
||||
{
|
||||
if (path_open) end_path ();
|
||||
path_open = true;
|
||||
funcs->move_to (path_start_x, path_start_y, user_data);
|
||||
}
|
||||
|
||||
hb_position_t path_start_x;
|
||||
hb_position_t path_start_y;
|
||||
|
||||
hb_position_t current_x;
|
||||
hb_position_t current_y;
|
||||
|
||||
bool path_open;
|
||||
const hb_draw_funcs_t *funcs;
|
||||
void *user_data;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* HB_DRAW_HH */
|
|
@ -226,7 +226,7 @@ hb_face_create (hb_blob_t *blob,
|
|||
hb_face_t *
|
||||
hb_face_get_empty ()
|
||||
{
|
||||
return const_cast<hb_face_t *> (&Null (hb_face_t));
|
||||
return const_cast<hb_face_t *> (&Null(hb_face_t));
|
||||
}
|
||||
|
||||
|
||||
|
@ -546,7 +546,7 @@ void
|
|||
hb_face_collect_unicodes (hb_face_t *face,
|
||||
hb_set_t *out)
|
||||
{
|
||||
face->table.cmap->collect_unicodes (out, face->get_num_glyphs ());
|
||||
face->table.cmap->collect_unicodes (out);
|
||||
}
|
||||
/**
|
||||
* hb_face_collect_variation_selectors:
|
||||
|
|
|
@ -94,7 +94,7 @@ struct hb_face_t
|
|||
unsigned int get_num_glyphs () const
|
||||
{
|
||||
unsigned int ret = num_glyphs.get_relaxed ();
|
||||
if (unlikely (ret == UINT_MAX))
|
||||
if (unlikely (ret == (unsigned int) -1))
|
||||
return load_num_glyphs ();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -33,9 +33,6 @@
|
|||
|
||||
#include "hb-ot.h"
|
||||
|
||||
#include "hb-ot-var-avar-table.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-font
|
||||
|
@ -677,8 +674,7 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
|
|||
void *user_data, \
|
||||
hb_destroy_func_t destroy) \
|
||||
{ \
|
||||
if (hb_object_is_immutable (ffuncs)) \
|
||||
{ \
|
||||
if (hb_object_is_immutable (ffuncs)) { \
|
||||
if (destroy) \
|
||||
destroy (user_data); \
|
||||
return; \
|
||||
|
@ -1336,7 +1332,6 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
|
|||
|
||||
0, /* num_coords */
|
||||
nullptr, /* coords */
|
||||
nullptr, /* design_coords */
|
||||
|
||||
const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t),
|
||||
|
||||
|
@ -1388,20 +1383,6 @@ hb_font_create (hb_face_t *face)
|
|||
return font;
|
||||
}
|
||||
|
||||
static void
|
||||
_hb_font_adopt_var_coords (hb_font_t *font,
|
||||
int *coords, /* 2.14 normalized */
|
||||
float *design_coords,
|
||||
unsigned int coords_length)
|
||||
{
|
||||
free (font->coords);
|
||||
free (font->design_coords);
|
||||
|
||||
font->coords = coords;
|
||||
font->design_coords = design_coords;
|
||||
font->num_coords = coords_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_create_sub_font:
|
||||
* @parent: parent font.
|
||||
|
@ -1432,22 +1413,15 @@ hb_font_create_sub_font (hb_font_t *parent)
|
|||
font->y_ppem = parent->y_ppem;
|
||||
font->ptem = parent->ptem;
|
||||
|
||||
unsigned int num_coords = parent->num_coords;
|
||||
if (num_coords)
|
||||
font->num_coords = parent->num_coords;
|
||||
if (font->num_coords)
|
||||
{
|
||||
int *coords = (int *) calloc (num_coords, sizeof (parent->coords[0]));
|
||||
float *design_coords = (float *) calloc (num_coords, sizeof (parent->design_coords[0]));
|
||||
if (likely (coords && design_coords))
|
||||
{
|
||||
memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0]));
|
||||
memcpy (design_coords, parent->design_coords, num_coords * sizeof (parent->design_coords[0]));
|
||||
_hb_font_adopt_var_coords (font, coords, design_coords, num_coords);
|
||||
}
|
||||
unsigned int size = parent->num_coords * sizeof (parent->coords[0]);
|
||||
font->coords = (int *) malloc (size);
|
||||
if (unlikely (!font->coords))
|
||||
font->num_coords = 0;
|
||||
else
|
||||
{
|
||||
free (coords);
|
||||
free (design_coords);
|
||||
}
|
||||
memcpy (font->coords, parent->coords, size);
|
||||
}
|
||||
|
||||
return font;
|
||||
|
@ -1465,7 +1439,7 @@ hb_font_create_sub_font (hb_font_t *parent)
|
|||
hb_font_t *
|
||||
hb_font_get_empty ()
|
||||
{
|
||||
return const_cast<hb_font_t *> (&Null (hb_font_t));
|
||||
return const_cast<hb_font_t *> (&Null(hb_font_t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1507,7 +1481,6 @@ hb_font_destroy (hb_font_t *font)
|
|||
hb_font_funcs_destroy (font->klass);
|
||||
|
||||
free (font->coords);
|
||||
free (font->design_coords);
|
||||
|
||||
free (font);
|
||||
}
|
||||
|
@ -1869,6 +1842,17 @@ hb_font_get_ptem (hb_font_t *font)
|
|||
* Variations
|
||||
*/
|
||||
|
||||
static void
|
||||
_hb_font_adopt_var_coords_normalized (hb_font_t *font,
|
||||
int *coords, /* 2.14 normalized */
|
||||
unsigned int coords_length)
|
||||
{
|
||||
free (font->coords);
|
||||
|
||||
font->coords = coords;
|
||||
font->num_coords = coords_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_variations:
|
||||
*
|
||||
|
@ -1891,30 +1875,13 @@ hb_font_set_variations (hb_font_t *font,
|
|||
unsigned int coords_length = hb_ot_var_get_axis_count (font->face);
|
||||
|
||||
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
|
||||
|
||||
if (unlikely (coords_length && !(normalized && design_coords)))
|
||||
{
|
||||
free (normalized);
|
||||
free (design_coords);
|
||||
if (unlikely (coords_length && !normalized))
|
||||
return;
|
||||
}
|
||||
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
for (unsigned int i = 0; i < variations_length; i++)
|
||||
{
|
||||
hb_ot_var_axis_info_t info;
|
||||
if (hb_ot_var_find_axis_info (font->face, variations[i].tag, &info) &&
|
||||
info.axis_index < coords_length)
|
||||
{
|
||||
float v = variations[i].value;
|
||||
design_coords[info.axis_index] = v;
|
||||
normalized[info.axis_index] = fvar.normalize_axis_value (info.axis_index, v);
|
||||
}
|
||||
}
|
||||
font->face->table.avar->map_coords (normalized, coords_length);
|
||||
|
||||
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
|
||||
hb_ot_var_normalize_variations (font->face,
|
||||
variations, variations_length,
|
||||
normalized, coords_length);
|
||||
_hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1931,20 +1898,11 @@ hb_font_set_var_coords_design (hb_font_t *font,
|
|||
return;
|
||||
|
||||
int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr;
|
||||
|
||||
if (unlikely (coords_length && !(normalized && design_coords)))
|
||||
{
|
||||
free (normalized);
|
||||
free (design_coords);
|
||||
if (unlikely (coords_length && !normalized))
|
||||
return;
|
||||
}
|
||||
|
||||
if (coords_length)
|
||||
memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0]));
|
||||
|
||||
hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
|
||||
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
|
||||
_hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1988,30 +1946,13 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
|
|||
return;
|
||||
|
||||
int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
int *unmapped = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (design_coords[0])) : nullptr;
|
||||
|
||||
if (unlikely (coords_length && !(copy && unmapped && design_coords)))
|
||||
{
|
||||
free (copy);
|
||||
free (unmapped);
|
||||
free (design_coords);
|
||||
if (unlikely (coords_length && !copy))
|
||||
return;
|
||||
}
|
||||
|
||||
if (coords_length)
|
||||
{
|
||||
memcpy (copy, coords, coords_length * sizeof (coords[0]));
|
||||
memcpy (unmapped, coords, coords_length * sizeof (coords[0]));
|
||||
}
|
||||
|
||||
/* Best effort design coords simulation */
|
||||
font->face->table.avar->unmap_coords (unmapped, coords_length);
|
||||
for (unsigned int i = 0; i < coords_length; ++i)
|
||||
design_coords[i] = font->face->table.fvar->unnormalize_axis_value (i, unmapped[i]);
|
||||
free (unmapped);
|
||||
|
||||
_hb_font_adopt_var_coords (font, copy, design_coords, coords_length);
|
||||
_hb_font_adopt_var_coords_normalized (font, copy, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2031,26 +1972,6 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
|
|||
|
||||
return font->coords;
|
||||
}
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
/**
|
||||
* hb_font_get_var_coords_design:
|
||||
*
|
||||
* Return value is valid as long as variation coordinates of the font
|
||||
* are not modified.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
*/
|
||||
const float *
|
||||
hb_font_get_var_coords_design (hb_font_t *font,
|
||||
unsigned int *length)
|
||||
{
|
||||
if (length)
|
||||
*length = font->num_coords;
|
||||
|
||||
return font->design_coords;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HB_DISABLE_DEPRECATED
|
||||
|
@ -2155,13 +2076,6 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
|
|||
hb_font_get_glyph_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy)
|
||||
{
|
||||
if (hb_object_is_immutable (ffuncs))
|
||||
{
|
||||
if (destroy)
|
||||
destroy (user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
hb_font_get_glyph_trampoline_t *trampoline;
|
||||
|
||||
trampoline = trampoline_create (func, user_data, destroy);
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include "hb-common.h"
|
||||
#include "hb-face.h"
|
||||
#include "hb-draw.h"
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
@ -705,12 +704,6 @@ hb_font_set_var_coords_design (hb_font_t *font,
|
|||
const float *coords,
|
||||
unsigned int coords_length);
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
HB_EXTERN const float *
|
||||
hb_font_get_var_coords_design (hb_font_t *font,
|
||||
unsigned int *length);
|
||||
#endif
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_var_coords_normalized (hb_font_t *font,
|
||||
const int *coords, /* 2.14 normalized */
|
||||
|
@ -724,12 +717,6 @@ HB_EXTERN void
|
|||
hb_font_set_var_named_instance (hb_font_t *font,
|
||||
unsigned instance_index);
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
|
||||
const hb_draw_funcs_t *funcs, void *user_data);
|
||||
#endif
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_FONT_H */
|
||||
|
|
|
@ -120,7 +120,6 @@ struct hb_font_t
|
|||
/* Font variation coordinates. */
|
||||
unsigned int num_coords;
|
||||
int *coords;
|
||||
float *design_coords;
|
||||
|
||||
hb_font_funcs_t *klass;
|
||||
void *user_data;
|
||||
|
@ -287,7 +286,7 @@ struct hb_font_t
|
|||
}
|
||||
|
||||
hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
*x = *y = 0;
|
||||
return klass->get.f.glyph_h_origin (this, user_data,
|
||||
|
|
|
@ -48,13 +48,8 @@
|
|||
* @short_description: FreeType integration
|
||||
* @include: hb-ft.h
|
||||
*
|
||||
* Functions for using HarfBuzz with the FreeType library.
|
||||
*
|
||||
* HarfBuzz supports using FreeType to provide face and
|
||||
* Functions for using HarfBuzz with the FreeType library to provide face and
|
||||
* font data.
|
||||
*
|
||||
* <note>Note that FreeType is not thread-safe, therefore these
|
||||
* functions are not thread-safe either.</note>
|
||||
**/
|
||||
|
||||
|
||||
|
@ -132,13 +127,10 @@ _hb_ft_font_destroy (void *data)
|
|||
|
||||
/**
|
||||
* hb_ft_font_set_load_flags:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @load_flags: The FreeType load flags to set
|
||||
* @font:
|
||||
* @load_flags:
|
||||
*
|
||||
* Sets the FT_Load_Glyph load flags for the specified #hb_font_t.
|
||||
*
|
||||
* For more information, see
|
||||
* https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
|
||||
*
|
||||
* Since: 1.0.5
|
||||
**/
|
||||
|
@ -148,7 +140,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
|
|||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
|
||||
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
|
||||
return;
|
||||
|
||||
hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
|
||||
|
@ -158,21 +150,17 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
|
|||
|
||||
/**
|
||||
* hb_ft_font_get_load_flags:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @font:
|
||||
*
|
||||
* Fetches the FT_Load_Glyph load flags of the specified #hb_font_t.
|
||||
*
|
||||
* For more information, see
|
||||
* https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
|
||||
*
|
||||
* Return value: FT_Load_Glyph flags found
|
||||
*
|
||||
* Return value:
|
||||
* Since: 1.0.5
|
||||
**/
|
||||
int
|
||||
hb_ft_font_get_load_flags (hb_font_t *font)
|
||||
{
|
||||
if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
|
||||
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
|
||||
return 0;
|
||||
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
|
||||
|
@ -180,21 +168,10 @@ hb_ft_font_get_load_flags (hb_font_t *font)
|
|||
return ft_font->load_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ft_get_face:
|
||||
* @font: #hb_font_t to work upon
|
||||
*
|
||||
* Fetches the FT_Face associated with the specified #hb_font_t
|
||||
* font object.
|
||||
*
|
||||
* Return value: the FT_Face found
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
FT_Face
|
||||
hb_ft_font_get_face (hb_font_t *font)
|
||||
{
|
||||
if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
|
||||
if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
|
||||
return nullptr;
|
||||
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
|
||||
|
@ -202,47 +179,6 @@ hb_ft_font_get_face (hb_font_t *font)
|
|||
return ft_font->ft_face;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ft_font_lock_face:
|
||||
* @font:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
* Since: 2.6.5
|
||||
**/
|
||||
FT_Face
|
||||
hb_ft_font_lock_face (hb_font_t *font)
|
||||
{
|
||||
if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
|
||||
return nullptr;
|
||||
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
|
||||
|
||||
ft_font->lock.lock ();
|
||||
|
||||
return ft_font->ft_face;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ft_font_unlock_face:
|
||||
* @font:
|
||||
*
|
||||
*
|
||||
*
|
||||
* Return value:
|
||||
* Since: 2.6.5
|
||||
**/
|
||||
void
|
||||
hb_ft_font_unlock_face (hb_font_t *font)
|
||||
{
|
||||
if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
|
||||
return;
|
||||
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
|
||||
|
||||
ft_font->lock.unlock ();
|
||||
}
|
||||
|
||||
|
||||
static hb_bool_t
|
||||
|
@ -659,22 +595,12 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data
|
|||
|
||||
/**
|
||||
* hb_ft_face_create:
|
||||
* @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
|
||||
* @destroy: A callback to call when the face object is not needed anymore
|
||||
* @ft_face: (destroy destroy) (scope notified):
|
||||
* @destroy:
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified FT_Face.
|
||||
*
|
||||
* This variant of the function does not provide any life-cycle management.
|
||||
*
|
||||
* Most client programs should use hb_ft_face_create_referenced()
|
||||
* (or, perhaps, hb_ft_face_create_cached()) instead.
|
||||
*
|
||||
* If you know you have valid reasons not to use hb_ft_face_create_referenced(),
|
||||
* then it is the client program's responsibility to destroy @ft_face
|
||||
* after the #hb_face_t face object has been destroyed.
|
||||
*
|
||||
* Return value: (transfer full): the new #hb_face_t face object
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
hb_face_t *
|
||||
|
@ -704,20 +630,11 @@ hb_ft_face_create (FT_Face ft_face,
|
|||
|
||||
/**
|
||||
* hb_ft_face_create_referenced:
|
||||
* @ft_face: FT_Face to work upon
|
||||
* @ft_face:
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified FT_Face.
|
||||
*
|
||||
* This is the preferred variant of the hb_ft_face_create*
|
||||
* function family, because it calls FT_Reference_Face() on @ft_face,
|
||||
* ensuring that @ft_face remains alive as long as the resulting
|
||||
* #hb_face_t face object remains alive. Also calls FT_Done_Face()
|
||||
* when the #hb_face_t face object is destroyed.
|
||||
*
|
||||
* Use this version unless you know you have good reasons not to.
|
||||
*
|
||||
* Return value: (transfer full): the new #hb_face_t face object
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
* Since: 0.9.38
|
||||
**/
|
||||
hb_face_t *
|
||||
|
@ -735,21 +652,11 @@ hb_ft_face_finalize (FT_Face ft_face)
|
|||
|
||||
/**
|
||||
* hb_ft_face_create_cached:
|
||||
* @ft_face: FT_Face to work upon
|
||||
* @ft_face:
|
||||
*
|
||||
* Creates an #hb_face_t face object from the specified FT_Face.
|
||||
*
|
||||
* This variant of the function caches the newly created #hb_face_t
|
||||
* face object, using the @generic pointer of @ft_face. Subsequent function
|
||||
* calls that are passed the same @ft_face parameter will have the same
|
||||
* #hb_face_t returned to them, and that #hb_face_t will be correctly
|
||||
* reference counted.
|
||||
*
|
||||
* However, client programs are still responsible for destroying
|
||||
* @ft_face after the last #hb_face_t face object has been destroyed.
|
||||
*
|
||||
* Return value: (transfer full): the new #hb_face_t face object
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
hb_face_t *
|
||||
|
@ -767,34 +674,15 @@ hb_ft_face_create_cached (FT_Face ft_face)
|
|||
return hb_face_reference ((hb_face_t *) ft_face->generic.data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_ft_font_create:
|
||||
* @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
|
||||
* @destroy: (optional): A callback to call when the font object is not needed anymore
|
||||
* @ft_face: (destroy destroy) (scope notified):
|
||||
* @destroy:
|
||||
*
|
||||
* Creates an #hb_font_t font object from the specified FT_Face.
|
||||
*
|
||||
* <note>Note: You must set the face size on @ft_face before calling
|
||||
* hb_ft_font_create() on it. Otherwise, HarfBuzz will not pick up
|
||||
* the face size.</note>
|
||||
*
|
||||
* This variant of the function does not provide any life-cycle management.
|
||||
*
|
||||
* Most client programs should use hb_ft_font_create_referenced()
|
||||
* instead.
|
||||
*
|
||||
* If you know you have valid reasons not to use hb_ft_font_create_referenced(),
|
||||
* then it is the client program's responsibility to destroy @ft_face
|
||||
* after the #hb_font_t font object has been destroyed.
|
||||
*
|
||||
* HarfBuzz will use the @destroy callback on the #hb_font_t font object
|
||||
* if it is supplied when you use this function. However, even if @destroy
|
||||
* is provided, it is the client program's responsibility to destroy @ft_face,
|
||||
* and it is the client program's responsibility to ensure that @ft_face is
|
||||
* destroyed only after the #hb_font_t font object has been destroyed.
|
||||
*
|
||||
* Return value: (transfer full): the new #hb_font_t font object
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
hb_font_t *
|
||||
|
@ -812,16 +700,6 @@ hb_ft_font_create (FT_Face ft_face,
|
|||
return font;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ft_font_has_changed:
|
||||
* @font: #hb_font_t to work upon
|
||||
*
|
||||
* Refreshes the state of @font when the underlying FT_Face has changed.
|
||||
* This function should be called after changing the size or
|
||||
* variation-axis settings on the FT_Face.
|
||||
*
|
||||
* Since: 1.0.5
|
||||
**/
|
||||
void
|
||||
hb_ft_font_changed (hb_font_t *font)
|
||||
{
|
||||
|
@ -840,7 +718,7 @@ hb_ft_font_changed (hb_font_t *font)
|
|||
ft_face->size->metrics.y_ppem);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
|
||||
#ifdef HAVE_FT_GET_VAR_BLEND_COORDINATES
|
||||
FT_MM_Var *mm_var = nullptr;
|
||||
if (!FT_Get_MM_Var (ft_face, &mm_var))
|
||||
{
|
||||
|
@ -877,23 +755,11 @@ hb_ft_font_changed (hb_font_t *font)
|
|||
|
||||
/**
|
||||
* hb_ft_font_create_referenced:
|
||||
* @ft_face: FT_Face to work upon
|
||||
* @ft_face:
|
||||
*
|
||||
* Creates an #hb_font_t font object from the specified FT_Face.
|
||||
*
|
||||
* <note>Note: You must set the face size on @ft_face before calling
|
||||
* hb_ft_font_create_references() on it. Otherwise, HarfBuzz will not pick up
|
||||
* the face size.</note>
|
||||
*
|
||||
* This is the preferred variant of the hb_ft_font_create*
|
||||
* function family, because it calls FT_Reference_Face() on @ft_face,
|
||||
* ensuring that @ft_face remains alive as long as the resulting
|
||||
* #hb_font_t font object remains alive.
|
||||
*
|
||||
* Use this version unless you know you have good reasons not to.
|
||||
*
|
||||
* Return value: (transfer full): the new #hb_font_t font object
|
||||
*
|
||||
* Return value: (transfer full):
|
||||
* Since: 0.9.38
|
||||
**/
|
||||
hb_font_t *
|
||||
|
@ -952,28 +818,6 @@ _release_blob (FT_Face ft_face)
|
|||
hb_blob_destroy ((hb_blob_t *) ft_face->generic.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_ft_font_set_funcs:
|
||||
* @font: #hb_font_t to work upon
|
||||
*
|
||||
* Configures the font-functions structure of the specified
|
||||
* #hb_font_t font object to use FreeType font functions.
|
||||
*
|
||||
* In particular, you can use this function to configure an
|
||||
* existing #hb_face_t face object for use with FreeType font
|
||||
* functions even if that #hb_face_t face object was initially
|
||||
* created with hb_face_create(), and therefore was not
|
||||
* initially configured to use FreeType font functions.
|
||||
*
|
||||
* An #hb_face_t face object created with hb_ft_face_create()
|
||||
* is preconfigured for FreeType font functions and does not
|
||||
* require this function to be used.
|
||||
*
|
||||
* <note>Note: Internally, this function creates an FT_Face.
|
||||
* </note>
|
||||
*
|
||||
* Since: 1.0.5
|
||||
**/
|
||||
void
|
||||
hb_ft_font_set_funcs (hb_font_t *font)
|
||||
{
|
||||
|
@ -1013,7 +857,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
|||
FT_Set_Transform (ft_face, &matrix, nullptr);
|
||||
}
|
||||
|
||||
#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
|
||||
#ifdef HAVE_FT_SET_VAR_BLEND_COORDINATES
|
||||
unsigned int num_coords;
|
||||
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
|
||||
if (num_coords)
|
||||
|
|
|
@ -110,12 +110,6 @@ hb_ft_font_create_referenced (FT_Face ft_face);
|
|||
HB_EXTERN FT_Face
|
||||
hb_ft_font_get_face (hb_font_t *font);
|
||||
|
||||
HB_EXTERN FT_Face
|
||||
hb_ft_font_lock_face (hb_font_t *font);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_ft_font_unlock_face (hb_font_t *font);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
|
||||
|
||||
|
|
|
@ -41,11 +41,7 @@
|
|||
* @short_description: GLib integration
|
||||
* @include: hb-glib.h
|
||||
*
|
||||
* Functions for using HarfBuzz with the GLib library.
|
||||
*
|
||||
* HarfBuzz supports using GLib to provide Unicode data, by attaching
|
||||
* GLib functions to the virtual methods in a #hb_unicode_funcs_t function
|
||||
* structure.
|
||||
* Functions for using HarfBuzz with the GLib library to provide Unicode data.
|
||||
**/
|
||||
|
||||
|
||||
|
@ -173,17 +169,6 @@ glib_script_to_script[] =
|
|||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_glib_script_to_script:
|
||||
* @script: The GUnicodeScript identifier to query
|
||||
*
|
||||
* Fetches the #hb_script_t script that corresponds to the
|
||||
* specified GUnicodeScript identifier.
|
||||
*
|
||||
* Return value: the #hb_script_t script found
|
||||
*
|
||||
* Since: 0.9.38
|
||||
**/
|
||||
hb_script_t
|
||||
hb_glib_script_to_script (GUnicodeScript script)
|
||||
{
|
||||
|
@ -200,17 +185,6 @@ hb_glib_script_to_script (GUnicodeScript script)
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_glib_script_from_script:
|
||||
* @script: The #hb_script_t to query
|
||||
*
|
||||
* Fetches the GUnicodeScript identifier that corresponds to the
|
||||
* specified #hb_script_t script.
|
||||
*
|
||||
* Return value: the GUnicodeScript identifier found
|
||||
*
|
||||
* Since: 0.9.38
|
||||
**/
|
||||
GUnicodeScript
|
||||
hb_glib_script_from_script (hb_script_t script)
|
||||
{
|
||||
|
@ -399,16 +373,6 @@ void free_static_glib_funcs ()
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_glib_get_unicode_funcs:
|
||||
*
|
||||
* Fetches a Unicode-functions structure that is populated
|
||||
* with the appropriate GLib function for each method.
|
||||
*
|
||||
* Return value: (transfer none): a pointer to the #hb_unicode_funcs_t Unicode-functions structure
|
||||
*
|
||||
* Since: 0.9.38
|
||||
**/
|
||||
hb_unicode_funcs_t *
|
||||
hb_glib_get_unicode_funcs ()
|
||||
{
|
||||
|
@ -427,12 +391,6 @@ _hb_g_bytes_unref (void *data)
|
|||
|
||||
/**
|
||||
* hb_glib_blob_create:
|
||||
* @gbytes: the GBytes structure to work upon
|
||||
*
|
||||
* Creates an #hb_blob_t blob from the specified
|
||||
* GBytes data structure.
|
||||
*
|
||||
* Return value: (transfer full): the new #hb_blob_t blob object
|
||||
*
|
||||
* Since: 0.9.38
|
||||
**/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*** BEGIN file-header ***/
|
||||
/*
|
||||
* Copyright (C) 2011 Google, Inc.
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*** BEGIN file-header ***/
|
||||
/*
|
||||
* Copyright (C) 2013 Google, Inc.
|
||||
* Copyright © 2013 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
|
|
@ -32,20 +32,11 @@
|
|||
/**
|
||||
* SECTION:hb-gobject
|
||||
* @title: hb-gobject
|
||||
* @short_description: GObject integration support
|
||||
* @short_description: GObject integration
|
||||
* @include: hb-gobject.h
|
||||
*
|
||||
* Support for using HarfBuzz with the GObject library to provide
|
||||
* Functions for using HarfBuzz with the GObject library to provide
|
||||
* type data.
|
||||
*
|
||||
* The types and functions listed here are solely a linkage between
|
||||
* HarfBuzz's public data types and the GTypes used by the GObject framework.
|
||||
* HarfBuzz uses GObject introspection to generate its Python bindings
|
||||
* (and potentially other language bindings); client programs should never need
|
||||
* to access the GObject-integration mechanics.
|
||||
*
|
||||
* For client programs using the GNOME and GTK software stack, please see the
|
||||
* GLib and FreeType integration pages.
|
||||
**/
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Google, Inc.
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Google, Inc.
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
|
|
@ -45,11 +45,7 @@
|
|||
* @short_description: Graphite2 integration
|
||||
* @include: hb-graphite2.h
|
||||
*
|
||||
* Functions for using HarfBuzz with fonts that include Graphite features.
|
||||
*
|
||||
* For Graphite features to work, you must be sure that HarfBuzz was compiled
|
||||
* with the `graphite2` shaping engine enabled. Currently, the default is to
|
||||
* not enable `graphite2` shaping.
|
||||
* Functions for using HarfBuzz with the Graphite2 fonts.
|
||||
**/
|
||||
|
||||
|
||||
|
@ -156,15 +152,7 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
|
|||
free (data);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_graphite2_face_get_gr_face:
|
||||
* @face: @hb_face_t to query
|
||||
*
|
||||
* Fetches the Graphite2 gr_face corresponding to the specified
|
||||
* #hb_face_t face object.
|
||||
*
|
||||
* Return value: the gr_face found
|
||||
*
|
||||
/*
|
||||
* Since: 0.9.10
|
||||
*/
|
||||
gr_face *
|
||||
|
@ -388,7 +376,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
|
|||
buffer->len = glyph_count;
|
||||
|
||||
/* Positioning. */
|
||||
unsigned int currclus = UINT_MAX;
|
||||
unsigned int currclus = (unsigned int) -1;
|
||||
const hb_glyph_info_t *info = buffer->info;
|
||||
hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, nullptr);
|
||||
if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
|
||||
|
|
|
@ -32,15 +32,7 @@
|
|||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* HB_GRAPHITE2_TAG_SILF:
|
||||
*
|
||||
* The #hb_tag_t tag for the `Silf` table, which holds Graphite
|
||||
* features.
|
||||
*
|
||||
* For more information, see http://graphite.sil.org/
|
||||
*
|
||||
**/
|
||||
|
||||
#define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f')
|
||||
|
||||
|
||||
|
|
|
@ -54,21 +54,7 @@
|
|||
* @short_description: ICU integration
|
||||
* @include: hb-icu.h
|
||||
*
|
||||
* Functions for using HarfBuzz with the International Components for Unicode
|
||||
* (ICU) library. HarfBuzz supports using ICU to provide Unicode data, by attaching
|
||||
* ICU functions to the virtual methods in a #hb_unicode_funcs_t function
|
||||
* structure.
|
||||
**/
|
||||
|
||||
/**
|
||||
* hb_icu_script_to_script:
|
||||
* @script: The UScriptCode identifier to query
|
||||
*
|
||||
* Fetches the #hb_script_t script that corresponds to the
|
||||
* specified UScriptCode identifier.
|
||||
*
|
||||
* Return value: the #hb_script_t script found
|
||||
*
|
||||
* Functions for using HarfBuzz with the ICU library to provide Unicode data.
|
||||
**/
|
||||
|
||||
hb_script_t
|
||||
|
@ -80,16 +66,6 @@ hb_icu_script_to_script (UScriptCode script)
|
|||
return hb_script_from_string (uscript_getShortName (script), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_icu_script_from_script:
|
||||
* @script: The #hb_script_t script to query
|
||||
*
|
||||
* Fetches the UScriptCode identifier that corresponds to the
|
||||
* specified #hb_script_t script.
|
||||
*
|
||||
* Return value: the UScriptCode identifier found
|
||||
*
|
||||
**/
|
||||
UScriptCode
|
||||
hb_icu_script_from_script (hb_script_t script)
|
||||
{
|
||||
|
@ -374,16 +350,6 @@ void free_static_icu_funcs ()
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hb_icu_get_unicode_funcs:
|
||||
*
|
||||
* Fetches a Unicode-functions structure that is populated
|
||||
* with the appropriate ICU function for each method.
|
||||
*
|
||||
* Return value: (transfer none): a pointer to the #hb_unicode_funcs_t Unicode-functions structure
|
||||
*
|
||||
* Since: 0.9.38
|
||||
**/
|
||||
hb_unicode_funcs_t *
|
||||
hb_icu_get_unicode_funcs ()
|
||||
{
|
||||
|
|
|
@ -52,7 +52,8 @@ struct hb_kern_machine_t
|
|||
OT::hb_ot_apply_context_t c (1, font, buffer);
|
||||
c.set_lookup_mask (kern_mask);
|
||||
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
|
||||
auto &skippy_iter = c.iter_input;
|
||||
OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
|
||||
skippy_iter.init (&c);
|
||||
|
||||
bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
|
||||
unsigned int count = buffer->len;
|
||||
|
|
|
@ -41,6 +41,22 @@
|
|||
* Casts
|
||||
*/
|
||||
|
||||
/* Cast to struct T, reference to reference */
|
||||
template<typename Type, typename TObject>
|
||||
static inline const Type& CastR(const TObject &X)
|
||||
{ return reinterpret_cast<const Type&> (X); }
|
||||
template<typename Type, typename TObject>
|
||||
static inline Type& CastR(TObject &X)
|
||||
{ return reinterpret_cast<Type&> (X); }
|
||||
|
||||
/* Cast to struct T, pointer to pointer */
|
||||
template<typename Type, typename TObject>
|
||||
static inline const Type* CastP(const TObject *X)
|
||||
{ return reinterpret_cast<const Type*> (X); }
|
||||
template<typename Type, typename TObject>
|
||||
static inline Type* CastP(TObject *X)
|
||||
{ return reinterpret_cast<Type*> (X); }
|
||||
|
||||
/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
|
||||
* location pointed to by P plus Ofs bytes. */
|
||||
template<typename Type>
|
||||
|
@ -54,7 +70,7 @@ static inline const Type& StructAtOffsetUnaligned(const void *P, unsigned int of
|
|||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
return * reinterpret_cast<const Type*> ((const char *) P + offset);
|
||||
return * reinterpret_cast<Type*> ((char *) P + offset);
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
template<typename Type>
|
||||
|
@ -119,7 +135,7 @@ static inline Type& StructAfter(TObject &X)
|
|||
|
||||
#define DEFINE_SIZE_ARRAY(size, array) \
|
||||
DEFINE_COMPILES_ASSERTION ((void) (array)[0].static_size) \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + (HB_VAR_ARRAY+0) * sizeof ((array)[0])) \
|
||||
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + HB_VAR_ARRAY * sizeof ((array)[0])) \
|
||||
static constexpr unsigned null_size = (size); \
|
||||
static constexpr unsigned min_size = (size)
|
||||
|
||||
|
@ -234,7 +250,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
|
|||
static Returned* convert (Stored *p) { return p; }
|
||||
|
||||
/* By default null/init/fini the object. */
|
||||
static const Stored* get_null () { return &Null (Stored); }
|
||||
static const Stored* get_null () { return &Null(Stored); }
|
||||
static Stored *create (Data *data)
|
||||
{
|
||||
Stored *p = (Stored *) calloc (1, sizeof (Stored));
|
||||
|
|
|
@ -69,7 +69,7 @@ hb_map_create ()
|
|||
hb_map_t *
|
||||
hb_map_get_empty ()
|
||||
{
|
||||
return const_cast<hb_map_t *> (&Null (hb_map_t));
|
||||
return const_cast<hb_map_t *> (&Null(hb_map_t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -135,8 +135,8 @@ struct hb_hashmap_t
|
|||
for (unsigned int i = 0; i < old_size; i++)
|
||||
if (old_items[i].is_real ())
|
||||
set_with_hash (old_items[i].key,
|
||||
old_items[i].hash,
|
||||
old_items[i].value);
|
||||
old_items[i].hash,
|
||||
old_items[i].value);
|
||||
|
||||
free (old_items);
|
||||
|
||||
|
@ -211,7 +211,7 @@ struct hb_hashmap_t
|
|||
)
|
||||
|
||||
/* Sink interface. */
|
||||
hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
|
||||
hb_hashmap_t<K, V, kINVALID, vINVALID>& operator << (const hb_pair_t<K, V>& v)
|
||||
{ set (v.first, v.second); return *this; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -396,16 +396,5 @@ using hb_is_trivial= hb_bool_constant<
|
|||
>;
|
||||
#define hb_is_trivial(T) hb_is_trivial<T>::value
|
||||
|
||||
/* hb_unwrap_type (T)
|
||||
* If T has no T::type, returns T. Otherwise calls itself on T::type recursively.
|
||||
*/
|
||||
|
||||
template <typename T, typename>
|
||||
struct _hb_unwrap_type : hb_type_identity_t<T> {};
|
||||
template <typename T>
|
||||
struct _hb_unwrap_type<T, hb_void_t<typename T::type>> : _hb_unwrap_type<typename T::type, void> {};
|
||||
template <typename T>
|
||||
using hb_unwrap_type = _hb_unwrap_type<T, void>;
|
||||
#define hb_unwrap_type(T) typename hb_unwrap_type<T>::type
|
||||
|
||||
#endif /* HB_META_HH */
|
||||
|
|
|
@ -104,7 +104,7 @@ struct NullHelper
|
|||
} \
|
||||
}; \
|
||||
namespace Namespace { \
|
||||
static_assert (true, "") /* Require semicolon after. */
|
||||
static_assert (true, "Just so we take semicolon after.")
|
||||
#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
|
||||
const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
|
||||
|
||||
|
@ -117,7 +117,7 @@ struct NullHelper
|
|||
return _hb_Null_##Type; \
|
||||
} \
|
||||
}; \
|
||||
static_assert (true, "") /* Require semicolon after. */
|
||||
static_assert (true, "Just so we take semicolon after.")
|
||||
#define DEFINE_NULL_INSTANCE(Type) \
|
||||
const Type _hb_Null_##Type
|
||||
|
||||
|
@ -135,7 +135,7 @@ template <typename Type>
|
|||
static inline Type& Crap () {
|
||||
static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
|
||||
Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
|
||||
memcpy (obj, &Null (Type), sizeof (*obj));
|
||||
memcpy (obj, &Null(Type), sizeof (*obj));
|
||||
return *obj;
|
||||
}
|
||||
template <typename QType>
|
||||
|
@ -148,11 +148,11 @@ struct CrapHelper
|
|||
|
||||
template <typename Type>
|
||||
struct CrapOrNullHelper {
|
||||
static Type & get () { return Crap (Type); }
|
||||
static Type & get () { return Crap(Type); }
|
||||
};
|
||||
template <typename Type>
|
||||
struct CrapOrNullHelper<const Type> {
|
||||
static const Type & get () { return Null (Type); }
|
||||
static const Type & get () { return Null(Type); }
|
||||
};
|
||||
#define CrapOrNull(Type) CrapOrNullHelper<Type>::get ()
|
||||
|
||||
|
@ -174,7 +174,7 @@ struct hb_nonnull_ptr_t
|
|||
/* Only auto-cast to const types. */
|
||||
template <typename C> operator const C * () const { return get (); }
|
||||
operator const char * () const { return (const char *) get (); }
|
||||
T * get () const { return v ? v : const_cast<T *> (&Null (T)); }
|
||||
T * get () const { return v ? v : const_cast<T *> (&Null(T)); }
|
||||
T * get_raw () const { return v; }
|
||||
|
||||
T *v;
|
||||
|
|
|
@ -30,8 +30,10 @@
|
|||
|
||||
#include "hb.hh"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#line 35 "hb-number-parser.hh"
|
||||
|
||||
#line 37 "hb-number-parser.hh"
|
||||
static const unsigned char _double_parser_trans_keys[] = {
|
||||
0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u,
|
||||
46u, 101u, 0
|
||||
|
@ -91,12 +93,12 @@ static const int double_parser_error = 0;
|
|||
static const int double_parser_en_main = 1;
|
||||
|
||||
|
||||
#line 68 "hb-number-parser.rl"
|
||||
#line 70 "hb-number-parser.rl"
|
||||
|
||||
|
||||
/* Works only for n < 512 */
|
||||
static inline double
|
||||
_pow10 (unsigned exponent)
|
||||
_pow10 (unsigned int exponent)
|
||||
{
|
||||
static const double _powers_of_10[] =
|
||||
{
|
||||
|
@ -110,37 +112,38 @@ _pow10 (unsigned exponent)
|
|||
100.,
|
||||
10.
|
||||
};
|
||||
unsigned mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
|
||||
unsigned int mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
|
||||
double result = 1;
|
||||
for (const double *power = _powers_of_10; mask; ++power, mask >>= 1)
|
||||
if (exponent & mask) result *= *power;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* a variant of strtod that also gets end of buffer in its second argument */
|
||||
static inline double
|
||||
strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
|
||||
strtod_rl (const char *buf, char **end_ptr)
|
||||
{
|
||||
const char *p, *pe;
|
||||
double value = 0;
|
||||
double frac = 0;
|
||||
double frac_count = 0;
|
||||
unsigned exp = 0;
|
||||
unsigned int exp = 0;
|
||||
bool neg = false, exp_neg = false, exp_overflow = false;
|
||||
const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 2^52-1 */
|
||||
const unsigned MAX_EXP = 0x7FFu; /* 2^11-1 */
|
||||
const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
|
||||
const unsigned int MAX_EXP = 0x7FFu; /* 1^11-1 */
|
||||
p = buf;
|
||||
pe = p + strlen (p);
|
||||
|
||||
const char *pe = *end_ptr;
|
||||
while (p < pe && ISSPACE (*p))
|
||||
p++;
|
||||
|
||||
int cs;
|
||||
|
||||
#line 139 "hb-number-parser.hh"
|
||||
#line 142 "hb-number-parser.hh"
|
||||
{
|
||||
cs = double_parser_start;
|
||||
}
|
||||
|
||||
#line 144 "hb-number-parser.hh"
|
||||
#line 147 "hb-number-parser.hh"
|
||||
{
|
||||
int _slen;
|
||||
int _trans;
|
||||
|
@ -166,21 +169,21 @@ _resume:
|
|||
|
||||
switch ( _double_parser_trans_actions[_trans] ) {
|
||||
case 1:
|
||||
#line 37 "hb-number-parser.rl"
|
||||
#line 39 "hb-number-parser.rl"
|
||||
{ neg = true; }
|
||||
break;
|
||||
case 4:
|
||||
#line 38 "hb-number-parser.rl"
|
||||
#line 40 "hb-number-parser.rl"
|
||||
{ exp_neg = true; }
|
||||
break;
|
||||
case 2:
|
||||
#line 40 "hb-number-parser.rl"
|
||||
#line 42 "hb-number-parser.rl"
|
||||
{
|
||||
value = value * 10. + ((*p) - '0');
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
#line 43 "hb-number-parser.rl"
|
||||
#line 45 "hb-number-parser.rl"
|
||||
{
|
||||
if (likely (frac <= MAX_FRACT / 10))
|
||||
{
|
||||
|
@ -190,7 +193,7 @@ _resume:
|
|||
}
|
||||
break;
|
||||
case 5:
|
||||
#line 50 "hb-number-parser.rl"
|
||||
#line 52 "hb-number-parser.rl"
|
||||
{
|
||||
if (likely (exp * 10 + ((*p) - '0') <= MAX_EXP))
|
||||
exp = exp * 10 + ((*p) - '0');
|
||||
|
@ -198,7 +201,7 @@ _resume:
|
|||
exp_overflow = true;
|
||||
}
|
||||
break;
|
||||
#line 202 "hb-number-parser.hh"
|
||||
#line 205 "hb-number-parser.hh"
|
||||
}
|
||||
|
||||
_again:
|
||||
|
@ -210,10 +213,10 @@ _again:
|
|||
_out: {}
|
||||
}
|
||||
|
||||
#line 113 "hb-number-parser.rl"
|
||||
#line 116 "hb-number-parser.rl"
|
||||
|
||||
|
||||
*end_ptr = p;
|
||||
*end_ptr = (char *) p;
|
||||
|
||||
if (frac_count) value += frac / _pow10 (frac_count);
|
||||
if (neg) value *= -1.;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "hb.hh"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
%%{
|
||||
|
||||
machine double_parser;
|
||||
|
@ -69,7 +71,7 @@ main := (
|
|||
|
||||
/* Works only for n < 512 */
|
||||
static inline double
|
||||
_pow10 (unsigned exponent)
|
||||
_pow10 (unsigned int exponent)
|
||||
{
|
||||
static const double _powers_of_10[] =
|
||||
{
|
||||
|
@ -83,26 +85,27 @@ _pow10 (unsigned exponent)
|
|||
100.,
|
||||
10.
|
||||
};
|
||||
unsigned mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
|
||||
unsigned int mask = 1 << (ARRAY_LENGTH (_powers_of_10) - 1);
|
||||
double result = 1;
|
||||
for (const double *power = _powers_of_10; mask; ++power, mask >>= 1)
|
||||
if (exponent & mask) result *= *power;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* a variant of strtod that also gets end of buffer in its second argument */
|
||||
static inline double
|
||||
strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
|
||||
strtod_rl (const char *buf, char **end_ptr)
|
||||
{
|
||||
const char *p, *pe;
|
||||
double value = 0;
|
||||
double frac = 0;
|
||||
double frac_count = 0;
|
||||
unsigned exp = 0;
|
||||
unsigned int exp = 0;
|
||||
bool neg = false, exp_neg = false, exp_overflow = false;
|
||||
const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 2^52-1 */
|
||||
const unsigned MAX_EXP = 0x7FFu; /* 2^11-1 */
|
||||
const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
|
||||
const unsigned int MAX_EXP = 0x7FFu; /* 1^11-1 */
|
||||
p = buf;
|
||||
pe = p + strlen (p);
|
||||
|
||||
const char *pe = *end_ptr;
|
||||
while (p < pe && ISSPACE (*p))
|
||||
p++;
|
||||
|
||||
|
@ -112,7 +115,7 @@ strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
|
|||
write exec;
|
||||
}%%
|
||||
|
||||
*end_ptr = p;
|
||||
*end_ptr = (char *) p;
|
||||
|
||||
if (frac_count) value += frac / _pow10 (frac_count);
|
||||
if (neg) value *= -1.;
|
||||
|
|
|
@ -25,16 +25,21 @@
|
|||
|
||||
#include "hb.hh"
|
||||
#include "hb-machinery.hh"
|
||||
#include "hb-number.hh"
|
||||
#include "hb-number-parser.hh"
|
||||
|
||||
#include <locale.h>
|
||||
#ifdef HAVE_XLOCALE_H
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
template<typename T, typename Func>
|
||||
static bool
|
||||
_parse_number (const char **pp, const char *end, T *pv,
|
||||
bool whole_buffer, Func f)
|
||||
{
|
||||
char buf[32];
|
||||
unsigned len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned) (end - *pp));
|
||||
unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1,
|
||||
(unsigned int) (end - *pp));
|
||||
strncpy (buf, *pp, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
|
@ -45,8 +50,7 @@ _parse_number (const char **pp, const char *end, T *pv,
|
|||
*pv = f (p, &pend);
|
||||
if (unlikely (errno || p == pend ||
|
||||
/* Check if consumed whole buffer if is requested */
|
||||
(whole_buffer && pend - p != end - *pp)))
|
||||
return false;
|
||||
(whole_buffer && pend - p != end - *pp))) return false;
|
||||
|
||||
*pp += pend - p;
|
||||
return true;
|
||||
|
@ -61,20 +65,83 @@ hb_parse_int (const char **pp, const char *end, int *pv, bool whole_buffer)
|
|||
}
|
||||
|
||||
bool
|
||||
hb_parse_uint (const char **pp, const char *end, unsigned *pv,
|
||||
hb_parse_uint (const char **pp, const char *end, unsigned int *pv,
|
||||
bool whole_buffer, int base)
|
||||
{
|
||||
return _parse_number<unsigned> (pp, end, pv, whole_buffer,
|
||||
[base] (const char *p, char **end)
|
||||
{ return strtoul (p, end, base); });
|
||||
return _parse_number<unsigned int> (pp, end, pv, whole_buffer,
|
||||
[base] (const char *p, char **end)
|
||||
{ return strtoul (p, end, base); });
|
||||
}
|
||||
|
||||
bool
|
||||
hb_parse_double (const char **pp, const char *end, double *pv, bool whole_buffer)
|
||||
|
||||
#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L)
|
||||
#define USE_XLOCALE 1
|
||||
#define HB_LOCALE_T locale_t
|
||||
#define HB_CREATE_LOCALE(locName) newlocale (LC_ALL_MASK, locName, nullptr)
|
||||
#define HB_FREE_LOCALE(loc) freelocale (loc)
|
||||
#elif defined(_MSC_VER)
|
||||
#define USE_XLOCALE 1
|
||||
#define HB_LOCALE_T _locale_t
|
||||
#define HB_CREATE_LOCALE(locName) _create_locale (LC_ALL, locName)
|
||||
#define HB_FREE_LOCALE(loc) _free_locale (loc)
|
||||
#define strtod_l(a, b, c) _strtod_l ((a), (b), (c))
|
||||
#endif
|
||||
|
||||
#ifdef USE_XLOCALE
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static void free_static_C_locale ();
|
||||
#endif
|
||||
|
||||
static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<HB_LOCALE_T>,
|
||||
hb_C_locale_lazy_loader_t>
|
||||
{
|
||||
const char *pend = end;
|
||||
*pv = strtod_rl (*pp, &pend);
|
||||
if (unlikely (*pp == pend)) return false;
|
||||
*pp = pend;
|
||||
return !whole_buffer || end == pend;
|
||||
static HB_LOCALE_T create ()
|
||||
{
|
||||
HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
atexit (free_static_C_locale);
|
||||
#endif
|
||||
|
||||
return C_locale;
|
||||
}
|
||||
static void destroy (HB_LOCALE_T p)
|
||||
{
|
||||
HB_FREE_LOCALE (p);
|
||||
}
|
||||
static HB_LOCALE_T get_null ()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
} static_C_locale;
|
||||
|
||||
#if HB_USE_ATEXIT
|
||||
static
|
||||
void free_static_C_locale ()
|
||||
{
|
||||
static_C_locale.free_instance ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static HB_LOCALE_T
|
||||
get_C_locale ()
|
||||
{
|
||||
return static_C_locale.get_unconst ();
|
||||
}
|
||||
#endif /* USE_XLOCALE */
|
||||
|
||||
bool
|
||||
hb_parse_double (const char **pp, const char *end, double *pv,
|
||||
bool whole_buffer)
|
||||
{
|
||||
return _parse_number<double> (pp, end, pv, whole_buffer,
|
||||
[] (const char *p, char **end)
|
||||
{
|
||||
#ifdef USE_XLOCALE
|
||||
return strtod_l (p, end, get_C_locale ());
|
||||
#else
|
||||
return strtod_rl (p, end);
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@ struct TTCHeader
|
|||
switch (u.header.version.major) {
|
||||
case 2: /* version 2 is compatible with version 1 */
|
||||
case 1: return u.version1.get_face (i);
|
||||
default:return Null (OpenTypeFontFace);
|
||||
default:return Null(OpenTypeFontFace);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ struct TTCHeader
|
|||
struct ResourceRecord
|
||||
{
|
||||
const OpenTypeFontFace & get_face (const void *data_base) const
|
||||
{ return * reinterpret_cast<const OpenTypeFontFace *> ((data_base+offset).arrayZ); }
|
||||
{ return CastR<OpenTypeFontFace> ((data_base+offset).arrayZ); }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c,
|
||||
const void *data_base) const
|
||||
|
@ -478,7 +478,7 @@ struct OpenTypeFontFile
|
|||
case TrueTypeTag: return u.fontFace;
|
||||
case TTCTag: return u.ttcHeader.get_face (i);
|
||||
case DFontTag: return u.rfHeader.get_face (i, base_offset);
|
||||
default: return Null (OpenTypeFontFace);
|
||||
default: return Null(OpenTypeFontFace);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,13 +73,6 @@ struct IntType
|
|||
|
||||
HB_INTERNAL static int cmp (const IntType *a, const IntType *b)
|
||||
{ return b->cmp (*a); }
|
||||
HB_INTERNAL static int cmp (const void *a, const void *b)
|
||||
{
|
||||
IntType *pa = (IntType *) a;
|
||||
IntType *pb = (IntType *) b;
|
||||
|
||||
return pb->cmp (*pa);
|
||||
}
|
||||
template <typename Type2>
|
||||
int cmp (Type2 a) const
|
||||
{
|
||||
|
@ -313,8 +306,11 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
}
|
||||
|
||||
template <typename ...Ts>
|
||||
bool serialize_subset (hb_subset_context_t *c, const OffsetTo& src,
|
||||
const void *src_base, Ts&&... ds)
|
||||
bool serialize_subset (hb_subset_context_t *c,
|
||||
const OffsetTo& src,
|
||||
const void *src_base,
|
||||
const void *dst_base,
|
||||
Ts&&... ds)
|
||||
{
|
||||
*this = 0;
|
||||
if (src.is_null ())
|
||||
|
@ -327,7 +323,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
bool ret = c->dispatch (src_base+src, hb_forward<Ts> (ds)...);
|
||||
|
||||
if (ret || !has_null)
|
||||
s->add_link (*this, s->pop_pack ());
|
||||
s->add_link (*this, s->pop_pack (), dst_base);
|
||||
else
|
||||
s->pop_discard ();
|
||||
|
||||
|
@ -335,13 +331,11 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
}
|
||||
|
||||
/* TODO: Somehow merge this with previous function into a serialize_dispatch(). */
|
||||
/* Workaround clang bug: https://bugs.llvm.org/show_bug.cgi?id=23029
|
||||
* Can't compile: whence = hb_serialize_context_t::Head followed by Ts&&...
|
||||
*/
|
||||
template <typename ...Ts>
|
||||
bool serialize_copy (hb_serialize_context_t *c, const OffsetTo& src,
|
||||
const void *src_base, unsigned dst_bias,
|
||||
hb_serialize_context_t::whence_t whence,
|
||||
bool serialize_copy (hb_serialize_context_t *c,
|
||||
const OffsetTo& src,
|
||||
const void *src_base,
|
||||
const void *dst_base,
|
||||
Ts&&... ds)
|
||||
{
|
||||
*this = 0;
|
||||
|
@ -352,15 +346,11 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
|
||||
bool ret = c->copy (src_base+src, hb_forward<Ts> (ds)...);
|
||||
|
||||
c->add_link (*this, c->pop_pack (), whence, dst_bias);
|
||||
c->add_link (*this, c->pop_pack (), dst_base);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool serialize_copy (hb_serialize_context_t *c, const OffsetTo& src,
|
||||
const void *src_base, unsigned dst_bias = 0)
|
||||
{ return serialize_copy (c, src, src_base, dst_bias, hb_serialize_context_t::Head); }
|
||||
|
||||
bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -604,7 +594,7 @@ struct ArrayOf
|
|||
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
|
||||
{ return as_array ().sub_array (start_offset, count); }
|
||||
|
||||
hb_success_t serialize (hb_serialize_context_t *c, unsigned items_len)
|
||||
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
|
@ -614,7 +604,7 @@ struct ArrayOf
|
|||
}
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_source_of (Iterator, Type))>
|
||||
hb_success_t serialize (hb_serialize_context_t *c, Iterator items)
|
||||
bool serialize (hb_serialize_context_t *c, Iterator items)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
unsigned count = items.len ();
|
||||
|
@ -1036,15 +1026,18 @@ struct VarSizedBinSearchArrayOf
|
|||
template <typename T>
|
||||
const Type *bsearch (const T &key) const
|
||||
{
|
||||
unsigned pos;
|
||||
return hb_bsearch_impl (&pos,
|
||||
key,
|
||||
(const void *) bytesZ,
|
||||
get_length (),
|
||||
header.unitSize,
|
||||
_hb_cmp_method<T, Type>)
|
||||
? (const Type *) (((const char *) &bytesZ) + (pos * header.unitSize))
|
||||
: nullptr;
|
||||
unsigned int size = header.unitSize;
|
||||
int min = 0, max = (int) get_length () - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = ((unsigned int) min + (unsigned int) max) / 2;
|
||||
const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
|
||||
int c = p->cmp (key);
|
||||
if (c < 0) max = mid - 1;
|
||||
else if (c > 0) min = mid + 1;
|
||||
else return p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -38,9 +38,6 @@ using namespace OT;
|
|||
|
||||
#define CFF_UNDEF_CODE 0xFFFFFFFF
|
||||
|
||||
using objidx_t = hb_serialize_context_t::objidx_t;
|
||||
using whence_t = hb_serialize_context_t::whence_t;
|
||||
|
||||
/* utility macro */
|
||||
template<typename Type>
|
||||
static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset)
|
||||
|
@ -92,14 +89,11 @@ struct CFFIndex
|
|||
unsigned int offset_array_size () const
|
||||
{ return calculate_offset_array_size (offSize, count); }
|
||||
|
||||
CFFIndex *copy (hb_serialize_context_t *c) const
|
||||
static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count,
|
||||
unsigned int dataSize)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
unsigned int size = get_size ();
|
||||
CFFIndex *out = c->allocate_size<CFFIndex> (size);
|
||||
if (likely (out))
|
||||
memcpy (out, this, size);
|
||||
return_trace (out);
|
||||
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)
|
||||
|
@ -107,7 +101,7 @@ struct CFFIndex
|
|||
TRACE_SERIALIZE (this);
|
||||
unsigned int size = src.get_size ();
|
||||
CFFIndex *dest = c->allocate_size<CFFIndex> (size);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
memcpy (dest, &src, size);
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -120,7 +114,7 @@ struct CFFIndex
|
|||
if (byteArray.length == 0)
|
||||
{
|
||||
COUNT *dest = c->allocate_min<COUNT> ();
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
*dest = 0;
|
||||
}
|
||||
else
|
||||
|
@ -145,9 +139,10 @@ struct CFFIndex
|
|||
/* serialize data */
|
||||
for (unsigned int i = 0; i < byteArray.length; i++)
|
||||
{
|
||||
const byte_str_t &bs = byteArray[i];
|
||||
unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
const byte_str_t &bs = byteArray[i];
|
||||
unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
|
||||
if (unlikely (dest == nullptr))
|
||||
return_trace (false);
|
||||
memcpy (dest, &bs[0], bs.length);
|
||||
}
|
||||
}
|
||||
|
@ -168,71 +163,6 @@ struct CFFIndex
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (it.len () == 0)
|
||||
{
|
||||
COUNT *dest = c->allocate_min<COUNT> ();
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
*dest = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; }));
|
||||
for (const byte_str_t &_ : +it)
|
||||
_.copy (c);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const byte_str_array_t &byteArray)
|
||||
{ return serialize (c, + hb_iter (byteArray)); }
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const str_buff_vec_t &buffArray)
|
||||
{
|
||||
auto it =
|
||||
+ hb_iter (buffArray)
|
||||
| hb_map ([] (const str_buff_t &_) { return byte_str_t (_.arrayZ, _.length); })
|
||||
;
|
||||
return serialize (c, it);
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool serialize_header (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
unsigned total = + it | hb_reduce (hb_add, 0);
|
||||
unsigned off_size = calcOffSize (total);
|
||||
|
||||
/* serialize CFFIndex header */
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
this->count = it.len ();
|
||||
this->offSize = off_size;
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (off_size * (it.len () + 1))))
|
||||
return_trace (false);
|
||||
|
||||
/* serialize indices */
|
||||
unsigned int offset = 1;
|
||||
unsigned int i = 0;
|
||||
for (unsigned _ : +it)
|
||||
{
|
||||
CFFIndex<COUNT>::set_offset_at (i++, offset);
|
||||
offset += _;
|
||||
}
|
||||
CFFIndex<COUNT>::set_offset_at (i, offset);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
void set_offset_at (unsigned int index, unsigned int offset)
|
||||
{
|
||||
HBUINT8 *p = offsets + offSize * index + offSize;
|
||||
|
@ -259,7 +189,7 @@ struct CFFIndex
|
|||
unsigned int length_at (unsigned int index) const
|
||||
{
|
||||
if (unlikely ((offset_at (index + 1) < offset_at (index)) ||
|
||||
(offset_at (index + 1) > offset_at (count))))
|
||||
(offset_at (index + 1) > offset_at (count))))
|
||||
return 0;
|
||||
return offset_at (index + 1) - offset_at (index);
|
||||
}
|
||||
|
@ -307,8 +237,7 @@ struct CFFIndex
|
|||
public:
|
||||
COUNT count; /* Number of object data. Note there are (count+1) offsets */
|
||||
HBUINT8 offSize; /* The byte size of each offset in the offsets array. */
|
||||
HBUINT8 offsets[HB_VAR_ARRAY];
|
||||
/* The array of (count + 1) offsets into objects array (1-base). */
|
||||
HBUINT8 offsets[HB_VAR_ARRAY]; /* The array of (count + 1) offsets into objects array (1-base). */
|
||||
/* HBUINT8 data[HB_VAR_ARRAY]; Object data */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
|
||||
|
@ -321,7 +250,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
|
|||
{
|
||||
if (likely (index < CFFIndex<COUNT>::count))
|
||||
return byte_str_t (CFFIndex<COUNT>::data_base () + CFFIndex<COUNT>::offset_at (index) - 1, CFFIndex<COUNT>::length_at (index));
|
||||
return Null (byte_str_t);
|
||||
return Null(byte_str_t);
|
||||
}
|
||||
|
||||
template <typename DATA, typename PARAM1, typename PARAM2>
|
||||
|
@ -355,41 +284,85 @@ struct CFFIndexOf : CFFIndex<COUNT>
|
|||
for (unsigned int i = 0; i < dataArrayLen; i++)
|
||||
{
|
||||
TYPE *dest = c->start_embed<TYPE> ();
|
||||
if (unlikely (!dest || !dest->serialize (c, dataArray[i], param1, param2)))
|
||||
if (unlikely (dest == nullptr ||
|
||||
!dest->serialize (c, dataArray[i], param1, param2)))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
/* in parallel to above */
|
||||
template <typename DATA, typename PARAM>
|
||||
static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
|
||||
const DATA *dataArray,
|
||||
unsigned int dataArrayLen,
|
||||
hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
|
||||
const PARAM ¶m)
|
||||
{
|
||||
/* determine offset size */
|
||||
unsigned int totalDataSize = 0;
|
||||
for (unsigned int i = 0; i < dataArrayLen; i++)
|
||||
{
|
||||
unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
|
||||
dataSizeArray[i] = dataSize;
|
||||
totalDataSize += dataSize;
|
||||
}
|
||||
offSize_ = calcOffSize (totalDataSize);
|
||||
|
||||
return CFFIndex<COUNT>::calculate_serialized_size (offSize_, dataArrayLen, totalDataSize);
|
||||
}
|
||||
};
|
||||
|
||||
/* Top Dict, Font Dict, Private Dict */
|
||||
struct Dict : UnsizedByteStr
|
||||
{
|
||||
template <typename DICTVAL, typename OP_SERIALIZER, typename ...Ts>
|
||||
template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const DICTVAL &dictval,
|
||||
OP_SERIALIZER& opszr,
|
||||
Ts&&... ds)
|
||||
PARAM& param)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
for (unsigned int i = 0; i < dictval.get_count (); i++)
|
||||
if (unlikely (!opszr.serialize (c, dictval[i], hb_forward<Ts> (ds)...)))
|
||||
if (unlikely (!opszr.serialize (c, dictval[i], param)))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
template <typename T, typename V>
|
||||
static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, V value, op_code_t intOp)
|
||||
/* in parallel to above */
|
||||
template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
|
||||
static unsigned int calculate_serialized_size (const DICTVAL &dictval,
|
||||
OP_SERIALIZER& opszr,
|
||||
PARAM& param)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
for (unsigned int i = 0; i < dictval.get_count (); i++)
|
||||
size += opszr.calculate_serialized_size (dictval[i], param);
|
||||
return size;
|
||||
}
|
||||
|
||||
template <typename DICTVAL, typename OP_SERIALIZER>
|
||||
static unsigned int calculate_serialized_size (const DICTVAL &dictval,
|
||||
OP_SERIALIZER& opszr)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
for (unsigned int i = 0; i < dictval.get_count (); i++)
|
||||
size += opszr.calculate_serialized_size (dictval[i]);
|
||||
return size;
|
||||
}
|
||||
|
||||
template <typename INTTYPE, int minVal, int maxVal>
|
||||
static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, int value, op_code_t intOp)
|
||||
{
|
||||
// XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
|
||||
if (/*unlikely*/ (!serialize_int<T, V> (c, intOp, value)))
|
||||
if (/*unlikely*/ (!serialize_int<INTTYPE, minVal, maxVal> (c, intOp, value)))
|
||||
return false;
|
||||
|
||||
TRACE_SERIALIZE (this);
|
||||
/* serialize the opcode */
|
||||
HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
|
||||
if (unlikely (!p)) return_trace (false);
|
||||
if (unlikely (p == nullptr)) return_trace (false);
|
||||
if (Is_OpCode_ESC (op))
|
||||
{
|
||||
*p = OpCode_escape;
|
||||
|
@ -400,28 +373,17 @@ struct Dict : UnsizedByteStr
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
static bool serialize_int4_op (hb_serialize_context_t *c, op_code_t op, V value)
|
||||
{ return serialize_int_op<HBINT32> (c, op, value, OpCode_longintdict); }
|
||||
static bool serialize_uint4_op (hb_serialize_context_t *c, op_code_t op, int value)
|
||||
{ return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
|
||||
|
||||
template <typename V>
|
||||
static bool serialize_int2_op (hb_serialize_context_t *c, op_code_t op, V value)
|
||||
{ return serialize_int_op<HBINT16> (c, op, value, OpCode_shortint); }
|
||||
static bool serialize_uint2_op (hb_serialize_context_t *c, op_code_t op, int value)
|
||||
{ return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
|
||||
|
||||
template <typename T, int int_op>
|
||||
static bool serialize_link_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence)
|
||||
{
|
||||
T &ofs = *(T *) (c->head + OpCode_Size (int_op));
|
||||
if (unlikely (!serialize_int_op<T> (c, op, 0, int_op))) return false;
|
||||
c->add_link (ofs, link, whence);
|
||||
return true;
|
||||
}
|
||||
static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value)
|
||||
{ return serialize_uint4_op (c, op, value); }
|
||||
|
||||
static bool serialize_link4_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head)
|
||||
{ return serialize_link_op<HBINT32, OpCode_longintdict> (c, op, link, whence); }
|
||||
|
||||
static bool serialize_link2_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head)
|
||||
{ return serialize_link_op<HBINT16, OpCode_shortint> (c, op, link, whence); }
|
||||
static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value)
|
||||
{ return serialize_uint2_op (c, op, value); }
|
||||
};
|
||||
|
||||
struct TopDict : Dict {};
|
||||
|
@ -430,39 +392,105 @@ struct PrivateDict : Dict {};
|
|||
|
||||
struct table_info_t
|
||||
{
|
||||
void init () { offset = size = 0; link = 0; }
|
||||
void init () { offSize = offset = size = 0; }
|
||||
|
||||
unsigned int offset;
|
||||
unsigned int size;
|
||||
objidx_t link;
|
||||
unsigned int offSize;
|
||||
};
|
||||
|
||||
template <typename COUNT>
|
||||
struct FDArray : CFFIndexOf<COUNT, FontDict>
|
||||
{
|
||||
template <typename DICTVAL, typename INFO, typename Iterator, typename OP_SERIALIZER>
|
||||
/* used by CFF1 */
|
||||
template <typename DICTVAL, typename OP_SERIALIZER>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
unsigned int offSize_,
|
||||
const hb_vector_t<DICTVAL> &fontDicts,
|
||||
OP_SERIALIZER& opszr)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
this->count = fontDicts.length;
|
||||
this->offSize = offSize_;
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
|
||||
return_trace (false);
|
||||
|
||||
/* serialize INDEX data */
|
||||
hb_vector_t<unsigned> sizes;
|
||||
c->push ();
|
||||
+ it
|
||||
| hb_map ([&] (const hb_pair_t<const DICTVAL&, const INFO&> &_)
|
||||
/* serialize font dict offsets */
|
||||
unsigned int offset = 1;
|
||||
unsigned int fid = 0;
|
||||
for (; fid < fontDicts.length; fid++)
|
||||
{
|
||||
CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
|
||||
offset += FontDict::calculate_serialized_size (fontDicts[fid], opszr);
|
||||
}
|
||||
CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
|
||||
|
||||
/* serialize font dicts */
|
||||
for (unsigned int i = 0; i < fontDicts.length; i++)
|
||||
{
|
||||
FontDict *dict = c->start_embed<FontDict> ();
|
||||
dict->serialize (c, _.first, opszr, _.second);
|
||||
return c->head - (const char*)dict;
|
||||
})
|
||||
| hb_sink (sizes)
|
||||
;
|
||||
c->pop_pack (false);
|
||||
if (unlikely (!dict->serialize (c, fontDicts[i], opszr, fontDicts[i])))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
/* serialize INDEX header */
|
||||
return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes)));
|
||||
/* used by CFF2 */
|
||||
template <typename DICTVAL, typename OP_SERIALIZER>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
unsigned int offSize_,
|
||||
const hb_vector_t<DICTVAL> &fontDicts,
|
||||
unsigned int fdCount,
|
||||
const hb_inc_bimap_t &fdmap,
|
||||
OP_SERIALIZER& opszr,
|
||||
const hb_vector_t<table_info_t> &privateInfos)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
this->count = fdCount;
|
||||
this->offSize = offSize_;
|
||||
if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
|
||||
return_trace (false);
|
||||
|
||||
/* serialize font dict offsets */
|
||||
unsigned int offset = 1;
|
||||
unsigned int fid = 0;
|
||||
for (unsigned i = 0; i < fontDicts.length; i++)
|
||||
if (fdmap.has (i))
|
||||
{
|
||||
if (unlikely (fid >= fdCount)) return_trace (false);
|
||||
CFFIndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
|
||||
offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
|
||||
}
|
||||
CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
|
||||
|
||||
/* serialize font dicts */
|
||||
for (unsigned int i = 0; i < fontDicts.length; i++)
|
||||
if (fdmap.has (i))
|
||||
{
|
||||
FontDict *dict = c->start_embed<FontDict> ();
|
||||
if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]])))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
/* in parallel to above */
|
||||
template <typename OP_SERIALIZER, typename DICTVAL>
|
||||
static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
|
||||
const hb_vector_t<DICTVAL> &fontDicts,
|
||||
unsigned int fdCount,
|
||||
const hb_inc_bimap_t &fdmap,
|
||||
OP_SERIALIZER& opszr)
|
||||
{
|
||||
unsigned int dictsSize = 0;
|
||||
for (unsigned int i = 0; i < fontDicts.len; i++)
|
||||
if (fdmap.has (i))
|
||||
dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr);
|
||||
|
||||
offSize_ = calcOffSize (dictsSize);
|
||||
return CFFIndex<COUNT>::calculate_serialized_size (offSize_, fdCount, dictsSize);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -516,7 +544,7 @@ struct FDSelect3_4
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) ||
|
||||
(nRanges () == 0) || ranges[0].first != 0))
|
||||
(nRanges () == 0) || ranges[0].first != 0))
|
||||
return_trace (false);
|
||||
|
||||
for (unsigned int i = 1; i < nRanges (); i++)
|
||||
|
@ -560,11 +588,14 @@ struct FDSelect
|
|||
TRACE_SERIALIZE (this);
|
||||
unsigned int size = src.get_size (num_glyphs);
|
||||
FDSelect *dest = c->allocate_size<FDSelect> (size);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
memcpy (dest, &src, size);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
unsigned int calculate_serialized_size (unsigned int num_glyphs) const
|
||||
{ return get_size (num_glyphs); }
|
||||
|
||||
unsigned int get_size (unsigned int num_glyphs) const
|
||||
{
|
||||
switch (format)
|
||||
|
|
|
@ -1,425 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2019 Adobe, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Adobe Author(s): Michiharu Ariza
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_CFF1_STD_STR_HH
|
||||
#if 0 /* Make checks happy. */
|
||||
#define HB_OT_CFF1_STD_STR_HH
|
||||
#include "hb.hh"
|
||||
#endif
|
||||
|
||||
_S(".notdef")
|
||||
_S("space")
|
||||
_S("exclam")
|
||||
_S("quotedbl")
|
||||
_S("numbersign")
|
||||
_S("dollar")
|
||||
_S("percent")
|
||||
_S("ampersand")
|
||||
_S("quoteright")
|
||||
_S("parenleft")
|
||||
_S("parenright")
|
||||
_S("asterisk")
|
||||
_S("plus")
|
||||
_S("comma")
|
||||
_S("hyphen")
|
||||
_S("period")
|
||||
_S("slash")
|
||||
_S("zero")
|
||||
_S("one")
|
||||
_S("two")
|
||||
_S("three")
|
||||
_S("four")
|
||||
_S("five")
|
||||
_S("six")
|
||||
_S("seven")
|
||||
_S("eight")
|
||||
_S("nine")
|
||||
_S("colon")
|
||||
_S("semicolon")
|
||||
_S("less")
|
||||
_S("equal")
|
||||
_S("greater")
|
||||
_S("question")
|
||||
_S("at")
|
||||
_S("A")
|
||||
_S("B")
|
||||
_S("C")
|
||||
_S("D")
|
||||
_S("E")
|
||||
_S("F")
|
||||
_S("G")
|
||||
_S("H")
|
||||
_S("I")
|
||||
_S("J")
|
||||
_S("K")
|
||||
_S("L")
|
||||
_S("M")
|
||||
_S("N")
|
||||
_S("O")
|
||||
_S("P")
|
||||
_S("Q")
|
||||
_S("R")
|
||||
_S("S")
|
||||
_S("T")
|
||||
_S("U")
|
||||
_S("V")
|
||||
_S("W")
|
||||
_S("X")
|
||||
_S("Y")
|
||||
_S("Z")
|
||||
_S("bracketleft")
|
||||
_S("backslash")
|
||||
_S("bracketright")
|
||||
_S("asciicircum")
|
||||
_S("underscore")
|
||||
_S("quoteleft")
|
||||
_S("a")
|
||||
_S("b")
|
||||
_S("c")
|
||||
_S("d")
|
||||
_S("e")
|
||||
_S("f")
|
||||
_S("g")
|
||||
_S("h")
|
||||
_S("i")
|
||||
_S("j")
|
||||
_S("k")
|
||||
_S("l")
|
||||
_S("m")
|
||||
_S("n")
|
||||
_S("o")
|
||||
_S("p")
|
||||
_S("q")
|
||||
_S("r")
|
||||
_S("s")
|
||||
_S("t")
|
||||
_S("u")
|
||||
_S("v")
|
||||
_S("w")
|
||||
_S("x")
|
||||
_S("y")
|
||||
_S("z")
|
||||
_S("braceleft")
|
||||
_S("bar")
|
||||
_S("braceright")
|
||||
_S("asciitilde")
|
||||
_S("exclamdown")
|
||||
_S("cent")
|
||||
_S("sterling")
|
||||
_S("fraction")
|
||||
_S("yen")
|
||||
_S("florin")
|
||||
_S("section")
|
||||
_S("currency")
|
||||
_S("quotesingle")
|
||||
_S("quotedblleft")
|
||||
_S("guillemotleft")
|
||||
_S("guilsinglleft")
|
||||
_S("guilsinglright")
|
||||
_S("fi")
|
||||
_S("fl")
|
||||
_S("endash")
|
||||
_S("dagger")
|
||||
_S("daggerdbl")
|
||||
_S("periodcentered")
|
||||
_S("paragraph")
|
||||
_S("bullet")
|
||||
_S("quotesinglbase")
|
||||
_S("quotedblbase")
|
||||
_S("quotedblright")
|
||||
_S("guillemotright")
|
||||
_S("ellipsis")
|
||||
_S("perthousand")
|
||||
_S("questiondown")
|
||||
_S("grave")
|
||||
_S("acute")
|
||||
_S("circumflex")
|
||||
_S("tilde")
|
||||
_S("macron")
|
||||
_S("breve")
|
||||
_S("dotaccent")
|
||||
_S("dieresis")
|
||||
_S("ring")
|
||||
_S("cedilla")
|
||||
_S("hungarumlaut")
|
||||
_S("ogonek")
|
||||
_S("caron")
|
||||
_S("emdash")
|
||||
_S("AE")
|
||||
_S("ordfeminine")
|
||||
_S("Lslash")
|
||||
_S("Oslash")
|
||||
_S("OE")
|
||||
_S("ordmasculine")
|
||||
_S("ae")
|
||||
_S("dotlessi")
|
||||
_S("lslash")
|
||||
_S("oslash")
|
||||
_S("oe")
|
||||
_S("germandbls")
|
||||
_S("onesuperior")
|
||||
_S("logicalnot")
|
||||
_S("mu")
|
||||
_S("trademark")
|
||||
_S("Eth")
|
||||
_S("onehalf")
|
||||
_S("plusminus")
|
||||
_S("Thorn")
|
||||
_S("onequarter")
|
||||
_S("divide")
|
||||
_S("brokenbar")
|
||||
_S("degree")
|
||||
_S("thorn")
|
||||
_S("threequarters")
|
||||
_S("twosuperior")
|
||||
_S("registered")
|
||||
_S("minus")
|
||||
_S("eth")
|
||||
_S("multiply")
|
||||
_S("threesuperior")
|
||||
_S("copyright")
|
||||
_S("Aacute")
|
||||
_S("Acircumflex")
|
||||
_S("Adieresis")
|
||||
_S("Agrave")
|
||||
_S("Aring")
|
||||
_S("Atilde")
|
||||
_S("Ccedilla")
|
||||
_S("Eacute")
|
||||
_S("Ecircumflex")
|
||||
_S("Edieresis")
|
||||
_S("Egrave")
|
||||
_S("Iacute")
|
||||
_S("Icircumflex")
|
||||
_S("Idieresis")
|
||||
_S("Igrave")
|
||||
_S("Ntilde")
|
||||
_S("Oacute")
|
||||
_S("Ocircumflex")
|
||||
_S("Odieresis")
|
||||
_S("Ograve")
|
||||
_S("Otilde")
|
||||
_S("Scaron")
|
||||
_S("Uacute")
|
||||
_S("Ucircumflex")
|
||||
_S("Udieresis")
|
||||
_S("Ugrave")
|
||||
_S("Yacute")
|
||||
_S("Ydieresis")
|
||||
_S("Zcaron")
|
||||
_S("aacute")
|
||||
_S("acircumflex")
|
||||
_S("adieresis")
|
||||
_S("agrave")
|
||||
_S("aring")
|
||||
_S("atilde")
|
||||
_S("ccedilla")
|
||||
_S("eacute")
|
||||
_S("ecircumflex")
|
||||
_S("edieresis")
|
||||
_S("egrave")
|
||||
_S("iacute")
|
||||
_S("icircumflex")
|
||||
_S("idieresis")
|
||||
_S("igrave")
|
||||
_S("ntilde")
|
||||
_S("oacute")
|
||||
_S("ocircumflex")
|
||||
_S("odieresis")
|
||||
_S("ograve")
|
||||
_S("otilde")
|
||||
_S("scaron")
|
||||
_S("uacute")
|
||||
_S("ucircumflex")
|
||||
_S("udieresis")
|
||||
_S("ugrave")
|
||||
_S("yacute")
|
||||
_S("ydieresis")
|
||||
_S("zcaron")
|
||||
_S("exclamsmall")
|
||||
_S("Hungarumlautsmall")
|
||||
_S("dollaroldstyle")
|
||||
_S("dollarsuperior")
|
||||
_S("ampersandsmall")
|
||||
_S("Acutesmall")
|
||||
_S("parenleftsuperior")
|
||||
_S("parenrightsuperior")
|
||||
_S("twodotenleader")
|
||||
_S("onedotenleader")
|
||||
_S("zerooldstyle")
|
||||
_S("oneoldstyle")
|
||||
_S("twooldstyle")
|
||||
_S("threeoldstyle")
|
||||
_S("fouroldstyle")
|
||||
_S("fiveoldstyle")
|
||||
_S("sixoldstyle")
|
||||
_S("sevenoldstyle")
|
||||
_S("eightoldstyle")
|
||||
_S("nineoldstyle")
|
||||
_S("commasuperior")
|
||||
_S("threequartersemdash")
|
||||
_S("periodsuperior")
|
||||
_S("questionsmall")
|
||||
_S("asuperior")
|
||||
_S("bsuperior")
|
||||
_S("centsuperior")
|
||||
_S("dsuperior")
|
||||
_S("esuperior")
|
||||
_S("isuperior")
|
||||
_S("lsuperior")
|
||||
_S("msuperior")
|
||||
_S("nsuperior")
|
||||
_S("osuperior")
|
||||
_S("rsuperior")
|
||||
_S("ssuperior")
|
||||
_S("tsuperior")
|
||||
_S("ff")
|
||||
_S("ffi")
|
||||
_S("ffl")
|
||||
_S("parenleftinferior")
|
||||
_S("parenrightinferior")
|
||||
_S("Circumflexsmall")
|
||||
_S("hyphensuperior")
|
||||
_S("Gravesmall")
|
||||
_S("Asmall")
|
||||
_S("Bsmall")
|
||||
_S("Csmall")
|
||||
_S("Dsmall")
|
||||
_S("Esmall")
|
||||
_S("Fsmall")
|
||||
_S("Gsmall")
|
||||
_S("Hsmall")
|
||||
_S("Ismall")
|
||||
_S("Jsmall")
|
||||
_S("Ksmall")
|
||||
_S("Lsmall")
|
||||
_S("Msmall")
|
||||
_S("Nsmall")
|
||||
_S("Osmall")
|
||||
_S("Psmall")
|
||||
_S("Qsmall")
|
||||
_S("Rsmall")
|
||||
_S("Ssmall")
|
||||
_S("Tsmall")
|
||||
_S("Usmall")
|
||||
_S("Vsmall")
|
||||
_S("Wsmall")
|
||||
_S("Xsmall")
|
||||
_S("Ysmall")
|
||||
_S("Zsmall")
|
||||
_S("colonmonetary")
|
||||
_S("onefitted")
|
||||
_S("rupiah")
|
||||
_S("Tildesmall")
|
||||
_S("exclamdownsmall")
|
||||
_S("centoldstyle")
|
||||
_S("Lslashsmall")
|
||||
_S("Scaronsmall")
|
||||
_S("Zcaronsmall")
|
||||
_S("Dieresissmall")
|
||||
_S("Brevesmall")
|
||||
_S("Caronsmall")
|
||||
_S("Dotaccentsmall")
|
||||
_S("Macronsmall")
|
||||
_S("figuredash")
|
||||
_S("hypheninferior")
|
||||
_S("Ogoneksmall")
|
||||
_S("Ringsmall")
|
||||
_S("Cedillasmall")
|
||||
_S("questiondownsmall")
|
||||
_S("oneeighth")
|
||||
_S("threeeighths")
|
||||
_S("fiveeighths")
|
||||
_S("seveneighths")
|
||||
_S("onethird")
|
||||
_S("twothirds")
|
||||
_S("zerosuperior")
|
||||
_S("foursuperior")
|
||||
_S("fivesuperior")
|
||||
_S("sixsuperior")
|
||||
_S("sevensuperior")
|
||||
_S("eightsuperior")
|
||||
_S("ninesuperior")
|
||||
_S("zeroinferior")
|
||||
_S("oneinferior")
|
||||
_S("twoinferior")
|
||||
_S("threeinferior")
|
||||
_S("fourinferior")
|
||||
_S("fiveinferior")
|
||||
_S("sixinferior")
|
||||
_S("seveninferior")
|
||||
_S("eightinferior")
|
||||
_S("nineinferior")
|
||||
_S("centinferior")
|
||||
_S("dollarinferior")
|
||||
_S("periodinferior")
|
||||
_S("commainferior")
|
||||
_S("Agravesmall")
|
||||
_S("Aacutesmall")
|
||||
_S("Acircumflexsmall")
|
||||
_S("Atildesmall")
|
||||
_S("Adieresissmall")
|
||||
_S("Aringsmall")
|
||||
_S("AEsmall")
|
||||
_S("Ccedillasmall")
|
||||
_S("Egravesmall")
|
||||
_S("Eacutesmall")
|
||||
_S("Ecircumflexsmall")
|
||||
_S("Edieresissmall")
|
||||
_S("Igravesmall")
|
||||
_S("Iacutesmall")
|
||||
_S("Icircumflexsmall")
|
||||
_S("Idieresissmall")
|
||||
_S("Ethsmall")
|
||||
_S("Ntildesmall")
|
||||
_S("Ogravesmall")
|
||||
_S("Oacutesmall")
|
||||
_S("Ocircumflexsmall")
|
||||
_S("Otildesmall")
|
||||
_S("Odieresissmall")
|
||||
_S("OEsmall")
|
||||
_S("Oslashsmall")
|
||||
_S("Ugravesmall")
|
||||
_S("Uacutesmall")
|
||||
_S("Ucircumflexsmall")
|
||||
_S("Udieresissmall")
|
||||
_S("Yacutesmall")
|
||||
_S("Thornsmall")
|
||||
_S("Ydieresissmall")
|
||||
_S("001.000")
|
||||
_S("001.001")
|
||||
_S("001.002")
|
||||
_S("001.003")
|
||||
_S("Black")
|
||||
_S("Bold")
|
||||
_S("Book")
|
||||
_S("Light")
|
||||
_S("Medium")
|
||||
_S("Regular")
|
||||
_S("Roman")
|
||||
_S("Semibold")
|
||||
|
||||
#endif /* HB_OT_CFF1_STD_STR_HH */
|
|
@ -28,25 +28,11 @@
|
|||
|
||||
#ifndef HB_NO_CFF
|
||||
|
||||
#include "hb-draw.hh"
|
||||
#include "hb-algs.hh"
|
||||
#include "hb-ot-cff1-table.hh"
|
||||
#include "hb-cff1-interp-cs.hh"
|
||||
|
||||
using namespace CFF;
|
||||
|
||||
struct sid_to_gid_t
|
||||
{
|
||||
uint16_t sid;
|
||||
uint8_t gid;
|
||||
|
||||
int cmp (uint16_t a) const
|
||||
{
|
||||
if (a == sid) return 0;
|
||||
return (a < sid) ? -1 : 1;
|
||||
}
|
||||
};
|
||||
|
||||
/* SID to code */
|
||||
static const uint8_t standard_encoding_to_code [] =
|
||||
{
|
||||
|
@ -118,80 +104,6 @@ static const uint16_t expert_subset_charset_to_sid [] =
|
|||
340, 341, 342, 343, 344, 345, 346
|
||||
};
|
||||
|
||||
/* SID to glyph ID */
|
||||
static const sid_to_gid_t expert_charset_sid_to_gid [] =
|
||||
{
|
||||
{ 1, 1 }, { 13, 12 }, { 14, 13 }, { 15, 14 },
|
||||
{ 27, 26 }, { 28, 27 }, { 99, 15 }, { 109, 46 },
|
||||
{ 110, 47 }, { 150, 111 }, { 155, 101 }, { 158, 100 },
|
||||
{ 163, 102 }, { 164, 112 }, { 169, 113 }, { 229, 2 },
|
||||
{ 230, 3 }, { 231, 4 }, { 232, 5 }, { 233, 6 },
|
||||
{ 234, 7 }, { 235, 8 }, { 236, 9 }, { 237, 10 },
|
||||
{ 238, 11 }, { 239, 16 }, { 240, 17 }, { 241, 18 },
|
||||
{ 242, 19 }, { 243, 20 }, { 244, 21 }, { 245, 22 },
|
||||
{ 246, 23 }, { 247, 24 }, { 248, 25 }, { 249, 28 },
|
||||
{ 250, 29 }, { 251, 30 }, { 252, 31 }, { 253, 32 },
|
||||
{ 254, 33 }, { 255, 34 }, { 256, 35 }, { 257, 36 },
|
||||
{ 258, 37 }, { 259, 38 }, { 260, 39 }, { 261, 40 },
|
||||
{ 262, 41 }, { 263, 42 }, { 264, 43 }, { 265, 44 },
|
||||
{ 266, 45 }, { 267, 48 }, { 268, 49 }, { 269, 50 },
|
||||
{ 270, 51 }, { 271, 52 }, { 272, 53 }, { 273, 54 },
|
||||
{ 274, 55 }, { 275, 56 }, { 276, 57 }, { 277, 58 },
|
||||
{ 278, 59 }, { 279, 60 }, { 280, 61 }, { 281, 62 },
|
||||
{ 282, 63 }, { 283, 64 }, { 284, 65 }, { 285, 66 },
|
||||
{ 286, 67 }, { 287, 68 }, { 288, 69 }, { 289, 70 },
|
||||
{ 290, 71 }, { 291, 72 }, { 292, 73 }, { 293, 74 },
|
||||
{ 294, 75 }, { 295, 76 }, { 296, 77 }, { 297, 78 },
|
||||
{ 298, 79 }, { 299, 80 }, { 300, 81 }, { 301, 82 },
|
||||
{ 302, 83 }, { 303, 84 }, { 304, 85 }, { 305, 86 },
|
||||
{ 306, 87 }, { 307, 88 }, { 308, 89 }, { 309, 90 },
|
||||
{ 310, 91 }, { 311, 92 }, { 312, 93 }, { 313, 94 },
|
||||
{ 314, 95 }, { 315, 96 }, { 316, 97 }, { 317, 98 },
|
||||
{ 318, 99 }, { 319, 103 }, { 320, 104 }, { 321, 105 },
|
||||
{ 322, 106 }, { 323, 107 }, { 324, 108 }, { 325, 109 },
|
||||
{ 326, 110 }, { 327, 114 }, { 328, 115 }, { 329, 116 },
|
||||
{ 330, 117 }, { 331, 118 }, { 332, 119 }, { 333, 120 },
|
||||
{ 334, 121 }, { 335, 122 }, { 336, 123 }, { 337, 124 },
|
||||
{ 338, 125 }, { 339, 126 }, { 340, 127 }, { 341, 128 },
|
||||
{ 342, 129 }, { 343, 130 }, { 344, 131 }, { 345, 132 },
|
||||
{ 346, 133 }, { 347, 134 }, { 348, 135 }, { 349, 136 },
|
||||
{ 350, 137 }, { 351, 138 }, { 352, 139 }, { 353, 140 },
|
||||
{ 354, 141 }, { 355, 142 }, { 356, 143 }, { 357, 144 },
|
||||
{ 358, 145 }, { 359, 146 }, { 360, 147 }, { 361, 148 },
|
||||
{ 362, 149 }, { 363, 150 }, { 364, 151 }, { 365, 152 },
|
||||
{ 366, 153 }, { 367, 154 }, { 368, 155 }, { 369, 156 },
|
||||
{ 370, 157 }, { 371, 158 }, { 372, 159 }, { 373, 160 },
|
||||
{ 374, 161 }, { 375, 162 }, { 376, 163 }, { 377, 164 },
|
||||
{ 378, 165 }
|
||||
};
|
||||
|
||||
/* SID to glyph ID */
|
||||
static const sid_to_gid_t expert_subset_charset_sid_to_gid [] =
|
||||
{
|
||||
{ 1, 1 }, { 13, 8 }, { 14, 9 }, { 15, 10 },
|
||||
{ 27, 22 }, { 28, 23 }, { 99, 11 }, { 109, 41 },
|
||||
{ 110, 42 }, { 150, 64 }, { 155, 55 }, { 158, 54 },
|
||||
{ 163, 56 }, { 164, 65 }, { 169, 66 }, { 231, 2 },
|
||||
{ 232, 3 }, { 235, 4 }, { 236, 5 }, { 237, 6 },
|
||||
{ 238, 7 }, { 239, 12 }, { 240, 13 }, { 241, 14 },
|
||||
{ 242, 15 }, { 243, 16 }, { 244, 17 }, { 245, 18 },
|
||||
{ 246, 19 }, { 247, 20 }, { 248, 21 }, { 249, 24 },
|
||||
{ 250, 25 }, { 251, 26 }, { 253, 27 }, { 254, 28 },
|
||||
{ 255, 29 }, { 256, 30 }, { 257, 31 }, { 258, 32 },
|
||||
{ 259, 33 }, { 260, 34 }, { 261, 35 }, { 262, 36 },
|
||||
{ 263, 37 }, { 264, 38 }, { 265, 39 }, { 266, 40 },
|
||||
{ 267, 43 }, { 268, 44 }, { 269, 45 }, { 270, 46 },
|
||||
{ 272, 47 }, { 300, 48 }, { 301, 49 }, { 302, 50 },
|
||||
{ 305, 51 }, { 314, 52 }, { 315, 53 }, { 320, 57 },
|
||||
{ 321, 58 }, { 322, 59 }, { 323, 60 }, { 324, 61 },
|
||||
{ 325, 62 }, { 326, 63 }, { 327, 67 }, { 328, 68 },
|
||||
{ 329, 69 }, { 330, 70 }, { 331, 71 }, { 332, 72 },
|
||||
{ 333, 73 }, { 334, 74 }, { 335, 75 }, { 336, 76 },
|
||||
{ 337, 77 }, { 338, 78 }, { 339, 79 }, { 340, 80 },
|
||||
{ 341, 81 }, { 342, 82 }, { 343, 83 }, { 344, 84 },
|
||||
{ 345, 85 }, { 346, 86 }
|
||||
};
|
||||
|
||||
/* code to SID */
|
||||
static const uint8_t standard_encoding_to_sid [] =
|
||||
{
|
||||
|
@ -245,18 +157,6 @@ hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t gl
|
|||
return 0;
|
||||
}
|
||||
|
||||
hb_codepoint_t OT::cff1::lookup_expert_charset_for_glyph (hb_codepoint_t sid)
|
||||
{
|
||||
const auto *pair = hb_sorted_array (expert_charset_sid_to_gid).bsearch (sid);
|
||||
return pair ? pair->gid : 0;
|
||||
}
|
||||
|
||||
hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid)
|
||||
{
|
||||
const auto *pair = hb_sorted_array (expert_subset_charset_sid_to_gid).bsearch (sid);
|
||||
return pair ? pair->gid : 0;
|
||||
}
|
||||
|
||||
hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
|
||||
{
|
||||
if (code < ARRAY_LENGTH (standard_encoding_to_sid))
|
||||
|
@ -442,130 +342,6 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
struct cff1_path_param_t
|
||||
{
|
||||
cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
|
||||
draw_helper_t &draw_helper_, point_t *delta_)
|
||||
{
|
||||
draw_helper = &draw_helper_;
|
||||
cff = cff_;
|
||||
font = font_;
|
||||
delta = delta_;
|
||||
}
|
||||
|
||||
void move_to (const point_t &p)
|
||||
{
|
||||
point_t point = p;
|
||||
if (delta) point.move (*delta);
|
||||
draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
|
||||
}
|
||||
|
||||
void line_to (const point_t &p)
|
||||
{
|
||||
point_t point = p;
|
||||
if (delta) point.move (*delta);
|
||||
draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
|
||||
}
|
||||
|
||||
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
|
||||
{
|
||||
point_t point1 = p1, point2 = p2, point3 = p3;
|
||||
if (delta)
|
||||
{
|
||||
point1.move (*delta);
|
||||
point2.move (*delta);
|
||||
point3.move (*delta);
|
||||
}
|
||||
draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()),
|
||||
font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()),
|
||||
font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ()));
|
||||
}
|
||||
|
||||
void end_path () { draw_helper->end_path (); }
|
||||
|
||||
hb_font_t *font;
|
||||
draw_helper_t *draw_helper;
|
||||
point_t *delta;
|
||||
|
||||
const OT::cff1::accelerator_t *cff;
|
||||
};
|
||||
|
||||
struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_interp_env_t, cff1_path_param_t>
|
||||
{
|
||||
static void moveto (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt)
|
||||
{
|
||||
param.move_to (pt);
|
||||
env.moveto (pt);
|
||||
}
|
||||
|
||||
static void line (cff1_cs_interp_env_t &env, cff1_path_param_t ¶m, const point_t &pt1)
|
||||
{
|
||||
param.line_to (pt1);
|
||||
env.moveto (pt1);
|
||||
}
|
||||
|
||||
static void curve (cff1_cs_interp_env_t &env, cff1_path_param_t ¶m, const point_t &pt1, const point_t &pt2, const point_t &pt3)
|
||||
{
|
||||
param.cubic_to (pt1, pt2, pt3);
|
||||
env.moveto (pt3);
|
||||
}
|
||||
};
|
||||
|
||||
static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
|
||||
draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr);
|
||||
|
||||
struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
|
||||
{
|
||||
static void process_seac (cff1_cs_interp_env_t &env, cff1_path_param_t& param)
|
||||
{
|
||||
/* End previous path */
|
||||
param.end_path ();
|
||||
|
||||
unsigned int n = env.argStack.get_count ();
|
||||
point_t delta;
|
||||
delta.x = env.argStack[n-4];
|
||||
delta.y = env.argStack[n-3];
|
||||
hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
|
||||
hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
|
||||
|
||||
if (unlikely (!(!env.in_seac && base && accent
|
||||
&& _get_path (param.cff, param.font, base, *param.draw_helper, true)
|
||||
&& _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta))))
|
||||
env.set_error ();
|
||||
}
|
||||
};
|
||||
|
||||
bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
|
||||
draw_helper_t &draw_helper, bool in_seac, point_t *delta)
|
||||
{
|
||||
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_path_t, cff1_path_param_t> interp;
|
||||
const byte_str_t str = (*cff->charStrings)[glyph];
|
||||
interp.env.init (str, *cff, fd);
|
||||
interp.env.set_in_seac (in_seac);
|
||||
cff1_path_param_t param (cff, font, draw_helper, delta);
|
||||
if (unlikely (!interp.interpret (param))) return false;
|
||||
|
||||
/* Let's end the path specially since it is called inside seac also */
|
||||
param.end_path ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
|
||||
{
|
||||
#ifdef HB_NO_OT_FONT_CFF
|
||||
/* XXX Remove check when this code moves to .hh file. */
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return _get_path (this, font, glyph, draw_helper);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct get_seac_param_t
|
||||
{
|
||||
void init (const OT::cff1::accelerator_t *_cff)
|
||||
|
|
|
@ -27,21 +27,15 @@
|
|||
#ifndef HB_OT_CFF1_TABLE_HH
|
||||
#define HB_OT_CFF1_TABLE_HH
|
||||
|
||||
#include "hb-ot-head-table.hh"
|
||||
#include "hb-ot-cff-common.hh"
|
||||
#include "hb-subset-cff1.hh"
|
||||
#include "hb-draw.hh"
|
||||
|
||||
#define HB_STRING_ARRAY_NAME cff1_std_strings
|
||||
#define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh"
|
||||
#include "hb-string-array.hh"
|
||||
#undef HB_STRING_ARRAY_LIST
|
||||
#undef HB_STRING_ARRAY_NAME
|
||||
|
||||
namespace CFF {
|
||||
|
||||
/*
|
||||
* CFF -- Compact Font Format (CFF)
|
||||
* https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
|
||||
* http://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
|
||||
*/
|
||||
#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
|
||||
|
||||
|
@ -55,6 +49,7 @@ template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
|
|||
|
||||
typedef CFFIndex<HBUINT16> CFF1Index;
|
||||
typedef CFF1Index CFF1CharStrings;
|
||||
typedef FDArray<HBUINT16> CFF1FDArray;
|
||||
typedef Subrs<HBUINT16> CFF1Subrs;
|
||||
|
||||
struct CFF1FDSelect : FDSelect {};
|
||||
|
@ -174,7 +169,7 @@ struct Encoding
|
|||
TRACE_SERIALIZE (this);
|
||||
unsigned int size = src.get_size ();
|
||||
Encoding *dest = c->allocate_size<Encoding> (size);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
memcpy (dest, &src, size);
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -188,13 +183,13 @@ struct Encoding
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
Encoding *dest = c->extend_min (*this);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
|
||||
switch (format) {
|
||||
case 0:
|
||||
{
|
||||
Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
|
||||
if (unlikely (!fmt0)) return_trace (false);
|
||||
if (unlikely (fmt0 == nullptr)) return_trace (false);
|
||||
fmt0->nCodes () = enc_count;
|
||||
unsigned int glyph = 0;
|
||||
for (unsigned int i = 0; i < code_ranges.length; i++)
|
||||
|
@ -211,7 +206,7 @@ struct Encoding
|
|||
case 1:
|
||||
{
|
||||
Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
|
||||
if (unlikely (!fmt1)) return_trace (false);
|
||||
if (unlikely (fmt1 == nullptr)) return_trace (false);
|
||||
fmt1->nRanges () = code_ranges.length;
|
||||
for (unsigned int i = 0; i < code_ranges.length; i++)
|
||||
{
|
||||
|
@ -228,7 +223,7 @@ struct Encoding
|
|||
if (supp_codes.length)
|
||||
{
|
||||
CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
|
||||
if (unlikely (!suppData)) return_trace (false);
|
||||
if (unlikely (suppData == nullptr)) return_trace (false);
|
||||
suppData->nSups () = supp_codes.length;
|
||||
for (unsigned int i = 0; i < supp_codes.length; i++)
|
||||
{
|
||||
|
@ -240,6 +235,23 @@ struct Encoding
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
/* parallel to above: calculate the size of a subset Encoding */
|
||||
static unsigned int calculate_serialized_size (uint8_t format,
|
||||
unsigned int enc_count,
|
||||
unsigned int supp_count)
|
||||
{
|
||||
unsigned int size = min_size;
|
||||
switch (format)
|
||||
{
|
||||
case 0: size += Encoding0::min_size + HBUINT8::static_size * enc_count; break;
|
||||
case 1: size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; break;
|
||||
default:return 0;
|
||||
}
|
||||
if (supp_count > 0)
|
||||
size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned int get_size () const
|
||||
{
|
||||
unsigned int size = min_size;
|
||||
|
@ -402,7 +414,7 @@ struct Charset1_2 {
|
|||
for (unsigned int i = 0;; i++)
|
||||
{
|
||||
if (glyph >= num_glyphs)
|
||||
return 0;
|
||||
return 0;
|
||||
if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
|
||||
return glyph + (sid - ranges[i].first);
|
||||
glyph += (ranges[i].nLeft + 1);
|
||||
|
@ -445,7 +457,7 @@ struct Charset
|
|||
TRACE_SERIALIZE (this);
|
||||
unsigned int size = src.get_size (num_glyphs);
|
||||
Charset *dest = c->allocate_size<Charset> (size);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
memcpy (dest, &src, size);
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -458,14 +470,14 @@ struct Charset
|
|||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
Charset *dest = c->extend_min (*this);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
dest->format = format;
|
||||
switch (format)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
|
||||
if (unlikely (!fmt0)) return_trace (false);
|
||||
if (unlikely (fmt0 == nullptr)) return_trace (false);
|
||||
unsigned int glyph = 0;
|
||||
for (unsigned int i = 0; i < sid_ranges.length; i++)
|
||||
{
|
||||
|
@ -479,10 +491,10 @@ struct Charset
|
|||
case 1:
|
||||
{
|
||||
Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
|
||||
if (unlikely (!fmt1)) return_trace (false);
|
||||
if (unlikely (fmt1 == nullptr)) return_trace (false);
|
||||
for (unsigned int i = 0; i < sid_ranges.length; i++)
|
||||
{
|
||||
if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
|
||||
if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
|
||||
return_trace (false);
|
||||
fmt1->ranges[i].first = sid_ranges[i].code;
|
||||
fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
|
||||
|
@ -493,10 +505,10 @@ struct Charset
|
|||
case 2:
|
||||
{
|
||||
Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
|
||||
if (unlikely (!fmt2)) return_trace (false);
|
||||
if (unlikely (fmt2 == nullptr)) return_trace (false);
|
||||
for (unsigned int i = 0; i < sid_ranges.length; i++)
|
||||
{
|
||||
if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
|
||||
if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
|
||||
return_trace (false);
|
||||
fmt2->ranges[i].first = sid_ranges[i].code;
|
||||
fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
|
||||
|
@ -508,6 +520,19 @@ struct Charset
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
/* parallel to above: calculate the size of a subset Charset */
|
||||
static unsigned int calculate_serialized_size (uint8_t format,
|
||||
unsigned int count)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 0: return min_size + Charset0::min_size + HBUINT16::static_size * (count - 1);
|
||||
case 1: return min_size + Charset1::min_size + Charset1_Range::static_size * count;
|
||||
case 2: return min_size + Charset2::min_size + Charset2_Range::static_size * count;
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int get_size (unsigned int num_glyphs) const
|
||||
{
|
||||
switch (format)
|
||||
|
@ -519,9 +544,8 @@ struct Charset
|
|||
}
|
||||
}
|
||||
|
||||
hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
|
||||
hb_codepoint_t get_sid (hb_codepoint_t glyph) const
|
||||
{
|
||||
if (unlikely (glyph >= num_glyphs)) return 0;
|
||||
switch (format)
|
||||
{
|
||||
case 0: return u.format0.get_sid (glyph);
|
||||
|
@ -570,7 +594,7 @@ struct Charset
|
|||
struct CFF1StringIndex : CFF1Index
|
||||
{
|
||||
bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
|
||||
const hb_inc_bimap_t &sidmap)
|
||||
unsigned int offSize_, const hb_inc_bimap_t &sidmap)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
|
||||
|
@ -588,14 +612,30 @@ struct CFF1StringIndex : CFF1Index
|
|||
for (unsigned int i = 0; i < strings.count; i++)
|
||||
{
|
||||
hb_codepoint_t j = sidmap[i];
|
||||
if (j != HB_MAP_VALUE_INVALID)
|
||||
if (j != CFF_UNDEF_CODE)
|
||||
bytesArray[j] = strings[i];
|
||||
}
|
||||
|
||||
bool result = CFF1Index::serialize (c, bytesArray);
|
||||
bool result = CFF1Index::serialize (c, offSize_, bytesArray);
|
||||
bytesArray.fini ();
|
||||
return_trace (result);
|
||||
}
|
||||
|
||||
/* in parallel to above */
|
||||
unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_inc_bimap_t &sidmap) const
|
||||
{
|
||||
offSize_ = 0;
|
||||
if ((count == 0) || (sidmap.get_population () == 0))
|
||||
return count.static_size;
|
||||
|
||||
unsigned int dataSize = 0;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (sidmap[i] != CFF_UNDEF_CODE)
|
||||
dataSize += length_at (i);
|
||||
|
||||
offSize_ = calcOffSize(dataSize);
|
||||
return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_population (), dataSize);
|
||||
}
|
||||
};
|
||||
|
||||
struct cff1_top_dict_interp_env_t : num_interp_env_t
|
||||
|
@ -698,7 +738,7 @@ struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
|
|||
unsigned int EncodingOffset;
|
||||
unsigned int CharsetOffset;
|
||||
unsigned int FDSelectOffset;
|
||||
table_info_t privateDictInfo;
|
||||
table_info_t privateDictInfo;
|
||||
};
|
||||
|
||||
struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
|
||||
|
@ -840,10 +880,21 @@ struct cff1_private_dict_values_base_t : dict_values_t<VAL>
|
|||
{
|
||||
dict_values_t<VAL>::init ();
|
||||
subrsOffset = 0;
|
||||
localSubrs = &Null (CFF1Subrs);
|
||||
localSubrs = &Null(CFF1Subrs);
|
||||
}
|
||||
void fini () { dict_values_t<VAL>::fini (); }
|
||||
|
||||
unsigned int calculate_serialized_size () const
|
||||
{
|
||||
unsigned int size = 0;
|
||||
for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
|
||||
if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
|
||||
size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
|
||||
else
|
||||
size += dict_values_t<VAL>::get_value (i).str.length;
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned int subrsOffset;
|
||||
const CFF1Subrs *localSubrs;
|
||||
};
|
||||
|
@ -946,37 +997,6 @@ typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1
|
|||
typedef CFF1Index CFF1NameIndex;
|
||||
typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
|
||||
|
||||
struct cff1_font_dict_values_mod_t
|
||||
{
|
||||
cff1_font_dict_values_mod_t() { init (); }
|
||||
|
||||
void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
|
||||
|
||||
void init (const cff1_font_dict_values_t *base_,
|
||||
unsigned int fontName_)
|
||||
{
|
||||
base = base_;
|
||||
fontName = fontName_;
|
||||
privateDictInfo.init ();
|
||||
}
|
||||
|
||||
unsigned get_count () const { return base->get_count (); }
|
||||
|
||||
const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
|
||||
|
||||
const cff1_font_dict_values_t *base;
|
||||
table_info_t privateDictInfo;
|
||||
unsigned int fontName;
|
||||
};
|
||||
|
||||
struct CFF1FDArray : FDArray<HBUINT16>
|
||||
{
|
||||
/* FDArray::serialize() requires this partial specialization to compile */
|
||||
template <typename ITER, typename OP_SERIALIZER>
|
||||
bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
|
||||
{ return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
|
||||
};
|
||||
|
||||
} /* namespace CFF */
|
||||
|
||||
namespace OT {
|
||||
|
@ -1011,7 +1031,7 @@ struct cff1
|
|||
|
||||
const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
|
||||
|
||||
if (cff == &Null (OT::cff1))
|
||||
if (cff == &Null(OT::cff1))
|
||||
{ fini (); return; }
|
||||
|
||||
nameIndex = &cff->nameIndex (cff);
|
||||
|
@ -1032,7 +1052,7 @@ struct cff1
|
|||
}
|
||||
|
||||
if (is_predef_charset ())
|
||||
charset = &Null (Charset);
|
||||
charset = &Null(Charset);
|
||||
else
|
||||
{
|
||||
charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
|
||||
|
@ -1044,30 +1064,16 @@ struct cff1
|
|||
{
|
||||
fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
|
||||
fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
|
||||
if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
|
||||
(fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
|
||||
if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
|
||||
(fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
|
||||
{ fini (); return; }
|
||||
|
||||
fdCount = fdArray->count;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdArray = &Null (CFF1FDArray);
|
||||
fdSelect = &Null (CFF1FDSelect);
|
||||
}
|
||||
|
||||
encoding = &Null (Encoding);
|
||||
if (is_CID ())
|
||||
{
|
||||
if (unlikely (charset == &Null (Charset))) { fini (); return; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!is_predef_encoding ())
|
||||
{
|
||||
encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
|
||||
if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
|
||||
}
|
||||
fdArray = &Null(CFF1FDArray);
|
||||
fdSelect = &Null(CFF1FDSelect);
|
||||
}
|
||||
|
||||
stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
|
||||
|
@ -1080,7 +1086,7 @@ struct cff1
|
|||
|
||||
charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
|
||||
|
||||
if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
|
||||
if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
|
||||
{ fini (); return; }
|
||||
|
||||
num_glyphs = charStrings->count;
|
||||
|
@ -1098,14 +1104,14 @@ struct cff1
|
|||
{
|
||||
byte_str_t fontDictStr = (*fdArray)[i];
|
||||
if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
|
||||
cff1_font_dict_values_t *font;
|
||||
cff1_font_dict_values_t *font;
|
||||
cff1_font_dict_interpreter_t font_interp;
|
||||
font_interp.env.init (fontDictStr);
|
||||
font = fontDicts.push ();
|
||||
if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; }
|
||||
if (unlikely (font == &Crap(cff1_font_dict_values_t))) { fini (); return; }
|
||||
font->init ();
|
||||
if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
|
||||
PRIVDICTVAL *priv = &privateDicts[i];
|
||||
PRIVDICTVAL *priv = &privateDicts[i];
|
||||
const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
|
||||
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
|
||||
dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
|
||||
|
@ -1114,15 +1120,15 @@ struct cff1
|
|||
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
|
||||
|
||||
priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
|
||||
if (priv->localSubrs != &Null (CFF1Subrs) &&
|
||||
if (priv->localSubrs != &Null(CFF1Subrs) &&
|
||||
unlikely (!priv->localSubrs->sanitize (&sc)))
|
||||
{ fini (); return; }
|
||||
}
|
||||
}
|
||||
else /* non-CID */
|
||||
{
|
||||
cff1_top_dict_values_t *font = &topDict;
|
||||
PRIVDICTVAL *priv = &privateDicts[0];
|
||||
cff1_top_dict_values_t *font = &topDict;
|
||||
PRIVDICTVAL *priv = &privateDicts[0];
|
||||
|
||||
const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
|
||||
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
|
||||
|
@ -1132,7 +1138,7 @@ struct cff1
|
|||
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
|
||||
|
||||
priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
|
||||
if (priv->localSubrs != &Null (CFF1Subrs) &&
|
||||
if (priv->localSubrs != &Null(CFF1Subrs) &&
|
||||
unlikely (!priv->localSubrs->sanitize (&sc)))
|
||||
{ fini (); return; }
|
||||
}
|
||||
|
@ -1148,7 +1154,7 @@ struct cff1
|
|||
blob = nullptr;
|
||||
}
|
||||
|
||||
bool is_valid () const { return blob; }
|
||||
bool is_valid () const { return blob != nullptr; }
|
||||
bool is_CID () const { return topDict.is_CID (); }
|
||||
|
||||
bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
|
||||
|
@ -1159,18 +1165,69 @@ struct cff1
|
|||
if (unlikely (sid == CFF_UNDEF_SID))
|
||||
return 0;
|
||||
|
||||
if (charset != &Null (Charset))
|
||||
if (charset != &Null(Charset))
|
||||
return charset->get_glyph (sid, num_glyphs);
|
||||
else if ((topDict.CharsetOffset == ISOAdobeCharset)
|
||||
&& (code <= 228 /*zcaron*/)) return sid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
hb_blob_t *blob;
|
||||
hb_sanitize_context_t sc;
|
||||
|
||||
public:
|
||||
const Charset *charset;
|
||||
const CFF1NameIndex *nameIndex;
|
||||
const CFF1TopDictIndex *topDictIndex;
|
||||
const CFF1StringIndex *stringIndex;
|
||||
const CFF1Subrs *globalSubrs;
|
||||
const CFF1CharStrings *charStrings;
|
||||
const CFF1FDArray *fdArray;
|
||||
const CFF1FDSelect *fdSelect;
|
||||
unsigned int fdCount;
|
||||
|
||||
cff1_top_dict_values_t topDict;
|
||||
hb_vector_t<cff1_font_dict_values_t> fontDicts;
|
||||
hb_vector_t<PRIVDICTVAL> privateDicts;
|
||||
|
||||
unsigned int num_glyphs;
|
||||
};
|
||||
|
||||
struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
|
||||
{
|
||||
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
|
||||
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
|
||||
};
|
||||
|
||||
struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t>
|
||||
{
|
||||
void init (hb_face_t *face)
|
||||
{
|
||||
SUPER::init (face);
|
||||
if (blob == nullptr) return;
|
||||
|
||||
const OT::cff1 *cff = this->blob->as<OT::cff1> ();
|
||||
encoding = &Null(Encoding);
|
||||
if (is_CID ())
|
||||
{
|
||||
if (unlikely (charset == &Null(Charset))) { fini (); return; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!is_predef_encoding ())
|
||||
{
|
||||
encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
|
||||
if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
|
||||
|
||||
hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
|
||||
{
|
||||
if (encoding != &Null (Encoding))
|
||||
if (encoding != &Null(Encoding))
|
||||
return encoding->get_code (glyph);
|
||||
else
|
||||
{
|
||||
|
@ -1194,20 +1251,20 @@ struct cff1
|
|||
|
||||
hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
|
||||
{
|
||||
if (charset != &Null (Charset))
|
||||
return charset->get_sid (glyph, num_glyphs);
|
||||
if (charset != &Null(Charset))
|
||||
return charset->get_sid (glyph);
|
||||
else
|
||||
{
|
||||
hb_codepoint_t sid = 0;
|
||||
switch (topDict.CharsetOffset)
|
||||
{
|
||||
case ISOAdobeCharset:
|
||||
case ISOAdobeCharset:
|
||||
if (glyph <= 228 /*zcaron*/) sid = glyph;
|
||||
break;
|
||||
case ExpertCharset:
|
||||
case ExpertCharset:
|
||||
sid = lookup_expert_charset_for_sid (glyph);
|
||||
break;
|
||||
case ExpertSubsetCharset:
|
||||
case ExpertSubsetCharset:
|
||||
sid = lookup_expert_subset_charset_for_sid (glyph);
|
||||
break;
|
||||
default:
|
||||
|
@ -1217,174 +1274,35 @@ struct cff1
|
|||
}
|
||||
}
|
||||
|
||||
hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
|
||||
{
|
||||
if (charset != &Null (Charset))
|
||||
return charset->get_glyph (sid, num_glyphs);
|
||||
else
|
||||
{
|
||||
hb_codepoint_t glyph = 0;
|
||||
switch (topDict.CharsetOffset)
|
||||
{
|
||||
case ISOAdobeCharset:
|
||||
if (sid <= 228 /*zcaron*/) glyph = sid;
|
||||
break;
|
||||
case ExpertCharset:
|
||||
glyph = lookup_expert_charset_for_glyph (sid);
|
||||
break;
|
||||
case ExpertSubsetCharset:
|
||||
glyph = lookup_expert_subset_charset_for_glyph (sid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return glyph;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
hb_blob_t *blob;
|
||||
hb_sanitize_context_t sc;
|
||||
|
||||
public:
|
||||
const Encoding *encoding;
|
||||
const Charset *charset;
|
||||
const CFF1NameIndex *nameIndex;
|
||||
const CFF1TopDictIndex *topDictIndex;
|
||||
const CFF1StringIndex *stringIndex;
|
||||
const CFF1Subrs *globalSubrs;
|
||||
const CFF1CharStrings *charStrings;
|
||||
const CFF1FDArray *fdArray;
|
||||
const CFF1FDSelect *fdSelect;
|
||||
unsigned int fdCount;
|
||||
|
||||
cff1_top_dict_values_t topDict;
|
||||
hb_vector_t<cff1_font_dict_values_t>
|
||||
fontDicts;
|
||||
hb_vector_t<PRIVDICTVAL> privateDicts;
|
||||
|
||||
unsigned int num_glyphs;
|
||||
};
|
||||
|
||||
struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
|
||||
{
|
||||
void init (hb_face_t *face)
|
||||
{
|
||||
SUPER::init (face);
|
||||
|
||||
if (!is_valid ()) return;
|
||||
if (is_CID ()) return;
|
||||
|
||||
/* fill glyph_names */
|
||||
for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
|
||||
{
|
||||
hb_codepoint_t sid = glyph_to_sid (gid);
|
||||
gname_t gname;
|
||||
gname.sid = sid;
|
||||
if (sid < cff1_std_strings_length)
|
||||
gname.name = cff1_std_strings (sid);
|
||||
else
|
||||
{
|
||||
byte_str_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
|
||||
gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length);
|
||||
}
|
||||
if (unlikely (!gname.name.arrayZ)) { fini (); return; }
|
||||
glyph_names.push (gname);
|
||||
}
|
||||
glyph_names.qsort ();
|
||||
}
|
||||
|
||||
void fini ()
|
||||
{
|
||||
glyph_names.fini ();
|
||||
|
||||
SUPER::fini ();
|
||||
}
|
||||
|
||||
bool get_glyph_name (hb_codepoint_t glyph,
|
||||
char *buf, unsigned int buf_len) const
|
||||
{
|
||||
if (!buf) return true;
|
||||
if (unlikely (!is_valid ())) return false;
|
||||
if (is_CID()) return false;
|
||||
hb_codepoint_t sid = glyph_to_sid (glyph);
|
||||
const char *str;
|
||||
size_t str_len;
|
||||
if (sid < cff1_std_strings_length)
|
||||
{
|
||||
hb_bytes_t byte_str = cff1_std_strings (sid);
|
||||
str = byte_str.arrayZ;
|
||||
str_len = byte_str.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
|
||||
str = (const char *)ubyte_str.arrayZ;
|
||||
str_len = ubyte_str.length;
|
||||
}
|
||||
if (!str_len) return false;
|
||||
unsigned int len = hb_min (buf_len - 1, str_len);
|
||||
strncpy (buf, (const char*)str, len);
|
||||
buf[len] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_glyph_from_name (const char *name, int len,
|
||||
hb_codepoint_t *glyph) const
|
||||
{
|
||||
if (len < 0) len = strlen (name);
|
||||
if (unlikely (!len)) return false;
|
||||
|
||||
gname_t key = { hb_bytes_t (name, len), 0 };
|
||||
const gname_t *gname = glyph_names.bsearch (key);
|
||||
if (!gname) return false;
|
||||
hb_codepoint_t gid = sid_to_glyph (gname->sid);
|
||||
if (!gid && gname->sid) return false;
|
||||
*glyph = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
|
||||
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
|
||||
#endif
|
||||
const Encoding *encoding;
|
||||
|
||||
private:
|
||||
struct gname_t
|
||||
{
|
||||
hb_bytes_t name;
|
||||
uint16_t sid;
|
||||
|
||||
static int cmp (const void *a_, const void *b_)
|
||||
{
|
||||
const gname_t *a = (const gname_t *)a_;
|
||||
const gname_t *b = (const gname_t *)b_;
|
||||
int minlen = hb_min (a->name.length, b->name.length);
|
||||
int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
|
||||
if (ret) return ret;
|
||||
return a->name.length - b->name.length;
|
||||
}
|
||||
|
||||
int cmp (const gname_t &a) const { return cmp (&a, this); }
|
||||
};
|
||||
|
||||
hb_sorted_vector_t<gname_t> glyph_names;
|
||||
|
||||
typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
|
||||
typedef accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> SUPER;
|
||||
};
|
||||
|
||||
struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {};
|
||||
bool subset (hb_subset_plan_t *plan) const
|
||||
{
|
||||
hb_blob_t *cff_prime = nullptr;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); }
|
||||
bool success = true;
|
||||
if (hb_subset_cff1 (plan, &cff_prime)) {
|
||||
success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime);
|
||||
hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
|
||||
success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
|
||||
hb_blob_destroy (head_blob);
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
hb_blob_destroy (cff_prime);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
protected:
|
||||
HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
|
||||
HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
|
||||
HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
|
||||
HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
|
||||
HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
|
||||
HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
|
||||
HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
|
||||
|
||||
public:
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include "hb-ot-cff2-table.hh"
|
||||
#include "hb-cff2-interp-cs.hh"
|
||||
#include "hb-draw.hh"
|
||||
|
||||
using namespace CFF;
|
||||
|
||||
|
@ -143,73 +142,5 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
struct cff2_path_param_t
|
||||
{
|
||||
cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_)
|
||||
{
|
||||
draw_helper = &draw_helper_;
|
||||
font = font_;
|
||||
}
|
||||
|
||||
void move_to (const point_t &p)
|
||||
{ draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
|
||||
|
||||
void line_to (const point_t &p)
|
||||
{ draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
|
||||
|
||||
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
|
||||
{
|
||||
draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()),
|
||||
font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()),
|
||||
font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ()));
|
||||
}
|
||||
|
||||
protected:
|
||||
draw_helper_t *draw_helper;
|
||||
hb_font_t *font;
|
||||
};
|
||||
|
||||
struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t, cff2_path_param_t>
|
||||
{
|
||||
static void moveto (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt)
|
||||
{
|
||||
param.move_to (pt);
|
||||
env.moveto (pt);
|
||||
}
|
||||
|
||||
static void line (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1)
|
||||
{
|
||||
param.line_to (pt1);
|
||||
env.moveto (pt1);
|
||||
}
|
||||
|
||||
static void curve (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
|
||||
{
|
||||
param.cubic_to (pt1, pt2, pt3);
|
||||
env.moveto (pt3);
|
||||
}
|
||||
};
|
||||
|
||||
struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
|
||||
|
||||
bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
|
||||
{
|
||||
#ifdef HB_NO_OT_FONT_CFF
|
||||
/* XXX Remove check when this code moves to .hh file. */
|
||||
return true;
|
||||
#endif
|
||||
|
||||
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
|
||||
|
||||
unsigned int fd = fdSelect->get_fd (glyph);
|
||||
cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
|
||||
const byte_str_t str = (*charStrings)[glyph];
|
||||
interp.env.init (str, *this, fd, font->coords, font->num_coords);
|
||||
cff2_path_param_t param (font, draw_helper);
|
||||
if (unlikely (!interp.interpret (param))) return false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
#ifndef HB_OT_CFF2_TABLE_HH
|
||||
#define HB_OT_CFF2_TABLE_HH
|
||||
|
||||
#include "hb-ot-head-table.hh"
|
||||
#include "hb-ot-cff-common.hh"
|
||||
#include "hb-subset-cff2.hh"
|
||||
#include "hb-draw.hh"
|
||||
|
||||
namespace CFF {
|
||||
|
||||
|
@ -43,6 +43,7 @@ typedef CFFIndex<HBUINT32> CFF2Index;
|
|||
template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {};
|
||||
|
||||
typedef CFF2Index CFF2CharStrings;
|
||||
typedef FDArray<HBUINT32> CFF2FDArray;
|
||||
typedef Subrs<HBUINT32> CFF2Subrs;
|
||||
|
||||
typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
|
||||
|
@ -55,11 +56,14 @@ struct CFF2FDSelect
|
|||
TRACE_SERIALIZE (this);
|
||||
unsigned int size = src.get_size (num_glyphs);
|
||||
CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
memcpy (dest, &src, size);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
unsigned int calculate_serialized_size (unsigned int num_glyphs) const
|
||||
{ return get_size (num_glyphs); }
|
||||
|
||||
unsigned int get_size (unsigned int num_glyphs) const
|
||||
{
|
||||
switch (format)
|
||||
|
@ -123,7 +127,7 @@ struct CFF2VariationStore
|
|||
TRACE_SERIALIZE (this);
|
||||
unsigned int size_ = varStore->get_size ();
|
||||
CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
|
||||
if (unlikely (!dest)) return_trace (false);
|
||||
if (unlikely (dest == nullptr)) return_trace (false);
|
||||
memcpy (dest, varStore, size_);
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -146,6 +150,26 @@ struct cff2_top_dict_values_t : top_dict_values_t<>
|
|||
}
|
||||
void fini () { top_dict_values_t<>::fini (); }
|
||||
|
||||
unsigned int calculate_serialized_size () const
|
||||
{
|
||||
unsigned int size = 0;
|
||||
for (unsigned int i = 0; i < get_count (); i++)
|
||||
{
|
||||
op_code_t op = get_value (i).op;
|
||||
switch (op)
|
||||
{
|
||||
case OpCode_vstore:
|
||||
case OpCode_FDSelect:
|
||||
size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
|
||||
break;
|
||||
default:
|
||||
size += top_dict_values_t<>::calculate_serialized_op_size (get_value (i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned int vstoreOffset;
|
||||
unsigned int FDSelectOffset;
|
||||
};
|
||||
|
@ -232,11 +256,22 @@ struct cff2_private_dict_values_base_t : dict_values_t<VAL>
|
|||
{
|
||||
dict_values_t<VAL>::init ();
|
||||
subrsOffset = 0;
|
||||
localSubrs = &Null (CFF2Subrs);
|
||||
localSubrs = &Null(CFF2Subrs);
|
||||
ivs = 0;
|
||||
}
|
||||
void fini () { dict_values_t<VAL>::fini (); }
|
||||
|
||||
unsigned int calculate_serialized_size () const
|
||||
{
|
||||
unsigned int size = 0;
|
||||
for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
|
||||
if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
|
||||
size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
|
||||
else
|
||||
size += dict_values_t<VAL>::get_value (i).str.length;
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned int subrsOffset;
|
||||
const CFF2Subrs *localSubrs;
|
||||
unsigned int ivs;
|
||||
|
@ -369,14 +404,6 @@ struct cff2_private_dict_opset_subset_t : dict_opset_t
|
|||
typedef dict_interpreter_t<cff2_top_dict_opset_t, cff2_top_dict_values_t> cff2_top_dict_interpreter_t;
|
||||
typedef dict_interpreter_t<cff2_font_dict_opset_t, cff2_font_dict_values_t> cff2_font_dict_interpreter_t;
|
||||
|
||||
struct CFF2FDArray : FDArray<HBUINT32>
|
||||
{
|
||||
/* FDArray::serialize does not compile without this partial specialization */
|
||||
template <typename ITER, typename OP_SERIALIZER>
|
||||
bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
|
||||
{ return FDArray<HBUINT32>::serialize<cff2_font_dict_values_t, table_info_t> (c, it, opszr); }
|
||||
};
|
||||
|
||||
} /* namespace CFF */
|
||||
|
||||
namespace OT {
|
||||
|
@ -411,7 +438,7 @@ struct cff2
|
|||
|
||||
const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
|
||||
|
||||
if (cff2 == &Null (OT::cff2))
|
||||
if (cff2 == &Null(OT::cff2))
|
||||
{ fini (); return; }
|
||||
|
||||
{ /* parse top dict */
|
||||
|
@ -429,11 +456,11 @@ struct cff2
|
|||
fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset);
|
||||
fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset);
|
||||
|
||||
if (((varStore != &Null (CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
|
||||
(charStrings == &Null (CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
|
||||
(globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
|
||||
(fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
|
||||
(((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
|
||||
if (((varStore != &Null(CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
|
||||
(charStrings == &Null(CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
|
||||
(globalSubrs == &Null(CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
|
||||
(fdArray == &Null(CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
|
||||
(((fdSelect != &Null(CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
|
||||
{ fini (); return; }
|
||||
|
||||
num_glyphs = charStrings->count;
|
||||
|
@ -452,7 +479,7 @@ struct cff2
|
|||
cff2_font_dict_interpreter_t font_interp;
|
||||
font_interp.env.init (fontDictStr);
|
||||
font = fontDicts.push ();
|
||||
if (unlikely (font == &Crap (cff2_font_dict_values_t))) { fini (); return; }
|
||||
if (unlikely (font == &Crap(cff2_font_dict_values_t))) { fini (); return; }
|
||||
font->init ();
|
||||
if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
|
||||
|
||||
|
@ -464,7 +491,7 @@ struct cff2
|
|||
if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; }
|
||||
|
||||
privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset);
|
||||
if (privateDicts[i].localSubrs != &Null (CFF2Subrs) &&
|
||||
if (privateDicts[i].localSubrs != &Null(CFF2Subrs) &&
|
||||
unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
|
||||
{ fini (); return; }
|
||||
}
|
||||
|
@ -480,7 +507,7 @@ struct cff2
|
|||
blob = nullptr;
|
||||
}
|
||||
|
||||
bool is_valid () const { return blob; }
|
||||
bool is_valid () const { return blob != nullptr; }
|
||||
|
||||
protected:
|
||||
hb_blob_t *blob;
|
||||
|
@ -506,14 +533,27 @@ struct cff2
|
|||
HB_INTERNAL bool get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents) const;
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const { return hb_subset_cff2 (c); }
|
||||
bool subset (hb_subset_plan_t *plan) const
|
||||
{
|
||||
hb_blob_t *cff2_prime = nullptr;
|
||||
|
||||
bool success = true;
|
||||
if (hb_subset_cff2 (plan, &cff2_prime)) {
|
||||
success = success && plan->add_table (HB_OT_TAG_cff2, cff2_prime);
|
||||
hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
|
||||
success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
|
||||
hb_blob_destroy (head_blob);
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
hb_blob_destroy (cff2_prime);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public:
|
||||
FixedVersion<HBUINT8> version; /* Version of CFF2 table. set to 0x0200u */
|
||||
|
|
|
@ -83,16 +83,18 @@ struct CmapSubtableFormat4
|
|||
HBUINT16 *endCode = c->start_embed<HBUINT16> ();
|
||||
hb_codepoint_t prev_endcp = 0xFFFF;
|
||||
|
||||
for (const hb_item_type<Iterator> _ : +it)
|
||||
{
|
||||
if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
|
||||
{
|
||||
HBUINT16 end_code;
|
||||
end_code = prev_endcp;
|
||||
c->copy<HBUINT16> (end_code);
|
||||
}
|
||||
prev_endcp = _.first;
|
||||
}
|
||||
+ 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
|
||||
|
@ -119,17 +121,19 @@ struct CmapSubtableFormat4
|
|||
HBUINT16 *startCode = c->start_embed<HBUINT16> ();
|
||||
hb_codepoint_t prev_cp = 0xFFFF;
|
||||
|
||||
for (const hb_item_type<Iterator> _ : +it)
|
||||
{
|
||||
if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
|
||||
{
|
||||
HBUINT16 start_code;
|
||||
start_code = _.first;
|
||||
c->copy<HBUINT16> (start_code);
|
||||
}
|
||||
+ 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;
|
||||
}
|
||||
prev_cp = _.first;
|
||||
})
|
||||
;
|
||||
|
||||
// There must be a final entry with end_code == 0xFFFF.
|
||||
if (it.len () == 0 || prev_cp != 0xFFFF)
|
||||
|
@ -158,28 +162,30 @@ struct CmapSubtableFormat4
|
|||
if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size)
|
||||
return nullptr;
|
||||
|
||||
for (const hb_item_type<Iterator> _ : +it)
|
||||
{
|
||||
if (_.first == startCode[i])
|
||||
{
|
||||
use_delta = true;
|
||||
start_gid = _.second;
|
||||
}
|
||||
else if (_.second != last_gid + 1) use_delta = false;
|
||||
+ 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);
|
||||
if (_.first == endCode[i])
|
||||
{
|
||||
HBINT16 delta;
|
||||
if (use_delta) delta = (int)start_gid - (int)startCode[i];
|
||||
else delta = 0;
|
||||
c->copy<HBINT16> (delta);
|
||||
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
last_gid = _.second;
|
||||
last_cp = _.first;
|
||||
}
|
||||
last_gid = _.second;
|
||||
last_cp = _.first;
|
||||
})
|
||||
;
|
||||
|
||||
if (it.len () == 0 || last_cp != 0xFFFF)
|
||||
{
|
||||
|
@ -232,21 +238,12 @@ struct CmapSubtableFormat4
|
|||
void serialize (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{
|
||||
auto format4_iter =
|
||||
+ it
|
||||
| hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
|
||||
{ return _.first <= 0xFFFF; })
|
||||
;
|
||||
|
||||
//comment off temporarily while we're working on supporting --gids option
|
||||
//if (format4_iter.len () == 0) return;
|
||||
|
||||
unsigned table_initpos = c->length ();
|
||||
if (unlikely (!c->extend_min (*this))) return;
|
||||
this->format = 4;
|
||||
|
||||
//serialize endCode[]
|
||||
HBUINT16 *endCode = serialize_endcode_array (c, format4_iter);
|
||||
HBUINT16 *endCode = serialize_endcode_array (c, it);
|
||||
if (unlikely (!endCode)) return;
|
||||
|
||||
unsigned segcount = (c->length () - min_size) / HBUINT16::static_size;
|
||||
|
@ -255,14 +252,14 @@ struct CmapSubtableFormat4
|
|||
if (unlikely (!c->allocate_size<HBUINT16> (HBUINT16::static_size))) return; // 2 bytes of padding.
|
||||
|
||||
// serialize startCode[]
|
||||
HBUINT16 *startCode = serialize_startcode_array (c, format4_iter);
|
||||
HBUINT16 *startCode = serialize_startcode_array (c, it);
|
||||
if (unlikely (!startCode)) return;
|
||||
|
||||
//serialize idDelta[]
|
||||
HBINT16 *idDelta = serialize_idDelta_array (c, format4_iter, endCode, startCode, segcount);
|
||||
HBINT16 *idDelta = serialize_idDelta_array (c, it, endCode, startCode, segcount);
|
||||
if (unlikely (!idDelta)) return;
|
||||
|
||||
HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
|
||||
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;
|
||||
|
@ -294,28 +291,27 @@ struct CmapSubtableFormat4
|
|||
|
||||
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
|
||||
{
|
||||
struct CustomRange
|
||||
/* Custom two-array bsearch. */
|
||||
int min = 0, max = (int) this->segCount - 1;
|
||||
const HBUINT16 *startCount = this->startCount;
|
||||
const HBUINT16 *endCount = this->endCount;
|
||||
unsigned int i;
|
||||
while (min <= max)
|
||||
{
|
||||
int cmp (hb_codepoint_t k,
|
||||
unsigned distance) const
|
||||
int mid = ((unsigned int) min + (unsigned int) max) / 2;
|
||||
if (codepoint < startCount[mid])
|
||||
max = mid - 1;
|
||||
else if (codepoint > endCount[mid])
|
||||
min = mid + 1;
|
||||
else
|
||||
{
|
||||
if (k > last) return +1;
|
||||
if (k < (&last)[distance]) return -1;
|
||||
return 0;
|
||||
i = mid;
|
||||
goto found;
|
||||
}
|
||||
HBUINT16 last;
|
||||
};
|
||||
|
||||
const HBUINT16 *found =hb_bsearch (codepoint,
|
||||
this->endCount,
|
||||
this->segCount,
|
||||
2,
|
||||
_hb_cmp_method<hb_codepoint_t, CustomRange, unsigned>,
|
||||
this->segCount + 1);
|
||||
if (!found)
|
||||
return false;
|
||||
unsigned int i = found - endCount;
|
||||
}
|
||||
return false;
|
||||
|
||||
found:
|
||||
hb_codepoint_t gid;
|
||||
unsigned int rangeOffset = this->idRangeOffset[i];
|
||||
if (rangeOffset == 0)
|
||||
|
@ -337,10 +333,8 @@ struct CmapSubtableFormat4
|
|||
*glyph = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
HB_INTERNAL static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
|
||||
{ return ((const accelerator_t *) obj)->get_glyph (codepoint, glyph); }
|
||||
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
unsigned int count = this->segCount;
|
||||
|
@ -534,26 +528,20 @@ struct CmapSubtableLongSegmented
|
|||
return true;
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
for (unsigned int i = 0; i < this->groups.len; i++)
|
||||
{
|
||||
hb_codepoint_t start = this->groups[i].startCharCode;
|
||||
hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
|
||||
(hb_codepoint_t) HB_UNICODE_MAX);
|
||||
hb_codepoint_t gid = this->groups[i].glyphID;
|
||||
if (!gid)
|
||||
for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
|
||||
{
|
||||
/* Intention is: if (hb_is_same (T, CmapSubtableFormat13)) continue; */
|
||||
if (! T::group_get_glyph (this->groups[i], end)) continue;
|
||||
start++;
|
||||
gid++;
|
||||
hb_codepoint_t gid = T::group_get_glyph (this->groups[i], codepoint);
|
||||
if (unlikely (!gid))
|
||||
continue;
|
||||
out->add (codepoint);
|
||||
}
|
||||
if (unlikely ((unsigned int) gid >= num_glyphs)) continue;
|
||||
if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
|
||||
end = start + (hb_codepoint_t) num_glyphs - gid;
|
||||
|
||||
out->add_range (start, end);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -594,29 +582,33 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
|
|||
hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
|
||||
hb_codepoint_t glyphID = 0;
|
||||
|
||||
for (const hb_item_type<Iterator> _ : +it)
|
||||
{
|
||||
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);
|
||||
+ 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;
|
||||
}
|
||||
startCharCode = _.first;
|
||||
endCharCode = _.first;
|
||||
glyphID = _.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
endCharCode = _.first;
|
||||
}
|
||||
})
|
||||
;
|
||||
|
||||
CmapSubtableLongGroup record;
|
||||
record.startCharCode = startCharCode;
|
||||
|
@ -780,7 +772,7 @@ struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32>
|
|||
{
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
out->add (arrayZ[i].unicodeValue);
|
||||
out->add (arrayZ[i].glyphID);
|
||||
}
|
||||
|
||||
void closure_glyphs (const hb_set_t *unicodes,
|
||||
|
@ -847,20 +839,6 @@ struct VariationSelectorRecord
|
|||
return GLYPH_VARIANT_NOT_FOUND;
|
||||
}
|
||||
|
||||
VariationSelectorRecord(const VariationSelectorRecord& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
void operator= (const VariationSelectorRecord& other)
|
||||
{
|
||||
varSelector = other.varSelector;
|
||||
HBUINT32 offset = other.defaultUVS;
|
||||
defaultUVS = offset;
|
||||
offset = other.nonDefaultUVS;
|
||||
nonDefaultUVS = offset;
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out, const void *base) const
|
||||
{
|
||||
(base+defaultUVS).collect_unicodes (out);
|
||||
|
@ -878,43 +856,50 @@ struct VariationSelectorRecord
|
|||
nonDefaultUVS.sanitize (c, base));
|
||||
}
|
||||
|
||||
hb_pair_t<unsigned, unsigned>
|
||||
copy (hb_serialize_context_t *c,
|
||||
const hb_set_t *unicodes,
|
||||
const hb_set_t *glyphs,
|
||||
const hb_map_t *glyph_map,
|
||||
const void *base) const
|
||||
VariationSelectorRecord* copy (hb_serialize_context_t *c,
|
||||
const hb_set_t *unicodes,
|
||||
const hb_set_t *glyphs,
|
||||
const hb_map_t *glyph_map,
|
||||
const void *src_base,
|
||||
const void *dst_base) const
|
||||
{
|
||||
auto snap = c->snapshot ();
|
||||
auto *out = c->embed<VariationSelectorRecord> (*this);
|
||||
if (unlikely (!out)) return hb_pair (0, 0);
|
||||
if (unlikely (!out)) return nullptr;
|
||||
|
||||
out->defaultUVS = 0;
|
||||
out->nonDefaultUVS = 0;
|
||||
|
||||
unsigned non_default_uvs_objidx = 0;
|
||||
if (nonDefaultUVS != 0)
|
||||
{
|
||||
c->push ();
|
||||
if (c->copy (base+nonDefaultUVS, unicodes, glyphs, glyph_map))
|
||||
non_default_uvs_objidx = c->pop_pack ();
|
||||
else c->pop_discard ();
|
||||
}
|
||||
bool drop = true;
|
||||
|
||||
unsigned default_uvs_objidx = 0;
|
||||
if (defaultUVS != 0)
|
||||
{
|
||||
c->push ();
|
||||
if (c->copy (base+defaultUVS, unicodes))
|
||||
default_uvs_objidx = c->pop_pack ();
|
||||
if (c->copy (src_base+defaultUVS, unicodes))
|
||||
{
|
||||
c->add_link (out->defaultUVS, c->pop_pack (), dst_base);
|
||||
drop = false;
|
||||
}
|
||||
else c->pop_discard ();
|
||||
}
|
||||
|
||||
if (nonDefaultUVS != 0)
|
||||
{
|
||||
c->push ();
|
||||
if (c->copy (src_base+nonDefaultUVS, unicodes, glyphs, glyph_map))
|
||||
{
|
||||
c->add_link (out->nonDefaultUVS, c->pop_pack (), dst_base);
|
||||
drop = false;
|
||||
}
|
||||
else c->pop_discard ();
|
||||
}
|
||||
|
||||
if (!default_uvs_objidx && !non_default_uvs_objidx)
|
||||
if (drop)
|
||||
{
|
||||
c->revert (snap);
|
||||
|
||||
return hb_pair (default_uvs_objidx, non_default_uvs_objidx);
|
||||
return nullptr;
|
||||
}
|
||||
else return out;
|
||||
}
|
||||
|
||||
HBUINT24 varSelector; /* Variation selector. */
|
||||
|
@ -947,7 +932,7 @@ struct CmapSubtableFormat14
|
|||
const hb_set_t *unicodes,
|
||||
const hb_set_t *glyphs,
|
||||
const hb_map_t *glyph_map,
|
||||
const void *base)
|
||||
const void *src_base)
|
||||
{
|
||||
auto snap = c->snapshot ();
|
||||
unsigned table_initpos = c->length ();
|
||||
|
@ -956,67 +941,17 @@ struct CmapSubtableFormat14
|
|||
if (unlikely (!c->extend_min (*this))) return;
|
||||
this->format = 14;
|
||||
|
||||
auto src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (base);
|
||||
|
||||
/*
|
||||
* Some versions of OTS require that offsets are in order. Due to the use
|
||||
* of push()/pop_pack() serializing the variation records in order results
|
||||
* in the offsets being in reverse order (first record has the largest
|
||||
* offset). While this is perfectly valid, it will cause some versions of
|
||||
* OTS to consider this table bad.
|
||||
*
|
||||
* So to prevent this issue we serialize the variation records in reverse
|
||||
* order, so that the offsets are ordered from small to large. Since
|
||||
* variation records are supposed to be in increasing order of varSelector
|
||||
* we then have to reverse the order of the written variation selector
|
||||
* records after everything is finalized.
|
||||
*/
|
||||
hb_vector_t<hb_pair_t<unsigned, unsigned>> obj_indices;
|
||||
for (int i = src_tbl->record.len - 1; i >= 0; i--)
|
||||
{
|
||||
hb_pair_t<unsigned, unsigned> result = src_tbl->record[i].copy (c, unicodes, glyphs, glyph_map, base);
|
||||
if (result.first || result.second)
|
||||
obj_indices.push (result);
|
||||
}
|
||||
const CmapSubtableFormat14 *src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (src_base);
|
||||
for (const VariationSelectorRecord& _ : src_tbl->record)
|
||||
c->copy (_, unicodes, glyphs, glyph_map, src_base, this);
|
||||
|
||||
if (c->length () - table_initpos == CmapSubtableFormat14::min_size)
|
||||
{
|
||||
c->revert (snap);
|
||||
return;
|
||||
}
|
||||
|
||||
int tail_len = init_tail - c->tail;
|
||||
c->check_assign (this->length, c->length () - table_initpos + tail_len);
|
||||
c->check_assign (this->record.len,
|
||||
(c->length () - table_initpos - CmapSubtableFormat14::min_size) /
|
||||
VariationSelectorRecord::static_size);
|
||||
|
||||
/* Correct the incorrect write order by reversing the order of the variation
|
||||
records array. */
|
||||
_reverse_variation_records ();
|
||||
|
||||
/* Now that records are in the right order, we can set up the offsets. */
|
||||
_add_links_to_variation_records (c, obj_indices);
|
||||
}
|
||||
|
||||
void _reverse_variation_records ()
|
||||
{
|
||||
record.as_array ().reverse ();
|
||||
}
|
||||
|
||||
void _add_links_to_variation_records (hb_serialize_context_t *c,
|
||||
const hb_vector_t<hb_pair_t<unsigned, unsigned>>& obj_indices)
|
||||
{
|
||||
for (unsigned i = 0; i < obj_indices.length; i++)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Since the record array has been reversed (see comments in copy())
|
||||
* but obj_indices has not been, the indices at obj_indices[i]
|
||||
* are for the variation record at record[j].
|
||||
*/
|
||||
int j = obj_indices.length - 1 - i;
|
||||
c->add_link (record[j].defaultUVS, obj_indices[i].first);
|
||||
c->add_link (record[j].nonDefaultUVS, obj_indices[i].second);
|
||||
int tail_len = init_tail - c->tail;
|
||||
c->check_assign (this->length, c->length () - table_initpos + tail_len);
|
||||
c->check_assign (this->record.len, (c->length () - table_initpos - CmapSubtableFormat14::min_size) / VariationSelectorRecord::static_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1031,12 +966,6 @@ struct CmapSubtableFormat14
|
|||
;
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
for (const VariationSelectorRecord& _ : record)
|
||||
_.collect_unicodes (out, this);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -1072,15 +1001,15 @@ struct CmapSubtable
|
|||
default: return false;
|
||||
}
|
||||
}
|
||||
void collect_unicodes (hb_set_t *out, unsigned int num_glyphs = UINT_MAX) const
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{
|
||||
switch (u.format) {
|
||||
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;
|
||||
case 12: u.format12.collect_unicodes (out, num_glyphs); return;
|
||||
case 13: u.format13.collect_unicodes (out, num_glyphs); return;
|
||||
case 12: u.format12.collect_unicodes (out); return;
|
||||
case 13: u.format13.collect_unicodes (out); return;
|
||||
case 14:
|
||||
default: return;
|
||||
}
|
||||
|
@ -1092,12 +1021,12 @@ struct CmapSubtable
|
|||
Iterator it,
|
||||
unsigned format,
|
||||
const hb_subset_plan_t *plan,
|
||||
const void *base)
|
||||
const void *src_base)
|
||||
{
|
||||
switch (format) {
|
||||
case 4: return u.format4.serialize (c, it);
|
||||
case 12: return u.format12.serialize (c, it);
|
||||
case 14: return u.format14.serialize (c, plan->unicodes, plan->_glyphset, plan->glyph_map, base);
|
||||
case 4: u.format4.serialize (c, it); return;
|
||||
case 12: u.format12.serialize (c, it); return;
|
||||
case 14: u.format14.serialize (c, plan->unicodes, plan->_glyphset, plan->glyph_map, src_base); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
@ -1158,7 +1087,8 @@ struct EncodingRecord
|
|||
EncodingRecord* copy (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
unsigned format,
|
||||
const void *base,
|
||||
const void *src_base,
|
||||
const void *dst_base,
|
||||
const hb_subset_plan_t *plan,
|
||||
/* INOUT */ unsigned *objidx) const
|
||||
{
|
||||
|
@ -1172,7 +1102,7 @@ struct EncodingRecord
|
|||
{
|
||||
CmapSubtable *cmapsubtable = c->push<CmapSubtable> ();
|
||||
unsigned origin_length = c->length ();
|
||||
cmapsubtable->serialize (c, it, format, plan, &(base+subtable));
|
||||
cmapsubtable->serialize (c, it, format, plan, &(src_base+subtable));
|
||||
if (c->length () - origin_length > 0) *objidx = c->pop_pack ();
|
||||
else c->pop_discard ();
|
||||
}
|
||||
|
@ -1183,7 +1113,7 @@ struct EncodingRecord
|
|||
return_trace (nullptr);
|
||||
}
|
||||
|
||||
c->add_link (out->subtable, *objidx);
|
||||
c->add_link (out->subtable, *objidx, dst_base);
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
|
@ -1204,7 +1134,7 @@ struct cmap
|
|||
void serialize (hb_serialize_context_t *c,
|
||||
Iterator it,
|
||||
EncodingRecIter encodingrec_iter,
|
||||
const void *base,
|
||||
const void *src_base,
|
||||
const hb_subset_plan_t *plan)
|
||||
{
|
||||
if (unlikely (!c->extend_min ((*this)))) return;
|
||||
|
@ -1214,14 +1144,11 @@ struct cmap
|
|||
|
||||
for (const EncodingRecord& _ : encodingrec_iter)
|
||||
{
|
||||
hb_set_t unicodes_set;
|
||||
(base+_.subtable).collect_unicodes (&unicodes_set);
|
||||
unsigned format = (src_base+_.subtable).u.format;
|
||||
|
||||
unsigned format = (base+_.subtable).u.format;
|
||||
|
||||
if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
|
||||
else if (format == 12) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
|
||||
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
|
||||
if (format == 4) c->copy (_, it, 4u, src_base, this, plan, &format4objidx);
|
||||
else if (format == 12) c->copy (_, it, 12u, src_base, this, plan, &format12objidx);
|
||||
else if (format == 14) c->copy (_, it, 14u, src_base, this, plan, &format14objidx);
|
||||
}
|
||||
|
||||
c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size);
|
||||
|
@ -1260,6 +1187,7 @@ struct cmap
|
|||
})
|
||||
;
|
||||
|
||||
|
||||
if (unlikely (!encodingrec_iter.len ())) return_trace (false);
|
||||
|
||||
const EncodingRecord *unicode_bmp= nullptr, *unicode_ucs4 = nullptr, *ms_bmp = nullptr, *ms_ucs4 = nullptr;
|
||||
|
@ -1277,7 +1205,7 @@ struct cmap
|
|||
else if (_.platformID == 3 && _.encodingID == 10) ms_ucs4 = table;
|
||||
}
|
||||
|
||||
if (unlikely (!has_format12 && !unicode_bmp && !ms_bmp)) return_trace (false);
|
||||
if (unlikely (!unicode_bmp && !ms_bmp)) return_trace (false);
|
||||
if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
|
||||
|
||||
auto it =
|
||||
|
@ -1411,8 +1339,8 @@ struct cmap
|
|||
return get_nominal_glyph (unicode, glyph);
|
||||
}
|
||||
|
||||
void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
|
||||
{ subtable->collect_unicodes (out, num_glyphs); }
|
||||
void collect_unicodes (hb_set_t *out) const
|
||||
{ subtable->collect_unicodes (out); }
|
||||
void collect_variation_selectors (hb_set_t *out) const
|
||||
{ subtable_uvs->collect_variation_selectors (out); }
|
||||
void collect_variation_unicodes (hb_codepoint_t variation_selector,
|
||||
|
@ -1485,7 +1413,7 @@ struct cmap
|
|||
}
|
||||
|
||||
const EncodingRecord *find_encodingrec (unsigned int platform_id,
|
||||
unsigned int encoding_id) const
|
||||
unsigned int encoding_id) const
|
||||
{
|
||||
EncodingRecord key;
|
||||
key.platformID = platform_id;
|
||||
|
@ -1517,9 +1445,9 @@ struct cmap
|
|||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number (0). */
|
||||
HBUINT16 version; /* Table version number (0). */
|
||||
SortedArrayOf<EncodingRecord>
|
||||
encodingRecord; /* Encoding tables. */
|
||||
encodingRecord; /* Encoding tables. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, encodingRecord);
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Seigo Nonaka, Calder Kitagawa
|
||||
* Google Author(s): Seigo Nonaka
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_COLOR_CBDT_TABLE_HH
|
||||
|
@ -43,35 +43,6 @@
|
|||
|
||||
namespace OT {
|
||||
|
||||
struct cblc_bitmap_size_subset_context_t
|
||||
{
|
||||
const char *cbdt;
|
||||
unsigned int cbdt_length;
|
||||
hb_vector_t<char> *cbdt_prime;
|
||||
unsigned int size; /* INOUT
|
||||
* Input: old size of IndexSubtable
|
||||
* Output: new size of IndexSubtable
|
||||
*/
|
||||
unsigned int num_tables; /* INOUT
|
||||
* Input: old number of subtables.
|
||||
* Output: new number of subtables.
|
||||
*/
|
||||
hb_codepoint_t start_glyph; /* OUT */
|
||||
hb_codepoint_t end_glyph; /* OUT */
|
||||
};
|
||||
|
||||
static inline bool
|
||||
_copy_data_to_cbdt (hb_vector_t<char> *cbdt_prime,
|
||||
const void *data,
|
||||
unsigned length)
|
||||
{
|
||||
unsigned int new_len = cbdt_prime->length + length;
|
||||
if (unlikely (!cbdt_prime->alloc (new_len))) return false;
|
||||
memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length);
|
||||
cbdt_prime->length = new_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct SmallGlyphMetrics
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -85,7 +56,7 @@ struct SmallGlyphMetrics
|
|||
extents->x_bearing = font->em_scale_x (bearingX);
|
||||
extents->y_bearing = font->em_scale_y (bearingY);
|
||||
extents->width = font->em_scale_x (width);
|
||||
extents->height = font->em_scale_y (-static_cast<int>(height));
|
||||
extents->height = font->em_scale_y (-height);
|
||||
}
|
||||
|
||||
HBUINT8 height;
|
||||
|
@ -94,7 +65,7 @@ struct SmallGlyphMetrics
|
|||
HBINT8 bearingY;
|
||||
HBUINT8 advance;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (5);
|
||||
DEFINE_SIZE_STATIC(5);
|
||||
};
|
||||
|
||||
struct BigGlyphMetrics : SmallGlyphMetrics
|
||||
|
@ -103,7 +74,7 @@ struct BigGlyphMetrics : SmallGlyphMetrics
|
|||
HBINT8 vertBearingY;
|
||||
HBUINT8 vertAdvance;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
DEFINE_SIZE_STATIC(8);
|
||||
};
|
||||
|
||||
struct SBitLineMetrics
|
||||
|
@ -127,7 +98,7 @@ struct SBitLineMetrics
|
|||
HBINT8 padding1;
|
||||
HBINT8 padding2;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
DEFINE_SIZE_STATIC(12);
|
||||
};
|
||||
|
||||
|
||||
|
@ -147,7 +118,7 @@ struct IndexSubtableHeader
|
|||
HBUINT16 imageFormat;
|
||||
HBUINT32 imageDataOffset;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
DEFINE_SIZE_STATIC(8);
|
||||
};
|
||||
|
||||
template <typename OffsetType>
|
||||
|
@ -172,23 +143,11 @@ struct IndexSubtableFormat1Or3
|
|||
return true;
|
||||
}
|
||||
|
||||
bool add_offset (hb_serialize_context_t *c,
|
||||
unsigned int offset,
|
||||
unsigned int *size /* OUT (accumulated) */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
Offset<OffsetType> embedded_offset;
|
||||
embedded_offset = offset;
|
||||
*size += sizeof (OffsetType);
|
||||
auto *o = c->embed (embedded_offset);
|
||||
return_trace ((bool) o);
|
||||
}
|
||||
|
||||
IndexSubtableHeader header;
|
||||
UnsizedArrayOf<Offset<OffsetType>>
|
||||
offsetArrayZ;
|
||||
offsetArrayZ;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, offsetArrayZ);
|
||||
DEFINE_SIZE_ARRAY(8, offsetArrayZ);
|
||||
};
|
||||
|
||||
struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<HBUINT32> {};
|
||||
|
@ -200,153 +159,35 @@ struct IndexSubtable
|
|||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.header.sanitize (c)) return_trace (false);
|
||||
switch (u.header.indexFormat)
|
||||
{
|
||||
switch (u.header.indexFormat) {
|
||||
case 1: return_trace (u.format1.sanitize (c, glyph_count));
|
||||
case 3: return_trace (u.format3.sanitize (c, glyph_count));
|
||||
default:return_trace (true);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
finish_subtable (hb_serialize_context_t *c,
|
||||
unsigned int cbdt_prime_len,
|
||||
unsigned int num_glyphs,
|
||||
unsigned int *size /* OUT (accumulated) */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
unsigned int local_offset = cbdt_prime_len - u.header.imageDataOffset;
|
||||
switch (u.header.indexFormat)
|
||||
{
|
||||
case 1: return_trace (u.format1.add_offset (c, local_offset, size));
|
||||
case 3: {
|
||||
if (!u.format3.add_offset (c, local_offset, size))
|
||||
return_trace (false);
|
||||
if (!(num_glyphs & 0x01)) // Pad to 32-bit alignment if needed.
|
||||
return_trace (u.format3.add_offset (c, 0, size));
|
||||
return_trace (true);
|
||||
}
|
||||
// TODO: implement 2, 4, 5.
|
||||
case 2: case 4: // No-op.
|
||||
case 5: // Pad to 32-bit aligned.
|
||||
default: return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
fill_missing_glyphs (hb_serialize_context_t *c,
|
||||
unsigned int cbdt_prime_len,
|
||||
unsigned int num_missing,
|
||||
unsigned int *size /* OUT (accumulated) */,
|
||||
unsigned int *num_glyphs /* OUT (accumulated) */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
unsigned int local_offset = cbdt_prime_len - u.header.imageDataOffset;
|
||||
switch (u.header.indexFormat)
|
||||
{
|
||||
case 1: {
|
||||
for (unsigned int i = 0; i < num_missing; i++)
|
||||
{
|
||||
if (unlikely (!u.format1.add_offset (c, local_offset, size)))
|
||||
return_trace (false);
|
||||
*num_glyphs += 1;
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
case 3: {
|
||||
for (unsigned int i = 0; i < num_missing; i++)
|
||||
{
|
||||
if (unlikely (!u.format3.add_offset (c, local_offset, size)))
|
||||
return_trace (false);
|
||||
*num_glyphs += 1;
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
// TODO: implement 2, 4, 5.
|
||||
case 2: // Add empty space in cbdt_prime?.
|
||||
case 4: case 5: // No-op as sparse is supported.
|
||||
default: return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
copy_glyph_at_idx (hb_serialize_context_t *c, unsigned int idx,
|
||||
const char *cbdt, unsigned int cbdt_length,
|
||||
hb_vector_t<char> *cbdt_prime /* INOUT */,
|
||||
IndexSubtable *subtable_prime /* INOUT */,
|
||||
unsigned int *size /* OUT (accumulated) */) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
unsigned int offset, length, format;
|
||||
if (unlikely (!get_image_data (idx, &offset, &length, &format))) return_trace (false);
|
||||
if (unlikely (offset > cbdt_length || cbdt_length - offset < length)) return_trace (false);
|
||||
|
||||
auto *header_prime = subtable_prime->get_header ();
|
||||
unsigned int new_local_offset = cbdt_prime->length - (unsigned int) header_prime->imageDataOffset;
|
||||
if (unlikely (!_copy_data_to_cbdt (cbdt_prime, cbdt + offset, length))) return_trace (false);
|
||||
|
||||
return_trace (subtable_prime->add_offset (c, new_local_offset, size));
|
||||
}
|
||||
|
||||
bool
|
||||
add_offset (hb_serialize_context_t *c, unsigned int local_offset,
|
||||
unsigned int *size /* OUT (accumulated) */)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
switch (u.header.indexFormat)
|
||||
{
|
||||
case 1: return_trace (u.format1.add_offset (c, local_offset, size));
|
||||
case 3: return_trace (u.format3.add_offset (c, local_offset, size));
|
||||
// TODO: Implement tables 2, 4, 5
|
||||
case 2: // Should be a no-op.
|
||||
case 4: case 5: // Handle sparse cases.
|
||||
default: return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const
|
||||
{
|
||||
switch (u.header.indexFormat)
|
||||
{
|
||||
switch (u.header.indexFormat) {
|
||||
case 2: case 5: /* TODO */
|
||||
case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */
|
||||
default:return (false);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
get_image_data (unsigned int idx, unsigned int *offset,
|
||||
unsigned int *length, unsigned int *format) const
|
||||
bool get_image_data (unsigned int idx,
|
||||
unsigned int *offset,
|
||||
unsigned int *length,
|
||||
unsigned int *format) const
|
||||
{
|
||||
*format = u.header.imageFormat;
|
||||
switch (u.header.indexFormat)
|
||||
{
|
||||
switch (u.header.indexFormat) {
|
||||
case 1: return u.format1.get_image_data (idx, offset, length);
|
||||
case 3: return u.format3.get_image_data (idx, offset, length);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
const IndexSubtableHeader* get_header () const { return &u.header; }
|
||||
|
||||
void populate_header (unsigned index_format,
|
||||
unsigned image_format,
|
||||
unsigned int image_data_offset,
|
||||
unsigned int *size)
|
||||
{
|
||||
u.header.indexFormat = index_format;
|
||||
u.header.imageFormat = image_format;
|
||||
u.header.imageDataOffset = image_data_offset;
|
||||
switch (u.header.indexFormat)
|
||||
{
|
||||
case 1: *size += IndexSubtableFormat1::min_size; break;
|
||||
case 3: *size += IndexSubtableFormat3::min_size; break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
union {
|
||||
IndexSubtableHeader header;
|
||||
|
@ -368,133 +209,12 @@ struct IndexSubtableRecord
|
|||
offsetToSubtable.sanitize (c, base, lastGlyphIndex - firstGlyphIndex + 1));
|
||||
}
|
||||
|
||||
const IndexSubtable* get_subtable (const void *base) const
|
||||
bool get_extents (hb_glyph_extents_t *extents,
|
||||
const void *base) const
|
||||
{
|
||||
return &(base+offsetToSubtable);
|
||||
return (base+offsetToSubtable).get_extents (extents);
|
||||
}
|
||||
|
||||
bool add_new_subtable (hb_subset_context_t* c,
|
||||
cblc_bitmap_size_subset_context_t *bitmap_size_context,
|
||||
IndexSubtableRecord *record,
|
||||
const hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> *lookup, /* IN */
|
||||
const void *base,
|
||||
unsigned int *start /* INOUT */) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
auto *subtable = c->serializer->start_embed<IndexSubtable> ();
|
||||
if (unlikely (!subtable)) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend_min (subtable))) return_trace (false);
|
||||
|
||||
auto *old_subtable = get_subtable (base);
|
||||
auto *old_header = old_subtable->get_header ();
|
||||
|
||||
subtable->populate_header (old_header->indexFormat,
|
||||
old_header->imageFormat,
|
||||
bitmap_size_context->cbdt_prime->length,
|
||||
&bitmap_size_context->size);
|
||||
|
||||
unsigned int num_glyphs = 0;
|
||||
bool early_exit = false;
|
||||
for (unsigned int i = *start; i < lookup->length; i++)
|
||||
{
|
||||
hb_codepoint_t new_gid = (*lookup)[i].first;
|
||||
const IndexSubtableRecord *next_record = (*lookup)[i].second;
|
||||
const IndexSubtable *next_subtable = next_record->get_subtable (base);
|
||||
auto *next_header = next_subtable->get_header ();
|
||||
if (next_header != old_header)
|
||||
{
|
||||
*start = i;
|
||||
early_exit = true;
|
||||
break;
|
||||
}
|
||||
unsigned int num_missing = record->add_glyph_for_subset (new_gid);
|
||||
if (unlikely (!subtable->fill_missing_glyphs (c->serializer,
|
||||
bitmap_size_context->cbdt_prime->length,
|
||||
num_missing,
|
||||
&bitmap_size_context->size,
|
||||
&num_glyphs)))
|
||||
return_trace (false);
|
||||
|
||||
hb_codepoint_t old_gid = 0;
|
||||
c->plan->old_gid_for_new_gid (new_gid, &old_gid);
|
||||
if (old_gid < next_record->firstGlyphIndex)
|
||||
return_trace (false);
|
||||
|
||||
unsigned int old_idx = (unsigned int) old_gid - next_record->firstGlyphIndex;
|
||||
if (unlikely (!next_subtable->copy_glyph_at_idx (c->serializer,
|
||||
old_idx,
|
||||
bitmap_size_context->cbdt,
|
||||
bitmap_size_context->cbdt_length,
|
||||
bitmap_size_context->cbdt_prime,
|
||||
subtable,
|
||||
&bitmap_size_context->size)))
|
||||
return_trace (false);
|
||||
num_glyphs += 1;
|
||||
}
|
||||
if (!early_exit)
|
||||
*start = lookup->length;
|
||||
if (unlikely (!subtable->finish_subtable (c->serializer,
|
||||
bitmap_size_context->cbdt_prime->length,
|
||||
num_glyphs,
|
||||
&bitmap_size_context->size)))
|
||||
return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool add_new_record (hb_subset_context_t *c,
|
||||
cblc_bitmap_size_subset_context_t *bitmap_size_context,
|
||||
const hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> *lookup, /* IN */
|
||||
const void *base,
|
||||
unsigned int *start, /* INOUT */
|
||||
hb_vector_t<IndexSubtableRecord>* records /* INOUT */) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
unsigned int old_size = bitmap_size_context->size;
|
||||
unsigned int old_cbdt_prime_length = bitmap_size_context->cbdt_prime->length;
|
||||
|
||||
// Set to invalid state to indicate filling glyphs is not yet started.
|
||||
records->resize (records->length + 1);
|
||||
(*records)[records->length - 1].firstGlyphIndex = 1;
|
||||
(*records)[records->length - 1].lastGlyphIndex = 0;
|
||||
bitmap_size_context->size += IndexSubtableRecord::min_size;
|
||||
|
||||
c->serializer->push ();
|
||||
|
||||
if (unlikely (!add_new_subtable (c, bitmap_size_context, &((*records)[records->length - 1]), lookup, base, start)))
|
||||
{
|
||||
c->serializer->pop_discard ();
|
||||
c->serializer->revert (snap);
|
||||
bitmap_size_context->cbdt_prime->shrink (old_cbdt_prime_length);
|
||||
bitmap_size_context->size = old_size;
|
||||
records->resize (records->length - 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
bitmap_size_context->num_tables += 1;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
unsigned int add_glyph_for_subset (hb_codepoint_t gid)
|
||||
{
|
||||
if (firstGlyphIndex > lastGlyphIndex)
|
||||
{
|
||||
firstGlyphIndex = gid;
|
||||
lastGlyphIndex = gid;
|
||||
return 0;
|
||||
}
|
||||
// TODO maybe assert? this shouldn't occur.
|
||||
if (lastGlyphIndex > gid)
|
||||
return 0;
|
||||
unsigned int num_missing = (unsigned int) (gid - lastGlyphIndex - 1);
|
||||
lastGlyphIndex = gid;
|
||||
return num_missing;
|
||||
}
|
||||
|
||||
bool get_extents (hb_glyph_extents_t *extents, const void *base) const
|
||||
{ return (base+offsetToSubtable).get_extents (extents); }
|
||||
|
||||
bool get_image_data (unsigned int gid,
|
||||
const void *base,
|
||||
unsigned int *offset,
|
||||
|
@ -510,7 +230,7 @@ struct IndexSubtableRecord
|
|||
HBGlyphID lastGlyphIndex;
|
||||
LOffsetTo<IndexSubtable> offsetToSubtable;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
DEFINE_SIZE_STATIC(8);
|
||||
};
|
||||
|
||||
struct IndexSubtableArray
|
||||
|
@ -523,77 +243,6 @@ struct IndexSubtableArray
|
|||
return_trace (indexSubtablesZ.sanitize (c, count, this));
|
||||
}
|
||||
|
||||
void
|
||||
build_lookup (hb_subset_context_t *c, cblc_bitmap_size_subset_context_t *bitmap_size_context,
|
||||
hb_vector_t<hb_pair_t<hb_codepoint_t,
|
||||
const IndexSubtableRecord*>> *lookup /* OUT */) const
|
||||
{
|
||||
bool start_glyph_is_set = false;
|
||||
for (hb_codepoint_t new_gid = 0; new_gid < c->plan->num_output_glyphs (); new_gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid;
|
||||
if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) continue;
|
||||
|
||||
const IndexSubtableRecord* record = find_table (old_gid, bitmap_size_context->num_tables);
|
||||
if (unlikely (!record)) continue;
|
||||
|
||||
// Don't add gaps to the lookup. The best way to determine if a glyph is a
|
||||
// gap is that it has no image data.
|
||||
unsigned int offset, length, format;
|
||||
if (unlikely (!record->get_image_data (old_gid, this, &offset, &length, &format))) continue;
|
||||
|
||||
lookup->push (hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*> (new_gid, record));
|
||||
|
||||
if (!start_glyph_is_set)
|
||||
{
|
||||
bitmap_size_context->start_glyph = new_gid;
|
||||
start_glyph_is_set = true;
|
||||
}
|
||||
|
||||
bitmap_size_context->end_glyph = new_gid;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
subset (hb_subset_context_t *c,
|
||||
cblc_bitmap_size_subset_context_t *bitmap_size_context) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
auto *dst = c->serializer->start_embed<IndexSubtableArray> ();
|
||||
if (unlikely (!dst)) return_trace (false);
|
||||
|
||||
hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> lookup;
|
||||
build_lookup (c, bitmap_size_context, &lookup);
|
||||
|
||||
bitmap_size_context->size = 0;
|
||||
bitmap_size_context->num_tables = 0;
|
||||
hb_vector_t<IndexSubtableRecord> records;
|
||||
for (unsigned int start = 0; start < lookup.length;)
|
||||
{
|
||||
if (unlikely (!lookup[start].second->add_new_record (c, bitmap_size_context, &lookup, this, &start, &records)))
|
||||
{
|
||||
// Discard any leftover pushes to the serializer from successful records.
|
||||
for (unsigned int i = 0; i < records.length; i++)
|
||||
c->serializer->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Workaround to ensure offset ordering is from least to greatest when
|
||||
* resolving links. */
|
||||
hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
|
||||
for (unsigned int i = 0; i < records.length; i++)
|
||||
objidxs.push (c->serializer->pop_pack ());
|
||||
for (unsigned int i = 0; i < records.length; i++)
|
||||
{
|
||||
IndexSubtableRecord* record = c->serializer->embed (records[i]);
|
||||
if (unlikely (!record)) return_trace (false);
|
||||
c->serializer->add_link (record->offsetToSubtable, objidxs[records.length - 1 - i]);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
public:
|
||||
const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
|
||||
{
|
||||
|
@ -625,48 +274,14 @@ struct BitmapSizeTable
|
|||
vertical.sanitize (c));
|
||||
}
|
||||
|
||||
const IndexSubtableRecord *
|
||||
find_table (hb_codepoint_t glyph, const void *base, const void **out_base) const
|
||||
const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
|
||||
const void *base,
|
||||
const void **out_base) const
|
||||
{
|
||||
*out_base = &(base+indexSubtableArrayOffset);
|
||||
return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
|
||||
}
|
||||
|
||||
bool
|
||||
subset (hb_subset_context_t *c, const void *base,
|
||||
const char *cbdt, unsigned int cbdt_length,
|
||||
hb_vector_t<char> *cbdt_prime /* INOUT */) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out_table = c->serializer->embed (this);
|
||||
if (unlikely (!out_table)) return_trace (false);
|
||||
|
||||
cblc_bitmap_size_subset_context_t bitmap_size_context;
|
||||
bitmap_size_context.cbdt = cbdt;
|
||||
bitmap_size_context.cbdt_length = cbdt_length;
|
||||
bitmap_size_context.cbdt_prime = cbdt_prime;
|
||||
bitmap_size_context.size = indexTablesSize;
|
||||
bitmap_size_context.num_tables = numberOfIndexSubtables;
|
||||
bitmap_size_context.start_glyph = 1;
|
||||
bitmap_size_context.end_glyph = 0;
|
||||
|
||||
if (!out_table->indexSubtableArrayOffset.serialize_subset (c,
|
||||
indexSubtableArrayOffset,
|
||||
base,
|
||||
&bitmap_size_context))
|
||||
return_trace (false);
|
||||
if (!bitmap_size_context.size ||
|
||||
!bitmap_size_context.num_tables ||
|
||||
bitmap_size_context.start_glyph > bitmap_size_context.end_glyph)
|
||||
return_trace (false);
|
||||
|
||||
out_table->indexTablesSize = bitmap_size_context.size;
|
||||
out_table->numberOfIndexSubtables = bitmap_size_context.num_tables;
|
||||
out_table->startGlyphIndex = bitmap_size_context.start_glyph;
|
||||
out_table->endGlyphIndex = bitmap_size_context.end_glyph;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
protected:
|
||||
LNNOffsetTo<IndexSubtableArray>
|
||||
indexSubtableArrayOffset;
|
||||
|
@ -682,7 +297,7 @@ struct BitmapSizeTable
|
|||
HBUINT8 bitDepth;
|
||||
HBINT8 flags;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (48);
|
||||
DEFINE_SIZE_STATIC(48);
|
||||
};
|
||||
|
||||
|
||||
|
@ -695,7 +310,7 @@ struct GlyphBitmapDataFormat17
|
|||
SmallGlyphMetrics glyphMetrics;
|
||||
LArrayOf<HBUINT8> data;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (9, data);
|
||||
DEFINE_SIZE_ARRAY(9, data);
|
||||
};
|
||||
|
||||
struct GlyphBitmapDataFormat18
|
||||
|
@ -703,14 +318,14 @@ struct GlyphBitmapDataFormat18
|
|||
BigGlyphMetrics glyphMetrics;
|
||||
LArrayOf<HBUINT8> data;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (12, data);
|
||||
DEFINE_SIZE_ARRAY(12, data);
|
||||
};
|
||||
|
||||
struct GlyphBitmapDataFormat19
|
||||
{
|
||||
LArrayOf<HBUINT8> data;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, data);
|
||||
DEFINE_SIZE_ARRAY(4, data);
|
||||
};
|
||||
|
||||
struct CBLC
|
||||
|
@ -727,50 +342,12 @@ struct CBLC
|
|||
sizeTables.sanitize (c, this));
|
||||
}
|
||||
|
||||
static bool
|
||||
sink_cbdt (hb_subset_context_t *c, hb_vector_t<char>* cbdt_prime)
|
||||
{
|
||||
hb_blob_t *cbdt_prime_blob = hb_blob_create (cbdt_prime->arrayZ,
|
||||
cbdt_prime->length,
|
||||
HB_MEMORY_MODE_WRITABLE,
|
||||
cbdt_prime->arrayZ,
|
||||
free);
|
||||
cbdt_prime->init (); // Leak arrayZ to the blob.
|
||||
bool ret = c->plan->add_table (HB_OT_TAG_CBDT, cbdt_prime_blob);
|
||||
hb_blob_destroy (cbdt_prime_blob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
subset_size_table (hb_subset_context_t *c, const BitmapSizeTable& table,
|
||||
const char *cbdt /* IN */, unsigned int cbdt_length,
|
||||
CBLC *cblc_prime /* INOUT */, hb_vector_t<char> *cbdt_prime /* INOUT */) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
cblc_prime->sizeTables.len++;
|
||||
|
||||
auto snap = c->serializer->snapshot ();
|
||||
auto cbdt_prime_len = cbdt_prime->length;
|
||||
|
||||
if (!table.subset (c, this, cbdt, cbdt_length, cbdt_prime))
|
||||
{
|
||||
cblc_prime->sizeTables.len--;
|
||||
c->serializer->revert (snap);
|
||||
cbdt_prime->shrink (cbdt_prime_len);
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
// Implemented in cc file as it depends on definition of CBDT.
|
||||
HB_INTERNAL bool subset (hb_subset_context_t *c) const;
|
||||
|
||||
protected:
|
||||
const BitmapSizeTable &choose_strike (hb_font_t *font) const
|
||||
{
|
||||
unsigned count = sizeTables.len;
|
||||
if (unlikely (!count))
|
||||
return Null (BitmapSizeTable);
|
||||
return Null(BitmapSizeTable);
|
||||
|
||||
unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
|
||||
if (!requested_ppem)
|
||||
|
@ -796,7 +373,7 @@ struct CBLC
|
|||
FixedVersion<> version;
|
||||
LArrayOf<BitmapSizeTable> sizeTables;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, sizeTables);
|
||||
DEFINE_SIZE_ARRAY(8, sizeTables);
|
||||
};
|
||||
|
||||
struct CBDT
|
||||
|
@ -807,8 +384,8 @@ struct CBDT
|
|||
{
|
||||
void init (hb_face_t *face)
|
||||
{
|
||||
cblc = hb_sanitize_context_t ().reference_table<CBLC> (face);
|
||||
cbdt = hb_sanitize_context_t ().reference_table<CBDT> (face);
|
||||
cblc = hb_sanitize_context_t().reference_table<CBLC> (face);
|
||||
cbdt = hb_sanitize_context_t().reference_table<CBDT> (face);
|
||||
|
||||
upem = hb_face_get_upem (face);
|
||||
}
|
||||
|
@ -819,8 +396,8 @@ struct CBDT
|
|||
this->cbdt.destroy ();
|
||||
}
|
||||
|
||||
bool
|
||||
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
|
||||
bool get_extents (hb_font_t *font, hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
const void *base;
|
||||
const BitmapSizeTable &strike = this->cblc->choose_strike (font);
|
||||
|
@ -835,27 +412,33 @@ struct CBDT
|
|||
if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
|
||||
return false;
|
||||
|
||||
unsigned int cbdt_len = cbdt.get_length ();
|
||||
if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
|
||||
return false;
|
||||
|
||||
switch (image_format)
|
||||
{
|
||||
case 17: {
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
|
||||
unsigned int cbdt_len = cbdt.get_length ();
|
||||
if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
|
||||
return false;
|
||||
auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
|
||||
glyphFormat17.glyphMetrics.get_extents (font, extents);
|
||||
break;
|
||||
}
|
||||
case 18: {
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
|
||||
return false;
|
||||
auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
|
||||
glyphFormat18.glyphMetrics.get_extents (font, extents);
|
||||
break;
|
||||
}
|
||||
default: return false; /* TODO: Support other image formats. */
|
||||
|
||||
switch (image_format)
|
||||
{
|
||||
case 17: {
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
|
||||
return false;
|
||||
const GlyphBitmapDataFormat17& glyphFormat17 =
|
||||
StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
|
||||
glyphFormat17.glyphMetrics.get_extents (font, extents);
|
||||
break;
|
||||
}
|
||||
case 18: {
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
|
||||
return false;
|
||||
const GlyphBitmapDataFormat18& glyphFormat18 =
|
||||
StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
|
||||
glyphFormat18.glyphMetrics.get_extents (font, extents);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// TODO: Support other image formats.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert to font units. */
|
||||
|
@ -869,8 +452,8 @@ struct CBDT
|
|||
return true;
|
||||
}
|
||||
|
||||
hb_blob_t*
|
||||
reference_png (hb_font_t *font, hb_codepoint_t glyph) const
|
||||
hb_blob_t* reference_png (hb_font_t *font,
|
||||
hb_codepoint_t glyph) const
|
||||
{
|
||||
const void *base;
|
||||
const BitmapSizeTable &strike = this->cblc->choose_strike (font);
|
||||
|
@ -882,41 +465,44 @@ struct CBDT
|
|||
if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
unsigned int cbdt_len = cbdt.get_length ();
|
||||
if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
|
||||
return hb_blob_get_empty ();
|
||||
{
|
||||
unsigned int cbdt_len = cbdt.get_length ();
|
||||
if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
switch (image_format)
|
||||
{
|
||||
case 17:
|
||||
{
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
|
||||
return hb_blob_get_empty ();
|
||||
auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
|
||||
return hb_blob_create_sub_blob (cbdt.get_blob (),
|
||||
image_offset + GlyphBitmapDataFormat17::min_size,
|
||||
glyphFormat17.data.len);
|
||||
}
|
||||
case 18:
|
||||
{
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
|
||||
return hb_blob_get_empty ();
|
||||
auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
|
||||
return hb_blob_create_sub_blob (cbdt.get_blob (),
|
||||
image_offset + GlyphBitmapDataFormat18::min_size,
|
||||
glyphFormat18.data.len);
|
||||
}
|
||||
case 19:
|
||||
{
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat19::min_size))
|
||||
return hb_blob_get_empty ();
|
||||
auto &glyphFormat19 = StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
|
||||
return hb_blob_create_sub_blob (cbdt.get_blob (),
|
||||
image_offset + GlyphBitmapDataFormat19::min_size,
|
||||
glyphFormat19.data.len);
|
||||
}
|
||||
default: return hb_blob_get_empty (); /* TODO: Support other image formats. */
|
||||
switch (image_format)
|
||||
{
|
||||
case 17: {
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
|
||||
return hb_blob_get_empty ();
|
||||
const GlyphBitmapDataFormat17& glyphFormat17 =
|
||||
StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
|
||||
return hb_blob_create_sub_blob (cbdt.get_blob (),
|
||||
image_offset + GlyphBitmapDataFormat17::min_size,
|
||||
glyphFormat17.data.len);
|
||||
}
|
||||
case 18: {
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
|
||||
return hb_blob_get_empty ();
|
||||
const GlyphBitmapDataFormat18& glyphFormat18 =
|
||||
StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
|
||||
return hb_blob_create_sub_blob (cbdt.get_blob (),
|
||||
image_offset + GlyphBitmapDataFormat18::min_size,
|
||||
glyphFormat18.data.len);
|
||||
}
|
||||
case 19: {
|
||||
if (unlikely (image_length < GlyphBitmapDataFormat19::min_size))
|
||||
return hb_blob_get_empty ();
|
||||
const GlyphBitmapDataFormat19& glyphFormat19 =
|
||||
StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
|
||||
return hb_blob_create_sub_blob (cbdt.get_blob (),
|
||||
image_offset + GlyphBitmapDataFormat19::min_size,
|
||||
glyphFormat19.data.len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
bool has_data () const { return cbdt.get_length (); }
|
||||
|
@ -939,41 +525,9 @@ struct CBDT
|
|||
FixedVersion<> version;
|
||||
UnsizedArrayOf<HBUINT8> dataZ;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, dataZ);
|
||||
DEFINE_SIZE_ARRAY(4, dataZ);
|
||||
};
|
||||
|
||||
inline bool
|
||||
CBLC::subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
auto *cblc_prime = c->serializer->start_embed<CBLC> ();
|
||||
|
||||
// Use a vector as a secondary buffer as the tables need to be built in parallel.
|
||||
hb_vector_t<char> cbdt_prime;
|
||||
|
||||
if (unlikely (!cblc_prime)) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend_min (cblc_prime))) return_trace (false);
|
||||
cblc_prime->version = version;
|
||||
|
||||
hb_blob_t* cbdt_blob = hb_sanitize_context_t ().reference_table<CBDT> (c->plan->source);
|
||||
unsigned int cbdt_length;
|
||||
CBDT* cbdt = (CBDT *) hb_blob_get_data (cbdt_blob, &cbdt_length);
|
||||
if (unlikely (cbdt_length < CBDT::min_size))
|
||||
{
|
||||
hb_blob_destroy (cbdt_blob);
|
||||
return_trace (false);
|
||||
}
|
||||
_copy_data_to_cbdt (&cbdt_prime, cbdt, CBDT::min_size);
|
||||
|
||||
for (const BitmapSizeTable& table : + sizeTables.iter ())
|
||||
subset_size_table (c, table, (const char *) cbdt, cbdt_length, cblc_prime, &cbdt_prime);
|
||||
|
||||
hb_blob_destroy (cbdt_blob);
|
||||
|
||||
return_trace (CBLC::sink_cbdt (c, &cbdt_prime));
|
||||
}
|
||||
|
||||
struct CBDT_accelerator_t : CBDT::accelerator_t {};
|
||||
|
||||
} /* namespace OT */
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
* Copyright © 2020 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -21,8 +20,6 @@
|
|||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Calder Kitagawa
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_COLOR_COLR_TABLE_HH
|
||||
|
@ -50,7 +47,7 @@ struct LayerRecord
|
|||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
public:
|
||||
protected:
|
||||
HBGlyphID glyphId; /* Glyph ID of layer glyph */
|
||||
Index colorIdx; /* Index value to use with a
|
||||
* selected color palette.
|
||||
|
@ -115,38 +112,6 @@ struct COLR
|
|||
return glyph_layers.length;
|
||||
}
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
accelerator_t () {}
|
||||
~accelerator_t () { fini (); }
|
||||
|
||||
void init (hb_face_t *face)
|
||||
{ colr = hb_sanitize_context_t ().reference_table<COLR> (face); }
|
||||
|
||||
void fini () { this->colr.destroy (); }
|
||||
|
||||
bool is_valid () { return colr.get_blob ()->length; }
|
||||
|
||||
void closure_glyphs (hb_codepoint_t glyph,
|
||||
hb_set_t *related_ids /* OUT */) const
|
||||
{ colr->closure_glyphs (glyph, related_ids); }
|
||||
|
||||
private:
|
||||
hb_blob_ptr_t<COLR> colr;
|
||||
};
|
||||
|
||||
void closure_glyphs (hb_codepoint_t glyph,
|
||||
hb_set_t *related_ids /* OUT */) const
|
||||
{
|
||||
const BaseGlyphRecord *record = get_base_glyph_record (glyph);
|
||||
if (!record) return;
|
||||
|
||||
auto glyph_layers = (this+layersZ).as_array (numLayers).sub_array (record->firstLayerIdx,
|
||||
record->numLayers);
|
||||
if (!glyph_layers.length) return;
|
||||
related_ids->add_array (&glyph_layers[0].glyphId, glyph_layers.length, LayerRecord::min_size);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -155,111 +120,6 @@ struct COLR
|
|||
(this+layersZ).sanitize (c, numLayers)));
|
||||
}
|
||||
|
||||
template<typename BaseIterator, typename LayerIterator,
|
||||
hb_requires (hb_is_iterator (BaseIterator)),
|
||||
hb_requires (hb_is_iterator (LayerIterator))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
unsigned version,
|
||||
BaseIterator base_it,
|
||||
LayerIterator layer_it)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (base_it.len () != layer_it.len ()))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
this->version = version;
|
||||
numLayers = 0;
|
||||
numBaseGlyphs = base_it.len ();
|
||||
baseGlyphsZ = COLR::min_size;
|
||||
layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size;
|
||||
|
||||
for (const hb_item_type<BaseIterator>& _ : + base_it.iter ())
|
||||
{
|
||||
auto* record = c->embed (_);
|
||||
if (unlikely (!record)) return_trace (false);
|
||||
record->firstLayerIdx = numLayers;
|
||||
numLayers += record->numLayers;
|
||||
}
|
||||
|
||||
for (const hb_item_type<LayerIterator>& _ : + layer_it.iter ())
|
||||
_.as_array ().copy (c);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
const BaseGlyphRecord* get_base_glyph_record (hb_codepoint_t gid) const
|
||||
{
|
||||
if ((unsigned int) gid == 0) // Ignore notdef.
|
||||
return nullptr;
|
||||
const BaseGlyphRecord* record = &(this+baseGlyphsZ).bsearch (numBaseGlyphs, (unsigned int) gid);
|
||||
if ((record && (hb_codepoint_t) record->glyphId != gid))
|
||||
record = nullptr;
|
||||
return record;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
|
||||
|
||||
auto base_it =
|
||||
+ hb_range (c->plan->num_output_glyphs ())
|
||||
| hb_map_retains_sorting ([&](hb_codepoint_t new_gid)
|
||||
{
|
||||
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
|
||||
|
||||
const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid);
|
||||
if (unlikely (!old_record))
|
||||
return hb_pair_t<bool, BaseGlyphRecord> (false, Null (BaseGlyphRecord));
|
||||
|
||||
BaseGlyphRecord new_record;
|
||||
new_record.glyphId = new_gid;
|
||||
new_record.numLayers = old_record->numLayers;
|
||||
return hb_pair_t<bool, BaseGlyphRecord> (true, new_record);
|
||||
})
|
||||
| hb_filter (hb_first)
|
||||
| hb_map_retains_sorting (hb_second)
|
||||
;
|
||||
|
||||
auto layer_it =
|
||||
+ hb_range (c->plan->num_output_glyphs ())
|
||||
| hb_map (reverse_glyph_map)
|
||||
| hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
|
||||
{
|
||||
const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid);
|
||||
hb_vector_t<LayerRecord> out_layers;
|
||||
|
||||
if (unlikely (!old_record ||
|
||||
old_record->firstLayerIdx >= numLayers ||
|
||||
old_record->firstLayerIdx + old_record->numLayers > numLayers))
|
||||
return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
|
||||
|
||||
auto layers = (this+layersZ).as_array (numLayers).sub_array (old_record->firstLayerIdx,
|
||||
old_record->numLayers);
|
||||
out_layers.resize (layers.length);
|
||||
for (unsigned int i = 0; i < layers.length; i++) {
|
||||
out_layers[i] = layers[i];
|
||||
hb_codepoint_t new_gid = 0;
|
||||
if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid)))
|
||||
return hb_pair_t<bool, hb_vector_t<LayerRecord>> (false, out_layers);
|
||||
out_layers[i].glyphId = new_gid;
|
||||
}
|
||||
|
||||
return hb_pair_t<bool, hb_vector_t<LayerRecord>> (true, out_layers);
|
||||
})
|
||||
| hb_filter (hb_first)
|
||||
| hb_map_retains_sorting (hb_second)
|
||||
;
|
||||
|
||||
if (unlikely (!base_it || !layer_it || base_it.len () != layer_it.len ()))
|
||||
return_trace (false);
|
||||
|
||||
COLR *colr_prime = c->serializer->start_embed<COLR> ();
|
||||
return_trace (colr_prime->serialize (c->serializer, version, base_it, layer_it));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number (starts at 0). */
|
||||
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */
|
||||
|
|
|
@ -155,7 +155,7 @@ struct CPAL
|
|||
private:
|
||||
const CPALV1Tail& v1 () const
|
||||
{
|
||||
if (version == 0) return Null (CPALV1Tail);
|
||||
if (version == 0) return Null(CPALV1Tail);
|
||||
return StructAfter<CPALV1Tail> (*this);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
* Copyright © 2020 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -21,15 +20,12 @@
|
|||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Calder Kitagawa
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_COLOR_SBIX_TABLE_HH
|
||||
#define HB_OT_COLOR_SBIX_TABLE_HH
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-layout-common.hh"
|
||||
|
||||
/*
|
||||
* sbix -- Standard Bitmap Graphics
|
||||
|
@ -44,20 +40,6 @@ namespace OT {
|
|||
|
||||
struct SBIXGlyph
|
||||
{
|
||||
SBIXGlyph* copy (hb_serialize_context_t *c, unsigned int data_length) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
SBIXGlyph* new_glyph = c->start_embed<SBIXGlyph> ();
|
||||
if (unlikely (!new_glyph)) return_trace (nullptr);
|
||||
if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr);
|
||||
|
||||
new_glyph->xOffset = xOffset;
|
||||
new_glyph->yOffset = yOffset;
|
||||
new_glyph->graphicType = graphicType;
|
||||
data.copy (c, data_length);
|
||||
return_trace (new_glyph);
|
||||
}
|
||||
|
||||
HBINT16 xOffset; /* The horizontal (x-axis) offset from the left
|
||||
* edge of the graphic to the glyph’s origin.
|
||||
* That is, the x-coordinate of the point on the
|
||||
|
@ -80,9 +62,6 @@ struct SBIXGlyph
|
|||
|
||||
struct SBIXStrike
|
||||
{
|
||||
static unsigned int get_size (unsigned num_glyphs)
|
||||
{ return min_size + num_glyphs * HBUINT32::static_size; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -137,49 +116,6 @@ struct SBIXStrike
|
|||
return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c, unsigned int available_len) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
unsigned int num_output_glyphs = c->plan->num_output_glyphs ();
|
||||
|
||||
auto* out = c->serializer->start_embed<SBIXStrike> ();
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (unlikely (!c->serializer->extend (*out, num_output_glyphs + 1))) return_trace (false);
|
||||
out->ppem = ppem;
|
||||
out->resolution = resolution;
|
||||
HBUINT32 head;
|
||||
head = get_size (num_output_glyphs + 1);
|
||||
|
||||
bool has_glyphs = false;
|
||||
for (unsigned new_gid = 0; new_gid < num_output_glyphs; new_gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid;
|
||||
if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid) ||
|
||||
unlikely (imageOffsetsZ[old_gid].is_null () ||
|
||||
imageOffsetsZ[old_gid + 1].is_null () ||
|
||||
imageOffsetsZ[old_gid + 1] <= imageOffsetsZ[old_gid] ||
|
||||
imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid] <= SBIXGlyph::min_size) ||
|
||||
(unsigned int) imageOffsetsZ[old_gid + 1] > available_len)
|
||||
{
|
||||
out->imageOffsetsZ[new_gid] = head;
|
||||
continue;
|
||||
}
|
||||
has_glyphs = true;
|
||||
unsigned int delta = imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid];
|
||||
unsigned int glyph_data_length = delta - SBIXGlyph::min_size;
|
||||
if (!(this+imageOffsetsZ[old_gid]).copy (c->serializer, glyph_data_length))
|
||||
return_trace (false);
|
||||
out->imageOffsetsZ[new_gid] = head;
|
||||
head += delta;
|
||||
}
|
||||
if (has_glyphs)
|
||||
out->imageOffsetsZ[num_output_glyphs] = head;
|
||||
else
|
||||
c->serializer->revert (snap);
|
||||
return_trace (has_glyphs);
|
||||
}
|
||||
|
||||
public:
|
||||
HBUINT16 ppem; /* The PPEM size for which this strike was designed. */
|
||||
HBUINT16 resolution; /* The device pixel density (in PPI) for which this
|
||||
|
@ -204,7 +140,7 @@ struct sbix
|
|||
{
|
||||
void init (hb_face_t *face)
|
||||
{
|
||||
table = hb_sanitize_context_t ().reference_table<sbix> (face);
|
||||
table = hb_sanitize_context_t().reference_table<sbix> (face);
|
||||
num_glyphs = face->get_num_glyphs ();
|
||||
}
|
||||
void fini () { table.destroy (); }
|
||||
|
@ -237,7 +173,7 @@ struct sbix
|
|||
{
|
||||
unsigned count = table->strikes.len;
|
||||
if (unlikely (!count))
|
||||
return Null (SBIXStrike);
|
||||
return Null(SBIXStrike);
|
||||
|
||||
unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
|
||||
if (!requested_ppem)
|
||||
|
@ -301,7 +237,7 @@ struct sbix
|
|||
extents->x_bearing = x_offset;
|
||||
extents->y_bearing = png.IHDR.height + y_offset;
|
||||
extents->width = png.IHDR.width;
|
||||
extents->height = -1 * png.IHDR.height;
|
||||
extents->height = -png.IHDR.height;
|
||||
|
||||
/* Convert to font units. */
|
||||
if (strike_ppem)
|
||||
|
@ -339,63 +275,6 @@ struct sbix
|
|||
strikes.sanitize (c, this)));
|
||||
}
|
||||
|
||||
bool
|
||||
add_strike (hb_subset_context_t *c, unsigned i) const
|
||||
{
|
||||
if (strikes[i].is_null () || c->source_blob->length < (unsigned) strikes[i])
|
||||
return false;
|
||||
|
||||
return (this+strikes[i]).subset (c, c->source_blob->length - (unsigned) strikes[i]);
|
||||
}
|
||||
|
||||
bool serialize_strike_offsets (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
auto *out = c->serializer->start_embed<LOffsetLArrayOf<SBIXStrike>> ();
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
hb_vector_t<LOffsetTo<SBIXStrike>*> new_strikes;
|
||||
hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
|
||||
for (int i = strikes.len - 1; i >= 0; --i)
|
||||
{
|
||||
auto* o = out->serialize_append (c->serializer);
|
||||
if (unlikely (!o)) return_trace (false);
|
||||
*o = 0;
|
||||
auto snap = c->serializer->snapshot ();
|
||||
c->serializer->push ();
|
||||
bool ret = add_strike (c, i);
|
||||
if (!ret)
|
||||
{
|
||||
c->serializer->pop_discard ();
|
||||
out->pop ();
|
||||
c->serializer->revert (snap);
|
||||
}
|
||||
else
|
||||
{
|
||||
objidxs.push (c->serializer->pop_pack ());
|
||||
new_strikes.push (o);
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < new_strikes.length; ++i)
|
||||
c->serializer->add_link (*new_strikes[i], objidxs[new_strikes.length - 1 - i]);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t* c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
sbix *sbix_prime = c->serializer->start_embed<sbix> ();
|
||||
if (unlikely (!sbix_prime)) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (this->version))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (this->flags))) return_trace (false);
|
||||
|
||||
return_trace (serialize_strike_offsets (c));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number — set to 1 */
|
||||
HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines.
|
||||
|
|
|
@ -80,7 +80,7 @@ struct SVG
|
|||
struct accelerator_t
|
||||
{
|
||||
void init (hb_face_t *face)
|
||||
{ table = hb_sanitize_context_t ().reference_table<SVG> (face); }
|
||||
{ table = hb_sanitize_context_t().reference_table<SVG> (face); }
|
||||
void fini () { table.destroy (); }
|
||||
|
||||
hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
|
||||
|
|
|
@ -183,21 +183,22 @@ hb_ot_get_glyph_extents (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
|
||||
bool ret = false;
|
||||
|
||||
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
|
||||
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
|
||||
if (!ret) ret = ot_face->sbix->get_extents (font, glyph, extents);
|
||||
#endif
|
||||
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
|
||||
if (!ret) ret = ot_face->glyf->get_extents (font, glyph, extents);
|
||||
#ifndef HB_NO_OT_FONT_CFF
|
||||
if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
|
||||
if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
|
||||
if (!ret) ret = ot_face->cff1->get_extents (font, glyph, extents);
|
||||
if (!ret) ret = ot_face->cff2->get_extents (font, glyph, extents);
|
||||
#endif
|
||||
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
|
||||
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
|
||||
if (!ret) ret = ot_face->CBDT->get_extents (font, glyph, extents);
|
||||
#endif
|
||||
|
||||
// TODO Hook up side-bearings variations.
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
|
||||
|
@ -209,11 +210,7 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
|
||||
if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
|
||||
#ifndef HB_NO_OT_FONT_CFF
|
||||
if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
|
||||
#endif
|
||||
return false;
|
||||
return ot_face->post->get_glyph_name (glyph, name, size);
|
||||
}
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
||||
|
@ -223,11 +220,7 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
|
||||
if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
|
||||
#ifndef HB_NO_OT_FONT_CFF
|
||||
if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
|
||||
#endif
|
||||
return false;
|
||||
return ot_face->post->get_glyph_from_name (name, len, glyph);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ struct GaspRange
|
|||
}
|
||||
|
||||
public:
|
||||
HBUINT16 rangeMaxPPEM; /* Upper limit of range, in PPEM */
|
||||
HBUINT16 rangeGaspBehavior;
|
||||
HBUINT16 rangeMaxPPEM; /* Upper limit of range, in PPEM */
|
||||
HBUINT16 rangeGaspBehavior;
|
||||
/* Flags describing desired rasterizer behavior. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
#include "hb-ot-head-table.hh"
|
||||
#include "hb-ot-hmtx-table.hh"
|
||||
#include "hb-ot-var-gvar-table.hh"
|
||||
#include "hb-draw.hh"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
@ -147,19 +148,7 @@ struct glyf
|
|||
const hb_subset_plan_t *plan)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
unsigned init_len = c->length ();
|
||||
for (const auto &_ : it) _.serialize (c, plan);
|
||||
|
||||
/* As a special case when all glyph in the font are empty, add a zero byte
|
||||
* to the table, so that OTS doesn’t reject it, and to make the table work
|
||||
* on Windows as well.
|
||||
* See https://github.com/khaledhosny/ots/issues/52 */
|
||||
if (init_len == c->length ())
|
||||
{
|
||||
HBUINT8 empty_byte;
|
||||
empty_byte = 0;
|
||||
c->copy (empty_byte);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
@ -240,18 +229,18 @@ struct glyf
|
|||
{
|
||||
enum composite_glyph_flag_t
|
||||
{
|
||||
ARG_1_AND_2_ARE_WORDS = 0x0001,
|
||||
ARGS_ARE_XY_VALUES = 0x0002,
|
||||
ROUND_XY_TO_GRID = 0x0004,
|
||||
WE_HAVE_A_SCALE = 0x0008,
|
||||
MORE_COMPONENTS = 0x0020,
|
||||
WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
|
||||
WE_HAVE_A_TWO_BY_TWO = 0x0080,
|
||||
WE_HAVE_INSTRUCTIONS = 0x0100,
|
||||
USE_MY_METRICS = 0x0200,
|
||||
OVERLAP_COMPOUND = 0x0400,
|
||||
SCALED_COMPONENT_OFFSET = 0x0800,
|
||||
UNSCALED_COMPONENT_OFFSET = 0x1000
|
||||
ARG_1_AND_2_ARE_WORDS = 0x0001,
|
||||
ARGS_ARE_XY_VALUES = 0x0002,
|
||||
ROUND_XY_TO_GRID = 0x0004,
|
||||
WE_HAVE_A_SCALE = 0x0008,
|
||||
MORE_COMPONENTS = 0x0020,
|
||||
WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
|
||||
WE_HAVE_A_TWO_BY_TWO = 0x0080,
|
||||
WE_HAVE_INSTRUCTIONS = 0x0100,
|
||||
USE_MY_METRICS = 0x0200,
|
||||
OVERLAP_COMPOUND = 0x0400,
|
||||
SCALED_COMPONENT_OFFSET = 0x0800,
|
||||
UNSCALED_COMPONENT_OFFSET = 0x1000
|
||||
};
|
||||
|
||||
unsigned int get_size () const
|
||||
|
@ -372,7 +361,7 @@ struct glyf
|
|||
typedef const CompositeGlyphChain *__item_t__;
|
||||
composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
|
||||
glyph (glyph_), current (current_)
|
||||
{ if (!check_range (current)) current = nullptr; }
|
||||
{ if (!in_range (current)) current = nullptr; }
|
||||
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr) {}
|
||||
|
||||
const CompositeGlyphChain &__item__ () const { return *current; }
|
||||
|
@ -383,16 +372,16 @@ struct glyf
|
|||
|
||||
const CompositeGlyphChain *possible = &StructAfter<CompositeGlyphChain,
|
||||
CompositeGlyphChain> (*current);
|
||||
if (!check_range (possible)) { current = nullptr; return; }
|
||||
if (!in_range (possible)) { current = nullptr; return; }
|
||||
current = possible;
|
||||
}
|
||||
bool operator != (const composite_iter_t& o) const
|
||||
{ return glyph != o.glyph || current != o.current; }
|
||||
|
||||
bool check_range (const CompositeGlyphChain *composite) const
|
||||
bool in_range (const CompositeGlyphChain *composite) const
|
||||
{
|
||||
return glyph.check_range (composite, CompositeGlyphChain::min_size)
|
||||
&& glyph.check_range (composite, composite->get_size ());
|
||||
return glyph.in_range (composite, CompositeGlyphChain::min_size)
|
||||
&& glyph.in_range (composite, composite->get_size ());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -400,29 +389,8 @@ struct glyf
|
|||
__item_t__ current;
|
||||
};
|
||||
|
||||
enum phantom_point_index_t
|
||||
{
|
||||
PHANTOM_LEFT = 0,
|
||||
PHANTOM_RIGHT = 1,
|
||||
PHANTOM_TOP = 2,
|
||||
PHANTOM_BOTTOM = 3,
|
||||
PHANTOM_COUNT = 4
|
||||
};
|
||||
|
||||
struct Glyph
|
||||
{
|
||||
enum simple_glyph_flag_t
|
||||
{
|
||||
FLAG_ON_CURVE = 0x01,
|
||||
FLAG_X_SHORT = 0x02,
|
||||
FLAG_Y_SHORT = 0x04,
|
||||
FLAG_REPEAT = 0x08,
|
||||
FLAG_X_SAME = 0x10,
|
||||
FLAG_Y_SAME = 0x20,
|
||||
FLAG_RESERVED1 = 0x40,
|
||||
FLAG_RESERVED2 = 0x80
|
||||
};
|
||||
|
||||
private:
|
||||
struct GlyphHeader
|
||||
{
|
||||
|
@ -477,6 +445,18 @@ struct glyf
|
|||
return instructionLength;
|
||||
}
|
||||
|
||||
enum simple_glyph_flag_t
|
||||
{
|
||||
FLAG_ON_CURVE = 0x01,
|
||||
FLAG_X_SHORT = 0x02,
|
||||
FLAG_Y_SHORT = 0x04,
|
||||
FLAG_REPEAT = 0x08,
|
||||
FLAG_X_SAME = 0x10,
|
||||
FLAG_Y_SAME = 0x20,
|
||||
FLAG_RESERVED1 = 0x40,
|
||||
FLAG_RESERVED2 = 0x80
|
||||
};
|
||||
|
||||
const Glyph trim_padding () const
|
||||
{
|
||||
/* based on FontTools _g_l_y_f.py::trim */
|
||||
|
@ -490,6 +470,7 @@ struct glyf
|
|||
unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
|
||||
|
||||
glyph += 2 + num_instructions;
|
||||
if (unlikely (glyph + 2 >= glyph_end)) return Glyph ();
|
||||
|
||||
unsigned int coord_bytes = 0;
|
||||
unsigned int coords_with_flags = 0;
|
||||
|
@ -538,53 +519,70 @@ struct glyf
|
|||
dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
|
||||
}
|
||||
|
||||
struct x_setter_t
|
||||
{
|
||||
void set (contour_point_t &point, float v) const { point.x = v; }
|
||||
bool is_short (uint8_t flag) const { return flag & FLAG_X_SHORT; }
|
||||
bool is_same (uint8_t flag) const { return flag & FLAG_X_SAME; }
|
||||
};
|
||||
|
||||
struct y_setter_t
|
||||
{
|
||||
void set (contour_point_t &point, float v) const { point.y = v; }
|
||||
bool is_short (uint8_t flag) const { return flag & FLAG_Y_SHORT; }
|
||||
bool is_same (uint8_t flag) const { return flag & FLAG_Y_SAME; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static bool read_points (const HBUINT8 *&p /* IN/OUT */,
|
||||
contour_point_vector_t &points_ /* IN/OUT */,
|
||||
const hb_bytes_t &bytes,
|
||||
void (* setter) (contour_point_t &_, float v),
|
||||
const simple_glyph_flag_t short_flag,
|
||||
const simple_glyph_flag_t same_flag)
|
||||
const hb_bytes_t &bytes)
|
||||
{
|
||||
T coord_setter;
|
||||
float v = 0;
|
||||
for (unsigned i = 0; i < points_.length; i++)
|
||||
for (unsigned int i = 0; i < points_.length - PHANTOM_COUNT; i++)
|
||||
{
|
||||
uint8_t flag = points_[i].flag;
|
||||
if (flag & short_flag)
|
||||
if (coord_setter.is_short (flag))
|
||||
{
|
||||
if (unlikely (!bytes.check_range (p))) return false;
|
||||
if (flag & same_flag)
|
||||
if (unlikely (!bytes.in_range (p))) return false;
|
||||
if (coord_setter.is_same (flag))
|
||||
v += *p++;
|
||||
else
|
||||
v -= *p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(flag & same_flag))
|
||||
if (!coord_setter.is_same (flag))
|
||||
{
|
||||
if (unlikely (!bytes.check_range ((const HBUINT16 *) p))) return false;
|
||||
if (unlikely (!bytes.in_range ((const HBUINT16 *) p))) return false;
|
||||
v += *(const HBINT16 *) p;
|
||||
p += HBINT16::static_size;
|
||||
}
|
||||
}
|
||||
setter (points_[i], v);
|
||||
coord_setter.set (points_[i], v);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
|
||||
bool phantom_only = false) const
|
||||
hb_vector_t<unsigned int> &end_points_ /* OUT */,
|
||||
const bool phantom_only=false) const
|
||||
{
|
||||
const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
|
||||
int num_contours = header.numberOfContours;
|
||||
if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
|
||||
if (unlikely (!bytes.in_range (&endPtsOfContours[num_contours + 1]))) return false;
|
||||
unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
|
||||
|
||||
points_.resize (num_points);
|
||||
points_.resize (num_points + PHANTOM_COUNT);
|
||||
for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
|
||||
if (phantom_only) return true;
|
||||
|
||||
/* Read simple glyph points if !phantom_only */
|
||||
end_points_.resize (num_contours);
|
||||
|
||||
for (int i = 0; i < num_contours; i++)
|
||||
points_[endPtsOfContours[i]].is_end_point = true;
|
||||
end_points_[i] = endPtsOfContours[i];
|
||||
|
||||
/* Skip instructions */
|
||||
const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
|
||||
|
@ -593,12 +591,12 @@ struct glyf
|
|||
/* Read flags */
|
||||
for (unsigned int i = 0; i < num_points; i++)
|
||||
{
|
||||
if (unlikely (!bytes.check_range (p))) return false;
|
||||
if (unlikely (!bytes.in_range (p))) return false;
|
||||
uint8_t flag = *p++;
|
||||
points_[i].flag = flag;
|
||||
if (flag & FLAG_REPEAT)
|
||||
{
|
||||
if (unlikely (!bytes.check_range (p))) return false;
|
||||
if (unlikely (!bytes.in_range (p))) return false;
|
||||
unsigned int repeat_count = *p++;
|
||||
while ((repeat_count-- > 0) && (++i < num_points))
|
||||
points_[i].flag = flag;
|
||||
|
@ -606,10 +604,8 @@ struct glyf
|
|||
}
|
||||
|
||||
/* Read x & y coordinates */
|
||||
return (read_points (p, points_, bytes,
|
||||
[] (contour_point_t &p, float v) { p.x = v; }, FLAG_X_SHORT, FLAG_X_SAME) &&
|
||||
read_points (p, points_, bytes,
|
||||
[] (contour_point_t &p, float v) { p.y = v; }, FLAG_Y_SHORT, FLAG_Y_SAME));
|
||||
return (read_points<x_setter_t> (p, points_, bytes) &&
|
||||
read_points<y_setter_t> (p, points_, bytes));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -652,10 +648,30 @@ struct glyf
|
|||
/* Chop instructions off the end */
|
||||
void drop_hints_bytes (hb_bytes_t &dest_start) const
|
||||
{ dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
|
||||
|
||||
bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
|
||||
hb_vector_t<unsigned int> &end_points_ /* OUT */,
|
||||
const bool phantom_only=false) const
|
||||
{
|
||||
/* add one pseudo point for each component in composite glyph */
|
||||
unsigned int num_points = hb_len (get_iterator ());
|
||||
points_.resize (num_points + PHANTOM_COUNT);
|
||||
for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
|
||||
|
||||
enum phantom_point_index_t
|
||||
{
|
||||
PHANTOM_LEFT = 0,
|
||||
PHANTOM_RIGHT = 1,
|
||||
PHANTOM_TOP = 2,
|
||||
PHANTOM_BOTTOM = 3,
|
||||
PHANTOM_COUNT = 4
|
||||
};
|
||||
|
||||
public:
|
||||
composite_iter_t get_composite_iterator () const
|
||||
{
|
||||
|
@ -690,130 +706,39 @@ struct glyf
|
|||
}
|
||||
}
|
||||
|
||||
/* Note: Recursively calls itself.
|
||||
* all_points includes phantom points
|
||||
/* for a simple glyph, return contour end points, flags, along with coordinate points
|
||||
* for a composite glyph, return pseudo component points
|
||||
* in both cases points trailed with four phantom points
|
||||
*/
|
||||
template<typename T>
|
||||
bool get_points (T glyph_for_gid, hb_font_t *font,
|
||||
contour_point_vector_t &all_points /* OUT */,
|
||||
bool phantom_only = false,
|
||||
unsigned int depth = 0) const
|
||||
bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
|
||||
hb_vector_t<unsigned int> &end_points_ /* OUT */,
|
||||
const bool phantom_only=false) const
|
||||
{
|
||||
if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
|
||||
contour_point_vector_t points;
|
||||
|
||||
switch (type) {
|
||||
case COMPOSITE:
|
||||
{
|
||||
/* pseudo component points for each component in composite glyph */
|
||||
unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ());
|
||||
if (unlikely (!points.resize (num_points))) return false;
|
||||
for (unsigned i = 0; i < points.length; i++)
|
||||
points[i].init ();
|
||||
break;
|
||||
case COMPOSITE: return CompositeGlyph (*header, bytes).get_contour_points (points_, end_points_, phantom_only);
|
||||
case SIMPLE: return SimpleGlyph (*header, bytes).get_contour_points (points_, end_points_, phantom_only);
|
||||
default:
|
||||
/* empty glyph */
|
||||
points_.resize (PHANTOM_COUNT);
|
||||
for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
|
||||
return true;
|
||||
}
|
||||
case SIMPLE:
|
||||
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
|
||||
return false;
|
||||
break;
|
||||
default: return false; /* empty glyph */
|
||||
}
|
||||
|
||||
hb_face_t *face = font->face;
|
||||
|
||||
/* Init phantom points */
|
||||
if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
|
||||
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
||||
{
|
||||
for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
|
||||
int h_delta = (int) header->xMin - face->table.hmtx->get_side_bearing (gid);
|
||||
int v_orig = (int) header->yMax + face->table.vmtx->get_side_bearing (gid);
|
||||
unsigned h_adv = face->table.hmtx->get_advance (gid);
|
||||
unsigned v_adv = face->table.vmtx->get_advance (gid);
|
||||
phantoms[PHANTOM_LEFT].x = h_delta;
|
||||
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
|
||||
phantoms[PHANTOM_TOP].y = v_orig;
|
||||
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, font, points.as_array ())))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
case SIMPLE:
|
||||
all_points.extend (points.as_array ());
|
||||
break;
|
||||
case COMPOSITE:
|
||||
{
|
||||
unsigned int comp_index = 0;
|
||||
for (auto &item : get_composite_iterator ())
|
||||
{
|
||||
contour_point_vector_t comp_points;
|
||||
if (unlikely (!glyph_for_gid (item.glyphIndex).get_points (glyph_for_gid, font, comp_points, phantom_only, depth + 1))
|
||||
|| comp_points.length < PHANTOM_COUNT)
|
||||
return false;
|
||||
|
||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||
if (item.is_use_my_metrics ())
|
||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||
|
||||
/* Apply component transformation & translation */
|
||||
item.transform_points (comp_points);
|
||||
|
||||
/* Apply translation from gvar */
|
||||
comp_points.translate (points[comp_index]);
|
||||
|
||||
if (item.is_anchored ())
|
||||
{
|
||||
unsigned int p1, p2;
|
||||
item.get_anchor_points (p1, p2);
|
||||
if (likely (p1 < all_points.length && p2 < comp_points.length))
|
||||
{
|
||||
contour_point_t delta;
|
||||
delta.init (all_points[p1].x - comp_points[p2].x,
|
||||
all_points[p1].y - comp_points[p2].y);
|
||||
|
||||
comp_points.translate (delta);
|
||||
}
|
||||
}
|
||||
|
||||
all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
|
||||
|
||||
comp_index++;
|
||||
}
|
||||
|
||||
all_points.extend (phantoms);
|
||||
} break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
if (depth == 0) /* Apply at top level */
|
||||
{
|
||||
/* Undocumented rasterizer behavior:
|
||||
* Shift points horizontally by the updated left side bearing
|
||||
*/
|
||||
contour_point_t delta;
|
||||
delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
|
||||
if (delta.x) all_points.translate (delta);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const
|
||||
bool is_simple_glyph () const { return type == SIMPLE; }
|
||||
bool is_composite_glyph () const { return type == COMPOSITE; }
|
||||
|
||||
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
||||
{
|
||||
if (type == EMPTY) return true; /* Empty glyph; zero extents. */
|
||||
return header->get_extents (font, gid, extents);
|
||||
}
|
||||
|
||||
hb_bytes_t get_bytes () const { return bytes; }
|
||||
hb_bytes_t get_bytes () const { return bytes; }
|
||||
const GlyphHeader &get_header () const { return *header; }
|
||||
|
||||
Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
|
||||
hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_),
|
||||
header (bytes.as<GlyphHeader> ())
|
||||
Glyph (hb_bytes_t bytes_ = hb_bytes_t ()) :
|
||||
bytes (bytes_), header (bytes.as<GlyphHeader> ())
|
||||
{
|
||||
int num_contours = header->numberOfContours;
|
||||
if (unlikely (num_contours == 0)) type = EMPTY;
|
||||
|
@ -823,7 +748,6 @@ struct glyf
|
|||
|
||||
protected:
|
||||
hb_bytes_t bytes;
|
||||
hb_codepoint_t gid;
|
||||
const GlyphHeader *header;
|
||||
unsigned type;
|
||||
};
|
||||
|
@ -847,7 +771,6 @@ struct glyf
|
|||
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
|
||||
|
||||
num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
|
||||
num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
|
||||
}
|
||||
|
||||
void fini ()
|
||||
|
@ -856,137 +779,223 @@ struct glyf
|
|||
glyf_table.destroy ();
|
||||
}
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
|
||||
enum phantom_point_index_t
|
||||
{
|
||||
/* Making this alloc free is not that easy
|
||||
https://github.com/harfbuzz/harfbuzz/issues/2095
|
||||
mostly because of gvar handling in VF fonts,
|
||||
perhaps a separate path for non-VF fonts can be considered */
|
||||
contour_point_vector_t all_points;
|
||||
PHANTOM_LEFT = 0,
|
||||
PHANTOM_RIGHT = 1,
|
||||
PHANTOM_TOP = 2,
|
||||
PHANTOM_BOTTOM = 3,
|
||||
PHANTOM_COUNT = 4
|
||||
};
|
||||
|
||||
bool phantom_only = !consumer.is_consuming_contour_points ();
|
||||
if (unlikely (!glyph_for_gid (gid).get_points ([this] (hb_codepoint_t gid) -> const Glyph { return this->glyph_for_gid (gid); },
|
||||
font, all_points, phantom_only)))
|
||||
return false;
|
||||
protected:
|
||||
|
||||
if (consumer.is_consuming_contour_points ())
|
||||
void init_phantom_points (hb_codepoint_t gid, hb_array_t<contour_point_t> &phantoms /* IN/OUT */) const
|
||||
{
|
||||
const Glyph &glyph = glyph_for_gid (gid);
|
||||
int h_delta = (int) glyph.get_header ().xMin - face->table.hmtx->get_side_bearing (gid);
|
||||
int v_orig = (int) glyph.get_header ().yMax + face->table.vmtx->get_side_bearing (gid);
|
||||
unsigned int h_adv = face->table.hmtx->get_advance (gid);
|
||||
unsigned int v_adv = face->table.vmtx->get_advance (gid);
|
||||
|
||||
phantoms[PHANTOM_LEFT].x = h_delta;
|
||||
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
|
||||
phantoms[PHANTOM_TOP].y = v_orig;
|
||||
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
|
||||
}
|
||||
|
||||
struct contour_bounds_t
|
||||
{
|
||||
contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
|
||||
|
||||
void add (const contour_point_t &p)
|
||||
{
|
||||
for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
|
||||
consumer.consume_point (all_points[point_index]);
|
||||
consumer.points_end ();
|
||||
min_x = hb_min (min_x, p.x);
|
||||
min_y = hb_min (min_y, p.y);
|
||||
max_x = hb_max (max_x, p.x);
|
||||
max_y = hb_max (max_y, p.y);
|
||||
}
|
||||
|
||||
/* Where to write phantoms, nullptr if not requested */
|
||||
contour_point_t *phantoms = consumer.get_phantoms_sink ();
|
||||
if (phantoms)
|
||||
for (unsigned i = 0; i < PHANTOM_COUNT; ++i)
|
||||
phantoms[i] = all_points[all_points.length - PHANTOM_COUNT + i];
|
||||
bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
|
||||
|
||||
void get_extents (hb_font_t *font, hb_glyph_extents_t *extents)
|
||||
{
|
||||
if (unlikely (empty ()))
|
||||
{
|
||||
extents->width = 0;
|
||||
extents->x_bearing = 0;
|
||||
extents->height = 0;
|
||||
extents->y_bearing = 0;
|
||||
return;
|
||||
}
|
||||
extents->x_bearing = font->em_scalef_x (min_x);
|
||||
extents->width = font->em_scalef_x (max_x - min_x);
|
||||
extents->y_bearing = font->em_scalef_y (max_y);
|
||||
extents->height = font->em_scalef_y (min_y - max_y);
|
||||
}
|
||||
|
||||
protected:
|
||||
float min_x, min_y, max_x, max_y;
|
||||
};
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
/* Note: Recursively calls itself.
|
||||
* all_points includes phantom points
|
||||
*/
|
||||
bool get_points_var (hb_codepoint_t gid,
|
||||
const int *coords, unsigned int coord_count,
|
||||
contour_point_vector_t &all_points /* OUT */,
|
||||
unsigned int depth = 0) const
|
||||
{
|
||||
if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return false;
|
||||
contour_point_vector_t points;
|
||||
hb_vector_t<unsigned int> end_points;
|
||||
const Glyph &glyph = glyph_for_gid (gid);
|
||||
if (unlikely (!glyph.get_contour_points (points, end_points))) return false;
|
||||
hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
||||
init_phantom_points (gid, phantoms);
|
||||
if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, coords, coord_count, points.as_array (), end_points.as_array ()))) return false;
|
||||
|
||||
unsigned int comp_index = 0;
|
||||
if (glyph.is_simple_glyph ())
|
||||
all_points.extend (points.as_array ());
|
||||
else if (glyph.is_composite_glyph ())
|
||||
{
|
||||
for (auto &item : glyph.get_composite_iterator ())
|
||||
{
|
||||
contour_point_vector_t comp_points;
|
||||
if (unlikely (!get_points_var (item.glyphIndex, coords, coord_count,
|
||||
comp_points, depth))
|
||||
|| comp_points.length < PHANTOM_COUNT)
|
||||
return false;
|
||||
|
||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||
if (item.is_use_my_metrics ())
|
||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||
|
||||
/* Apply component transformation & translation */
|
||||
item.transform_points (comp_points);
|
||||
|
||||
/* Apply translatation from gvar */
|
||||
comp_points.translate (points[comp_index]);
|
||||
|
||||
if (item.is_anchored ())
|
||||
{
|
||||
unsigned int p1, p2;
|
||||
item.get_anchor_points (p1, p2);
|
||||
if (likely (p1 < all_points.length && p2 < comp_points.length))
|
||||
{
|
||||
contour_point_t delta;
|
||||
delta.init (all_points[p1].x - comp_points[p2].x,
|
||||
all_points[p1].y - comp_points[p2].y);
|
||||
|
||||
comp_points.translate (delta);
|
||||
}
|
||||
}
|
||||
|
||||
all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
|
||||
|
||||
comp_index++;
|
||||
}
|
||||
|
||||
all_points.extend (phantoms);
|
||||
}
|
||||
else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_points_bearing_applied (hb_font_t *font, hb_codepoint_t gid, contour_point_vector_t &all_points) const
|
||||
{
|
||||
if (unlikely (!get_points_var (gid, font->coords, font->num_coords, all_points) ||
|
||||
all_points.length < PHANTOM_COUNT)) return false;
|
||||
|
||||
/* Undocumented rasterizer behavior:
|
||||
* Shift points horizontally by the updated left side bearing
|
||||
*/
|
||||
contour_point_t delta;
|
||||
delta.init (-all_points[all_points.length - PHANTOM_COUNT + PHANTOM_LEFT].x, 0.f);
|
||||
if (delta.x) all_points.translate (delta);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool get_var_extents_and_phantoms (hb_font_t *font, hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents=nullptr /* OUT */,
|
||||
contour_point_vector_t *phantoms=nullptr /* OUT */) const
|
||||
{
|
||||
contour_point_vector_t all_points;
|
||||
if (!unlikely (get_points_bearing_applied (font, gid, all_points))) return false;
|
||||
if (extents)
|
||||
{
|
||||
contour_bounds_t bounds;
|
||||
for (unsigned int i = 0; i + PHANTOM_COUNT < all_points.length; i++)
|
||||
bounds.add (all_points[i]);
|
||||
bounds.get_extents (font, extents);
|
||||
}
|
||||
if (phantoms)
|
||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||
(*phantoms)[i] = all_points[all_points.length - PHANTOM_COUNT + i];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_var_metrics (hb_font_t *font, hb_codepoint_t gid,
|
||||
contour_point_vector_t &phantoms) const
|
||||
{ return get_var_extents_and_phantoms (font, gid, nullptr, &phantoms); }
|
||||
|
||||
bool get_extents_var (hb_font_t *font, hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{ return get_var_extents_and_phantoms (font, gid, extents); }
|
||||
#endif
|
||||
|
||||
public:
|
||||
#ifndef HB_NO_VAR
|
||||
struct points_aggregator_t
|
||||
{
|
||||
hb_font_t *font;
|
||||
hb_glyph_extents_t *extents;
|
||||
contour_point_t *phantoms;
|
||||
|
||||
struct contour_bounds_t
|
||||
{
|
||||
contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
|
||||
|
||||
void add (const contour_point_t &p)
|
||||
{
|
||||
min_x = hb_min (min_x, p.x);
|
||||
min_y = hb_min (min_y, p.y);
|
||||
max_x = hb_max (max_x, p.x);
|
||||
max_y = hb_max (max_y, p.y);
|
||||
}
|
||||
|
||||
bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
|
||||
|
||||
void get_extents (hb_font_t *font, hb_glyph_extents_t *extents)
|
||||
{
|
||||
if (unlikely (empty ()))
|
||||
{
|
||||
extents->width = 0;
|
||||
extents->x_bearing = 0;
|
||||
extents->height = 0;
|
||||
extents->y_bearing = 0;
|
||||
return;
|
||||
}
|
||||
extents->x_bearing = font->em_scalef_x (min_x);
|
||||
extents->width = font->em_scalef_x (max_x - min_x);
|
||||
extents->y_bearing = font->em_scalef_y (max_y);
|
||||
extents->height = font->em_scalef_y (min_y - max_y);
|
||||
}
|
||||
|
||||
protected:
|
||||
float min_x, min_y, max_x, max_y;
|
||||
} bounds;
|
||||
|
||||
points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_)
|
||||
{
|
||||
font = font_;
|
||||
extents = extents_;
|
||||
phantoms = phantoms_;
|
||||
if (extents) bounds = contour_bounds_t ();
|
||||
}
|
||||
|
||||
void consume_point (const contour_point_t &point) { bounds.add (point); }
|
||||
void points_end () { bounds.get_extents (font, extents); }
|
||||
|
||||
bool is_consuming_contour_points () { return extents; }
|
||||
contour_point_t *get_phantoms_sink () { return phantoms; }
|
||||
};
|
||||
|
||||
unsigned int
|
||||
get_advance_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
|
||||
unsigned int get_advance_var (hb_font_t *font, hb_codepoint_t gid,
|
||||
bool is_vertical) const
|
||||
{
|
||||
bool success = false;
|
||||
contour_point_vector_t phantoms;
|
||||
phantoms.resize (PHANTOM_COUNT);
|
||||
|
||||
contour_point_t phantoms[PHANTOM_COUNT];
|
||||
if (likely (font->num_coords == face->table.gvar->get_axis_count ()))
|
||||
success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
|
||||
success = get_var_metrics (font, gid, phantoms);
|
||||
|
||||
if (unlikely (!success))
|
||||
return is_vertical
|
||||
? face->table.vmtx->get_advance (gid)
|
||||
: face->table.hmtx->get_advance (gid);
|
||||
return is_vertical ? face->table.vmtx->get_advance (gid) : face->table.hmtx->get_advance (gid);
|
||||
|
||||
return is_vertical
|
||||
? roundf (phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y)
|
||||
: roundf (phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x);
|
||||
if (is_vertical)
|
||||
return roundf (phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y);
|
||||
else
|
||||
return roundf (phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x);
|
||||
}
|
||||
|
||||
int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
|
||||
{
|
||||
hb_glyph_extents_t extents;
|
||||
contour_point_vector_t phantoms;
|
||||
phantoms.resize (PHANTOM_COUNT);
|
||||
|
||||
contour_point_t phantoms[PHANTOM_COUNT];
|
||||
if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms))))
|
||||
return is_vertical
|
||||
? face->table.vmtx->get_side_bearing (gid)
|
||||
: face->table.hmtx->get_side_bearing (gid);
|
||||
if (unlikely (!get_var_extents_and_phantoms (font, gid, &extents, &phantoms)))
|
||||
return is_vertical ? face->table.vmtx->get_side_bearing (gid) : face->table.hmtx->get_side_bearing (gid);
|
||||
|
||||
return is_vertical
|
||||
? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
|
||||
: floorf (phantoms[PHANTOM_LEFT].x);
|
||||
return is_vertical ? ceil (phantoms[PHANTOM_TOP].y) - extents.y_bearing : floor (phantoms[PHANTOM_LEFT].x);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
||||
{
|
||||
if (unlikely (gid >= num_glyphs)) return false;
|
||||
#ifndef HB_NO_VAR
|
||||
if (font->num_coords && font->num_coords == face->table.gvar->get_axis_count ())
|
||||
return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
|
||||
unsigned int coord_count;
|
||||
const int *coords = hb_font_get_var_coords_normalized (font, &coord_count);
|
||||
if (coords && coord_count > 0 && coord_count == face->table.gvar->get_axis_count ())
|
||||
return get_extents_var (font, gid, extents);
|
||||
#endif
|
||||
return glyph_for_gid (gid).get_extents (font, extents);
|
||||
|
||||
if (unlikely (gid >= num_glyphs)) return false;
|
||||
|
||||
return glyph_for_gid (gid).get_extents (font, gid, extents);
|
||||
}
|
||||
|
||||
const Glyph
|
||||
|
@ -1012,7 +1021,7 @@ struct glyf
|
|||
return Glyph ();
|
||||
|
||||
Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
|
||||
end_offset - start_offset), gid);
|
||||
end_offset - start_offset));
|
||||
return needs_padding_removal ? glyph.trim_padding () : glyph;
|
||||
}
|
||||
|
||||
|
@ -1027,130 +1036,9 @@ struct glyf
|
|||
gids_to_retain->add (gid);
|
||||
|
||||
for (auto &item : glyph_for_gid (gid).get_composite_iterator ())
|
||||
add_gid_and_children (item.glyphIndex, gids_to_retain, depth);
|
||||
add_gid_and_children (item.glyphIndex, gids_to_retain, depth);
|
||||
}
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
struct path_builder_t
|
||||
{
|
||||
hb_font_t *font;
|
||||
draw_helper_t *draw_helper;
|
||||
|
||||
struct optional_point_t
|
||||
{
|
||||
optional_point_t () { has_data = false; }
|
||||
optional_point_t (float x_, float y_) { x = x_; y = y_; has_data = true; }
|
||||
|
||||
bool has_data;
|
||||
float x;
|
||||
float y;
|
||||
|
||||
optional_point_t lerp (optional_point_t p, float t)
|
||||
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
|
||||
} first_oncurve, first_offcurve, last_offcurve;
|
||||
|
||||
path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_)
|
||||
{
|
||||
font = font_;
|
||||
draw_helper = &draw_helper_;
|
||||
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
||||
}
|
||||
|
||||
/* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
|
||||
See also:
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
|
||||
* https://stackoverflow.com/a/20772557 */
|
||||
void consume_point (const contour_point_t &point)
|
||||
{
|
||||
/* Skip empty contours */
|
||||
if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data))
|
||||
return;
|
||||
|
||||
bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
|
||||
optional_point_t p (point.x, point.y);
|
||||
if (!first_oncurve.has_data)
|
||||
{
|
||||
if (is_on_curve)
|
||||
{
|
||||
first_oncurve = p;
|
||||
draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (first_offcurve.has_data)
|
||||
{
|
||||
optional_point_t mid = first_offcurve.lerp (p, .5f);
|
||||
first_oncurve = mid;
|
||||
last_offcurve = p;
|
||||
draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
|
||||
}
|
||||
else
|
||||
first_offcurve = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (last_offcurve.has_data)
|
||||
{
|
||||
if (is_on_curve)
|
||||
{
|
||||
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
|
||||
font->em_scalef_x (p.x), font->em_scalef_y (p.y));
|
||||
last_offcurve = optional_point_t ();
|
||||
}
|
||||
else
|
||||
{
|
||||
optional_point_t mid = last_offcurve.lerp (p, .5f);
|
||||
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
|
||||
font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
|
||||
last_offcurve = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_on_curve)
|
||||
draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
|
||||
else
|
||||
last_offcurve = p;
|
||||
}
|
||||
}
|
||||
|
||||
if (point.is_end_point)
|
||||
{
|
||||
if (first_offcurve.has_data && last_offcurve.has_data)
|
||||
{
|
||||
optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
|
||||
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
|
||||
font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
|
||||
last_offcurve = optional_point_t ();
|
||||
/* now check the rest */
|
||||
}
|
||||
|
||||
if (first_offcurve.has_data && first_oncurve.has_data)
|
||||
draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y),
|
||||
font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
|
||||
else if (last_offcurve.has_data && first_oncurve.has_data)
|
||||
draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
|
||||
font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
|
||||
else if (first_oncurve.has_data)
|
||||
draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
|
||||
|
||||
/* Getting ready for the next contour */
|
||||
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
||||
draw_helper->end_path ();
|
||||
}
|
||||
}
|
||||
void points_end () {}
|
||||
|
||||
bool is_consuming_contour_points () { return true; }
|
||||
contour_point_t *get_phantoms_sink () { return nullptr; }
|
||||
};
|
||||
|
||||
bool
|
||||
get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const
|
||||
{ return get_points (font, gid, path_builder_t (font, draw_helper)); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool short_offset;
|
||||
unsigned int num_glyphs;
|
||||
|
@ -1185,7 +1073,7 @@ struct glyf
|
|||
pad_length--;
|
||||
}
|
||||
|
||||
if (unlikely (!dest_glyph.length)) return_trace (true);
|
||||
if (!unlikely (dest_glyph.length)) return_trace (true);
|
||||
|
||||
/* update components gids */
|
||||
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
|
||||
|
|
|
@ -107,8 +107,11 @@ struct hdmx
|
|||
this->numRecords = it.len ();
|
||||
this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0);
|
||||
|
||||
for (const hb_item_type<Iterator>& _ : +it)
|
||||
c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
|
||||
+ it
|
||||
| hb_apply ([c] (const hb_item_type<Iterator>& _) {
|
||||
c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
|
||||
})
|
||||
;
|
||||
|
||||
return_trace (c->successful);
|
||||
}
|
||||
|
@ -131,10 +134,10 @@ struct hdmx
|
|||
auto row =
|
||||
+ hb_range (c->plan->num_output_glyphs ())
|
||||
| hb_map (c->plan->reverse_glyph_map)
|
||||
| hb_map ([this, c, device_record] (hb_codepoint_t _)
|
||||
| hb_map ([=] (hb_codepoint_t _)
|
||||
{
|
||||
if (c->plan->is_empty_glyph (_))
|
||||
return Null (HBUINT8);
|
||||
return Null(HBUINT8);
|
||||
return device_record->widthsZ.as_array (get_num_glyphs ()) [_];
|
||||
})
|
||||
;
|
||||
|
@ -161,12 +164,10 @@ struct hdmx
|
|||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number (0) */
|
||||
HBUINT16 numRecords; /* Number of device records. */
|
||||
HBUINT32 sizeDeviceRecord;
|
||||
/* Size of a device record, 32-bit aligned. */
|
||||
DeviceRecord firstDeviceRecord;
|
||||
/* Array of device records. */
|
||||
HBUINT16 version; /* Table version number (0) */
|
||||
HBUINT16 numRecords; /* Number of device records. */
|
||||
HBUINT32 sizeDeviceRecord; /* Size of a device record, 32-bit aligned. */
|
||||
DeviceRecord firstDeviceRecord; /* Array of device records. */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (8);
|
||||
};
|
||||
|
|
|
@ -54,18 +54,6 @@ struct head
|
|||
return 16 <= upem && upem <= 16384 ? upem : 1000;
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
return_trace ((bool) c->embed (this));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
return_trace (serialize (c->serializer));
|
||||
}
|
||||
|
||||
enum mac_style_flag_t {
|
||||
BOLD = 1u<<0,
|
||||
ITALIC = 1u<<1,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче