diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..708188ad8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +trim_trailing_whitespace = true +end_of_line = lf +insert_final_newline = true + +[*.{c,cc,h,hh}] +indent_size = 2 +indent_style = space +tab_width = 8 + +[*.{py,sh}] +indent_style = tab + +[{CMakeLists.txt,*.cmake}] +indent_size = 2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c19a4b98..6b4e10899 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -836,10 +836,9 @@ if (UNIX OR MINGW) ) add_test(NAME check-libstdc++.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-libstdc++.sh) add_test(NAME check-symbols.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-symbols.sh) - add_test(NAME check-defs.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-defs.sh) set_tests_properties( - check-static-inits.sh check-libstdc++.sh check-symbols.sh check-defs.sh + check-static-inits.sh check-libstdc++.sh check-symbols.sh PROPERTIES ENVIRONMENT "libs=.;srcdir=${PROJECT_SOURCE_DIR}/src" SKIP_RETURN_CODE 77) diff --git a/configure.ac b/configure.ac index 8c3ab2029..eee2568dc 100644 --- a/configure.ac +++ b/configure.ac @@ -184,6 +184,7 @@ if $have_gobject; then AC_SUBST(GLIB_MKENUMS) fi AM_CONDITIONAL(HAVE_GOBJECT, $have_gobject) +AC_SUBST(have_gobject) dnl =========================================================================== @@ -491,6 +492,7 @@ AC_CONFIG_FILES([ Makefile src/Makefile src/hb-version.h +src/harfbuzz-config.cmake src/hb-ucdn/Makefile util/Makefile test/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index aba6803cd..c4d5fb85b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -125,10 +125,12 @@ HBLIBS += $(HBNONPCLIBS) if OS_WIN32 export_symbols = -export-symbols harfbuzz.def harfbuzz_def_dependency = harfbuzz.def -export_symbols_icu = -export-symbols harfbuzz-icu.def -harfbuzz_icu_def_dependency = harfbuzz-icu.def export_symbols_subset = -export-symbols harfbuzz-subset.def harfbuzz_subset_def_dependency = harfbuzz-subset.def +export_symbols_icu = -export-symbols harfbuzz-icu.def +harfbuzz_icu_def_dependency = harfbuzz-icu.def +export_symbols_gobject = -export-symbols harfbuzz-gobject.def +harfbuzz_gobject_def_dependency = harfbuzz-gobject.def chosen_linker = $(CXXLINK) else if WITH_LIBSTDCXX @@ -154,7 +156,9 @@ pkginclude_HEADERS = $(HBHEADERS) nodist_pkginclude_HEADERS = $(HBNODISTHEADERS) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = harfbuzz.pc -EXTRA_DIST += harfbuzz.pc.in +cmakedir = $(libdir)/cmake/harfbuzz +cmake_DATA = harfbuzz-config.cmake +EXTRA_DIST += harfbuzz.pc.in harfbuzz-config.cmake.in lib_LTLIBRARIES += libharfbuzz-subset.la libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources) @@ -210,13 +214,14 @@ EXTRA_DIST += harfbuzz-icu.pc.in if HAVE_GOBJECT lib_LTLIBRARIES += libharfbuzz-gobject.la libharfbuzz_gobject_la_LINK = $(chosen_linker) $(libharfbuzz_gobject_la_LDFLAGS) -libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_sources) -nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_ENUM_sources) +libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_DIST_sources) +nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_NODIST_sources) libharfbuzz_gobject_la_CPPFLAGS = $(HBCFLAGS) $(HBNOLIBCXXFLAGS) $(GOBJECT_CFLAGS) libharfbuzz_gobject_la_LDFLAGS = $(base_link_flags) libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la -pkginclude_HEADERS += $(HB_GOBJECT_headers) -nodist_pkginclude_HEADERS += $(HB_GOBJECT_ENUM_headers) +EXTRA_libharfbuzz_gobject_la_DEPENDENCIES = $(harfbuzz_gobject_def_dependency) +pkginclude_HEADERS += $(HB_GOBJECT_DIST_headers) +nodist_pkginclude_HEADERS += $(HB_GOBJECT_NODIST_headers) pkgconfig_DATA += harfbuzz-gobject.pc BUILT_SOURCES += \ @@ -256,12 +261,19 @@ EXTRA_DIST += \ CLEANFILES += $(pkgconfig_DATA) -CLEANFILES += harfbuzz.def harfbuzz-icu.def harfbuzz-subset.def +DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def +if HAVE_GOBJECT +DEF_FILES += harfbuzz-gobject.def +endif +check: $(DEF_FILES) # For check-symbols.sh +CLEANFILES += $(DEF_FILES) harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS) $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@ +harfbuzz-subset.def: $(HB_SUBSET_headers) + $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@ harfbuzz-icu.def: $(HB_ICU_headers) $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@ -harfbuzz-subset.def: $(HB_SUBSET_headers) +harfbuzz-gobject.def: $(HB_GOBJECT_headers) $(AM_V_GEN) headers="$^" $(srcdir)/gen-def.py $@ @@ -335,11 +347,8 @@ test_buffer_serialize_SOURCES = test-buffer-serialize.cc test_buffer_serialize_CPPFLAGS = $(HBCFLAGS) test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS) -check: harfbuzz.def harfbuzz-icu.def harfbuzz-subset.def # For check-defs.sh - dist_check_SCRIPTS = \ check-c-linkage-decls.sh \ - check-defs.sh \ check-externs.sh \ check-header-guards.sh \ check-includes.sh \ @@ -415,10 +424,8 @@ HarfBuzz_0_0_gir_FILES = \ $(HBHEADERS) \ $(HBNODISTHEADERS) \ $(HBSOURCES) \ - $(HB_GOBJECT_ENUM_sources) \ - $(HB_GOBJECT_ENUM_headers) \ $(HB_GOBJECT_sources) \ - $(HB_GOBJECT_STRUCTS_headers) \ + $(HB_GOBJECT_headers) \ $(NULL) girdir = $(datadir)/gir-1.0 diff --git a/src/Makefile.sources b/src/Makefile.sources index 9b96716d2..2bb56b4f9 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -20,6 +20,7 @@ HB_BASE_sources = \ hb-ot-cbdt-table.hh \ hb-ot-cmap-table.hh \ hb-ot-glyf-table.hh \ + hb-ot-hdmx-table.hh \ hb-ot-head-table.hh \ hb-ot-hhea-table.hh \ hb-ot-hmtx-table.hh \ @@ -200,8 +201,11 @@ HB_SUBSET_headers = \ hb-subset-private.hh \ $(NULL) -HB_GOBJECT_sources = hb-gobject-structs.cc -HB_GOBJECT_STRUCTS_headers = hb-gobject-structs.h -HB_GOBJECT_headers = hb-gobject.h $(HB_GOBJECT_STRUCTS_headers) +HB_GOBJECT_DIST_sources = hb-gobject-structs.cc +HB_GOBJECT_DIST_headers = hb-gobject.h hb-gobject-structs.h HB_GOBJECT_ENUM_sources = hb-gobject-enums.cc HB_GOBJECT_ENUM_headers = hb-gobject-enums.h +HB_GOBJECT_NODIST_sources = $(HB_GOBJECT_ENUM_sources) +HB_GOBJECT_NODIST_headers = $(HB_GOBJECT_ENUM_headers) +HB_GOBJECT_sources = $(HB_GOBJECT_DIST_sources) $(HB_GOBJECT_NODIST_sources) +HB_GOBJECT_headers = $(HB_GOBJECT_DIST_headers) $(HB_GOBJECT_NODIST_headers) diff --git a/src/check-defs.sh b/src/check-defs.sh deleted file mode 100755 index ade593570..000000000 --- a/src/check-defs.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh - -LC_ALL=C -export LC_ALL - -test -z "$srcdir" && srcdir=. -test -z "$libs" && libs=.libs -stat=0 - -if which nm 2>/dev/null >/dev/null; then - : -else - echo "check-defs.sh: 'nm' not found; skipping test" - exit 77 -fi - -tested=false -for def in harfbuzz.def harfbuzz-icu.def harfbuzz-subset.def; do - if ! test -f "$def"; then - echo "check-defs.sh: '$def' not found; skipping test it" - continue - fi - lib=`echo "$def" | sed 's/[.]def$//;s@.*/@@'` - for suffix in so dylib; do - so=$libs/lib${lib}.$suffix - if ! test -f "$so"; then continue; fi - - # On macOS, C symbols are prefixed with _ - if test $suffix = dylib; then prefix="_"; fi - - EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v " $prefix"'\(_fini\>\|_init\>\|_fdata\>\|_ftext\>\|_fbss\>\|__bss_start\>\|__bss_start__\>\|__bss_end__\>\|_edata\>\|_end\>\|_bss_end__\>\|__end__\>\|__gcov_flush\>\|llvm_\)' | cut -d' ' -f3`" - - if test -f "$so"; then - - echo "Checking that $so has the same symbol list as $def" - { - echo EXPORTS - echo "$EXPORTED_SYMBOLS" | sed -e "s/^${prefix}hb/hb/g" - # cheat: copy the last line from the def file! - tail -n1 "$def" - } | diff "$def" - >&2 || stat=1 - - tested=true - fi - done -done -if ! $tested; then - echo "check-defs.sh: libharfbuzz shared library not found; skipping test" - exit 77 -fi - -exit $stat diff --git a/src/check-symbols.sh b/src/check-symbols.sh index af8af4416..bfc93b349 100755 --- a/src/check-symbols.sh +++ b/src/check-symbols.sh @@ -7,6 +7,7 @@ test -z "$srcdir" && srcdir=. 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_flush\|llvm_.*' if which nm 2>/dev/null >/dev/null; then : @@ -15,31 +16,46 @@ else exit 77 fi -echo "Checking that we are not exposing internal symbols" tested=false for soname in harfbuzz harfbuzz-subset harfbuzz-icu harfbuzz-gobject; do for suffix in so dylib; do so=$libs/lib$soname.$suffix if ! test -f "$so"; then continue; fi - EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| ___gcov_flush\>\| llvm_\| _llvm_' | cut -d' ' -f3`" - - prefix=`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'` - # On macOS, C symbols are prefixed with _ - if test $suffix = dylib; then prefix="_$prefix"; fi + symprefix= + if test $suffix = dylib; then symprefix=_; fi - echo "Processing $so" + EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] .' | grep -v " $symprefix\\($IGNORED_SYMBOLS\\>\\)" | cut -d' ' -f3 | c++filt`" + + prefix=$symprefix`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'` + + echo + echo "Checking that $so does not expose internal symbols" if echo "$EXPORTED_SYMBOLS" | grep -v "^${prefix}\(_\|$\)"; then echo "Ouch, internal symbols exposed" stat=1 fi + def=$soname.def + if ! test -f "$def"; then + echo "'$def' not found; skipping" + else + echo + echo "Checking that $so has the same symbol list as $def" + { + echo EXPORTS + echo "$EXPORTED_SYMBOLS" | sed -e "s/^${symprefix}hb/hb/g" + # cheat: copy the last line from the def file! + tail -n1 "$def" + } | c++filt | diff "$def" - >&2 || stat=1 + fi + tested=true done done if ! $tested; then - echo "check-symbols.sh: no shared library found; skipping test" + echo "check-symbols.sh: no shared libraries found; skipping test" exit 77 fi diff --git a/src/dev-run.sh b/src/dev-run.sh index 5a7ae1022..3b2257b1d 100755 --- a/src/dev-run.sh +++ b/src/dev-run.sh @@ -13,26 +13,48 @@ [ $# = 0 ] && echo Usage: "src/dev-run.sh [FONT-FILE] [TEXT]" && exit command -v entr >/dev/null 2>&1 || { echo >&2 "This script needs `entr` be installed"; exit 1; } +GDB=gdb +# if gdb doesn't exist, hopefully lldb exist +command -v $GDB >/dev/null 2>&1 || export GDB="lldb" + [ -f 'build/build.ninja' ] && CMAKENINJA=TRUE # or "fswatch -0 . -e build/ -e .git" find src/ | entr printf '\0' | while read -d ""; do clear + echo '====================================================' if [[ $CMAKENINJA ]]; then - ninja -Cbuild hb-shape hb-view - build/hb-shape $@ - build/hb-view $@ + ninja -Cbuild hb-shape hb-view && { + build/hb-shape $@ + build/hb-view $@ + } else - make -Cbuild/src -j5 -s lib - build/util/hb-shape $@ - build/util/hb-view $@ + make -Cbuild/src -j5 -s lib && { + build/util/hb-shape $@ + build/util/hb-view $@ + } fi done -read -n 1 -p "Run the tests (y/n)? " answer -if [[ "$answer" = "y" ]]; then +read -n 1 -p "[T]est, [D]ebug, [R]estart, [Q]uit?" answer +case "$answer" in +t|T ) if [[ $CMAKENINJA ]]; then CTEST_OUTPUT_ON_FAILURE=1 CTEST_PARALLEL_LEVEL=5 ninja -Cbuild test else make -Cbuild -j5 check && .ci/fail.sh fi -fi +;; +d|D ) + if [[ $CMAKENINJA ]]; then + echo "Not supported on cmake builds yet" + else + build/libtool --mode=execute $GDB build/util/hb-shape $@ + fi +;; +r|R ) + src/dev-run.sh $@ +;; +* ) + exit +;; +esac diff --git a/src/harfbuzz-config.cmake.in b/src/harfbuzz-config.cmake.in new file mode 100644 index 000000000..87b15721a --- /dev/null +++ b/src/harfbuzz-config.cmake.in @@ -0,0 +1,82 @@ +# Set these variables so that the `${prefix}/lib` expands to something we can +# remove. +set(_harfbuzz_remove_string "REMOVE_ME") +set(exec_prefix "${_harfbuzz_remove_string}") +set(prefix "${_harfbuzz_remove_string}") + +# Compute the installation prefix by stripping components from our current +# location. +get_filename_component(_harfbuzz_prefix "${CMAKE_CURRENT_LIST_DIR}" DIRECTORY) +get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY) +set(_harfbuzz_libdir "@libdir@") +string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_libdir "${_harfbuzz_libdir}") +set(_harfbuzz_libdir_iter "${_harfbuzz_libdir}") +while (_harfbuzz_libdir_iter) + get_filename_component(_harfbuzz_libdir_iter "${_harfbuzz_libdir_iter}" DIRECTORY) + get_filename_component(_harfbuzz_prefix "${_harfbuzz_prefix}" DIRECTORY) +endwhile () +unset(_harfbuzz_libdir_iter) + +# Get the include subdir. +set(_harfbuzz_includedir "@includedir@") +string(REPLACE "${_harfbuzz_remove_string}/" "" _harfbuzz_includedir "${_harfbuzz_includedir}") + +# Extract version information from libtool. +set(_harfbuzz_version_info "@HB_LIBTOOL_VERSION_INFO@") +string(REPLACE ":" ";" _harfbuzz_version_info "${_harfbuzz_version_info}") +list(GET _harfbuzz_version_info 0 + _harfbuzz_current) +list(GET _harfbuzz_version_info 1 + _harfbuzz_revision) +list(GET _harfbuzz_version_info 2 + _harfbuzz_age) +unset(_harfbuzz_version_info) + +if (APPLE) + set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}") +elseif (UNIX) + set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}") +else () + # Unsupported. + set(harfbuzz_FOUND 0) +endif () + +# Add the libraries. +add_library(harfbuzz::harfbuzz SHARED IMPORTED) +set_target_properties(harfbuzz::harfbuzz PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz" + IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz${_harfbuzz_lib_suffix}") + +add_library(harfbuzz::icu SHARED IMPORTED) +set_target_properties(harfbuzz::icu PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz" + INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz" + IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-icu${_harfbuzz_lib_suffix}") + +add_library(harfbuzz::subset SHARED IMPORTED) +set_target_properties(harfbuzz::subset PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz" + INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz" + IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-subset${_harfbuzz_lib_suffix}") + +# Only add the gobject library if it was built. +set(_harfbuzz_have_gobject "@have_gobject@") +if (_harfbuzz_have_gobject) + add_library(harfbuzz::gobject SHARED IMPORTED) + set_target_properties(harfbuzz::gobject PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_harfbuzz_prefix}/${_harfbuzz_includedir}/harfbuzz" + INTERFACE_LINK_LIBRARIES "harfbuzz::harfbuzz" + IMPORTED_LOCATION "${_harfbuzz_prefix}/${_harfbuzz_libdir}/libharfbuzz-gobject${_harfbuzz_lib_suffix}") +endif () + +# Clean out variables we used in our scope. +unset(_harfbuzz_lib_suffix) +unset(_harfbuzz_current) +unset(_harfbuzz_revision) +unset(_harfbuzz_age) +unset(_harfbuzz_includedir) +unset(_harfbuzz_libdir) +unset(_harfbuzz_prefix) +unset(exec_prefix) +unset(prefix) +unset(_harfbuzz_remove_string) diff --git a/src/hb-buffer-deserialize-json.hh b/src/hb-buffer-deserialize-json.hh new file mode 100644 index 000000000..be374c77a --- /dev/null +++ b/src/hb-buffer-deserialize-json.hh @@ -0,0 +1,643 @@ + +#line 1 "hb-buffer-deserialize-json.rl" +/* + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BUFFER_DESERIALIZE_JSON_HH +#define HB_BUFFER_DESERIALIZE_JSON_HH + +#include "hb-private.hh" + + +#line 36 "hb-buffer-deserialize-json.hh" +static const unsigned char _deserialize_json_trans_keys[] = { + 0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, + 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, + 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, + 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, + 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, + 65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0 +}; + +static const char _deserialize_json_key_spans[] = { + 0, 115, 26, 7, 2, 1, 50, 49, + 10, 117, 117, 117, 1, 50, 49, 10, + 117, 117, 1, 1, 50, 49, 117, 117, + 2, 1, 50, 49, 10, 117, 117, 1, + 50, 49, 10, 117, 117, 1, 50, 49, + 58, 89, 117, 117, 85, 115, 0 +}; + +static const short _deserialize_json_index_offsets[] = { + 0, 0, 116, 143, 151, 154, 156, 207, + 257, 268, 386, 504, 622, 624, 675, 725, + 736, 854, 972, 974, 976, 1027, 1077, 1195, + 1313, 1316, 1318, 1369, 1419, 1430, 1548, 1666, + 1668, 1719, 1769, 1780, 1898, 2016, 2018, 2069, + 2119, 2178, 2268, 2386, 2504, 2590, 2706 +}; + +static const char _deserialize_json_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 4, 1, + 5, 1, 6, 7, 1, 1, 8, 1, + 9, 10, 1, 11, 1, 11, 11, 11, + 11, 11, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 11, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 12, 1, + 12, 12, 12, 12, 12, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 12, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 13, 1, 1, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 1, 16, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 1, 18, 18, 18, + 18, 18, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 18, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 19, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 20, 1, 21, 21, 21, 21, 21, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 21, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 22, + 1, 18, 18, 18, 18, 18, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 18, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 19, 1, 1, 1, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 20, 1, 23, + 1, 23, 23, 23, 23, 23, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 23, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 24, 1, 24, 24, 24, 24, + 24, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 24, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 25, 1, 1, 26, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 1, 28, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 1, 30, 30, 30, 30, 30, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 30, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 31, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 32, 1, 30, + 30, 30, 30, 30, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 30, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 31, 1, 1, 1, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 32, 1, 33, 1, 34, + 1, 34, 34, 34, 34, 34, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 34, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 35, 1, 35, 35, 35, 35, + 35, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 35, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 36, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 1, 38, 38, + 38, 38, 38, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 38, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 40, 1, 38, 38, 38, 38, + 38, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 38, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 39, + 1, 1, 1, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 40, 1, 42, 43, 1, 44, 1, 44, + 44, 44, 44, 44, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 44, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 45, 1, 45, 45, 45, 45, 45, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 45, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 46, 1, + 1, 47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 1, 49, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 1, 51, + 51, 51, 51, 51, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 51, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 52, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 53, 1, 51, 51, 51, + 51, 51, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 51, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 52, 1, 1, 1, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 53, 1, 54, 1, 54, 54, 54, + 54, 54, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 54, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 55, 1, + 55, 55, 55, 55, 55, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 55, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 56, 1, 1, 57, + 58, 58, 58, 58, 58, 58, 58, 58, + 58, 1, 59, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 1, 61, 61, 61, + 61, 61, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 61, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 62, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 63, 1, 61, 61, 61, 61, 61, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 61, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 62, 1, + 1, 1, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 63, + 1, 64, 1, 64, 64, 64, 64, 64, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 64, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 65, 1, 65, 65, + 65, 65, 65, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 65, 1, 66, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 67, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 1, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 1, 1, 1, 1, 1, 1, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 1, 70, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 71, 71, + 1, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 1, 1, 1, 1, 1, + 1, 1, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 1, 1, 1, 1, + 71, 1, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 1, 72, 72, 72, + 72, 72, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 72, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 73, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 74, 1, 72, 72, 72, 72, 72, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 73, 1, + 1, 1, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 74, + 1, 76, 76, 76, 76, 76, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 76, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 77, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 78, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 0 +}; + +static const char _deserialize_json_trans_targs[] = { + 1, 0, 2, 2, 3, 4, 18, 24, + 37, 5, 12, 6, 7, 8, 9, 11, + 9, 11, 10, 2, 44, 10, 44, 13, + 14, 15, 16, 17, 16, 17, 10, 2, + 44, 19, 20, 21, 22, 23, 10, 2, + 44, 23, 25, 31, 26, 27, 28, 29, + 30, 29, 30, 10, 2, 44, 32, 33, + 34, 35, 36, 35, 36, 10, 2, 44, + 38, 39, 40, 42, 43, 41, 10, 41, + 10, 2, 44, 43, 44, 45, 46 +}; + +static const char _deserialize_json_trans_actions[] = { + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, + 0, 0, 3, 3, 4, 0, 5, 0, + 0, 2, 2, 2, 0, 0, 6, 6, + 7, 0, 0, 0, 2, 2, 8, 8, + 9, 0, 0, 0, 0, 0, 2, 2, + 2, 0, 0, 10, 10, 11, 0, 0, + 2, 2, 2, 0, 0, 12, 12, 13, + 0, 0, 0, 2, 2, 2, 14, 0, + 15, 15, 16, 0, 0, 0, 0 +}; + +static const int deserialize_json_start = 1; +static const int deserialize_json_first_final = 44; +static const int deserialize_json_error = 0; + +static const int deserialize_json_en_main = 1; + + +#line 97 "hb-buffer-deserialize-json.rl" + + +static hb_bool_t +_hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer, + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) +{ + const char *p = buf, *pe = buf + buf_len; + + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, nullptr); + + while (p < pe && ISSPACE (*p)) + p++; + if (p < pe && *p == (buffer->len ? ',' : '[')) + { + *end_ptr = ++p; + } + + const char *tok = nullptr; + int cs; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; + +#line 466 "hb-buffer-deserialize-json.hh" + { + cs = deserialize_json_start; + } + +#line 471 "hb-buffer-deserialize-json.hh" + { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_json_trans_keys + (cs<<1); + _inds = _deserialize_json_indicies + _deserialize_json_index_offsets[cs]; + + _slen = _deserialize_json_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; + + cs = _deserialize_json_trans_targs[_trans]; + + if ( _deserialize_json_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _deserialize_json_trans_actions[_trans] ) { + case 1: +#line 38 "hb-buffer-deserialize-json.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} + break; + case 5: +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 2: +#line 51 "hb-buffer-deserialize-json.rl" + { + tok = p; +} + break; + case 14: +#line 55 "hb-buffer-deserialize-json.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 15: +#line 62 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } + break; + case 8: +#line 63 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 10: +#line 64 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +#line 65 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 3: +#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 6: +#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } + break; + case 16: +#line 62 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 63 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 64 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 13: +#line 65 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 4: +#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 7: +#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 624 "hb-buffer-deserialize-json.hh" + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + _out: {} + } + +#line 125 "hb-buffer-deserialize-json.rl" + + + *end_ptr = p; + + return p == pe && *(p-1) != ']'; +} + +#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */ diff --git a/src/hb-buffer-deserialize-text.hh b/src/hb-buffer-deserialize-text.hh new file mode 100644 index 000000000..a6ab0bbde --- /dev/null +++ b/src/hb-buffer-deserialize-text.hh @@ -0,0 +1,571 @@ + +#line 1 "hb-buffer-deserialize-text.rl" +/* + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BUFFER_DESERIALIZE_TEXT_HH +#define HB_BUFFER_DESERIALIZE_TEXT_HH + +#include "hb-private.hh" + + +#line 36 "hb-buffer-deserialize-text.hh" +static const unsigned char _deserialize_text_trans_keys[] = { + 0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, + 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, + 9u, 122u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, + 9u, 124u, 9u, 124u, 9u, 124u, 0 +}; + +static const char _deserialize_text_key_spans[] = { + 0, 114, 13, 10, 13, 10, 10, 13, + 10, 1, 13, 10, 14, 116, 116, 0, + 114, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116 +}; + +static const short _deserialize_text_index_offsets[] = { + 0, 0, 115, 129, 140, 154, 165, 176, + 190, 201, 203, 217, 228, 243, 360, 477, + 478, 593, 710, 827, 944, 1061, 1178, 1295, + 1412, 1529, 1646 +}; + +static const char _deserialize_text_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, + 1, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 1, 1, 1, 1, + 1, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 5, 1, 1, 6, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 1, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 1, 10, 1, 1, + 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 1, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 1, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 1, 17, 1, 1, 18, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 1, 20, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 1, 22, 1, 23, 1, 1, 24, + 25, 25, 25, 25, 25, 25, 25, 25, + 25, 1, 26, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 1, 22, 1, 1, + 1, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 1, 28, 28, 28, 28, + 28, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 28, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 29, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 30, 1, 1, 31, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 32, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 33, + 1, 34, 34, 34, 34, 34, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 34, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 35, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 36, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 1, 1, 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 1, 28, 28, 28, 28, 28, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 28, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 29, 1, 1, 1, + 1, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 1, 1, 1, 30, 1, + 1, 31, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 32, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 33, 1, 38, + 38, 38, 38, 38, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 38, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 39, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 40, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 41, 1, 42, 42, 42, 42, + 42, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 42, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 43, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 44, + 1, 42, 42, 42, 42, 42, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 42, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 43, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 44, 1, 38, 38, + 38, 38, 38, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 38, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 40, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 41, 1, 45, 45, 45, 45, 45, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 45, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 46, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 47, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 48, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 49, 1, + 50, 50, 50, 50, 50, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 50, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 51, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 52, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 53, 1, 50, 50, 50, + 50, 50, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 50, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 51, + 1, 1, 1, 1, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 52, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 53, 1, 45, 45, 45, 45, 45, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 45, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 46, 1, 1, 1, + 1, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 1, 1, 1, 1, 1, + 1, 47, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 48, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 49, 1, 28, + 28, 28, 28, 28, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 28, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 29, 1, 55, 55, 1, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 1, 1, 1, 30, 1, 1, 31, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 1, 1, 32, 1, 55, 1, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, + 55, 1, 33, 1, 0 +}; + +static const char _deserialize_text_trans_targs[] = { + 1, 0, 13, 17, 26, 3, 18, 21, + 18, 21, 5, 19, 20, 19, 20, 22, + 25, 8, 9, 12, 9, 12, 10, 11, + 23, 24, 23, 24, 14, 2, 6, 7, + 15, 16, 14, 15, 16, 17, 14, 4, + 15, 16, 14, 15, 16, 14, 2, 7, + 15, 16, 14, 2, 15, 16, 25, 26 +}; + +static const char _deserialize_text_trans_actions[] = { + 0, 0, 1, 1, 1, 2, 2, 2, + 0, 0, 2, 2, 2, 0, 0, 2, + 2, 2, 2, 2, 0, 0, 3, 2, + 2, 2, 0, 0, 4, 5, 5, 5, + 4, 4, 0, 0, 0, 0, 6, 7, + 6, 6, 8, 8, 8, 9, 10, 10, + 9, 9, 11, 12, 11, 11, 0, 0 +}; + +static const char _deserialize_text_eof_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, + 0, 4, 6, 8, 8, 6, 9, 11, + 11, 9, 4 +}; + +static const int deserialize_text_start = 1; +static const int deserialize_text_first_final = 13; +static const int deserialize_text_error = 0; + +static const int deserialize_text_en_main = 1; + + +#line 91 "hb-buffer-deserialize-text.rl" + + +static hb_bool_t +_hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer, + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) +{ + const char *p = buf, *pe = buf + buf_len; + + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, nullptr); + + while (p < pe && ISSPACE (*p)) + p++; + if (p < pe && *p == (buffer->len ? '|' : '[')) + { + *end_ptr = ++p; + } + + const char *eof = pe, *tok = nullptr; + int cs; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; + +#line 343 "hb-buffer-deserialize-text.hh" + { + cs = deserialize_text_start; + } + +#line 348 "hb-buffer-deserialize-text.hh" + { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_text_trans_keys + (cs<<1); + _inds = _deserialize_text_indicies + _deserialize_text_index_offsets[cs]; + + _slen = _deserialize_text_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; + + cs = _deserialize_text_trans_targs[_trans]; + + if ( _deserialize_text_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _deserialize_text_trans_actions[_trans] ) { + case 2: +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} + break; + case 5: +#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 10: +#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 3: +#line 63 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 7: +#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 1: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} + break; + case 4: +#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 6: +#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 8: +#line 66 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 480 "hb-buffer-deserialize-text.hh" + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + switch ( _deserialize_text_eof_actions[cs] ) { + case 4: +#line 55 "hb-buffer-deserialize-text.rl" + { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 62 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 64 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 6: +#line 65 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 8: +#line 66 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 557 "hb-buffer-deserialize-text.hh" + } + } + + _out: {} + } + +#line 119 "hb-buffer-deserialize-text.rl" + + + *end_ptr = p; + + return p == pe && *(p-1) != ']'; +} + +#endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */ diff --git a/src/hb-gobject-enums.h.tmpl b/src/hb-gobject-enums.h.tmpl index e28510c22..606727cd3 100644 --- a/src/hb-gobject-enums.h.tmpl +++ b/src/hb-gobject-enums.h.tmpl @@ -42,7 +42,8 @@ HB_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN value-header ***/ -HB_EXTERN GType @enum_name@_get_type (void) G_GNUC_CONST; +HB_EXTERN GType +@enum_name@_get_type (void) G_GNUC_CONST; #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) /*** END value-header ***/ diff --git a/src/hb-gobject-structs.h b/src/hb-gobject-structs.h index a34b06abb..302dc9584 100644 --- a/src/hb-gobject-structs.h +++ b/src/hb-gobject-structs.h @@ -45,7 +45,8 @@ HB_BEGIN_DECLS * * Since: 0.9.2 **/ -HB_EXTERN GType hb_gobject_blob_get_type (void); +HB_EXTERN GType +hb_gobject_blob_get_type (void); #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ()) /** @@ -53,7 +54,8 @@ HB_EXTERN GType hb_gobject_blob_get_type (void); * * Since: 0.9.2 **/ -HB_EXTERN GType hb_gobject_buffer_get_type (void); +HB_EXTERN GType +hb_gobject_buffer_get_type (void); #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ()) /** @@ -61,7 +63,8 @@ HB_EXTERN GType hb_gobject_buffer_get_type (void); * * Since: 0.9.2 **/ -HB_EXTERN GType hb_gobject_face_get_type (void); +HB_EXTERN GType +hb_gobject_face_get_type (void); #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ()) /** @@ -69,7 +72,8 @@ HB_EXTERN GType hb_gobject_face_get_type (void); * * Since: 0.9.2 **/ -HB_EXTERN GType hb_gobject_font_get_type (void); +HB_EXTERN GType +hb_gobject_font_get_type (void); #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ()) /** @@ -77,13 +81,16 @@ HB_EXTERN GType hb_gobject_font_get_type (void); * * Since: 0.9.2 **/ -HB_EXTERN GType hb_gobject_font_funcs_get_type (void); +HB_EXTERN GType +hb_gobject_font_funcs_get_type (void); #define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ()) -HB_EXTERN GType hb_gobject_set_get_type (void); +HB_EXTERN GType +hb_gobject_set_get_type (void); #define HB_GOBJECT_TYPE_SET (hb_gobject_set_get_type ()) -HB_EXTERN GType hb_gobject_shape_plan_get_type (void); +HB_EXTERN GType +hb_gobject_shape_plan_get_type (void); #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ()) /** @@ -91,30 +98,38 @@ HB_EXTERN GType hb_gobject_shape_plan_get_type (void); * * Since: 0.9.2 **/ -HB_EXTERN GType hb_gobject_unicode_funcs_get_type (void); +HB_EXTERN GType +hb_gobject_unicode_funcs_get_type (void); #define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ()) /* Value types */ -HB_EXTERN GType hb_gobject_feature_get_type (void); +HB_EXTERN GType +hb_gobject_feature_get_type (void); #define HB_GOBJECT_TYPE_FEATURE (hb_gobject_feature_get_type ()) -HB_EXTERN GType hb_gobject_glyph_info_get_type (void); +HB_EXTERN GType +hb_gobject_glyph_info_get_type (void); #define HB_GOBJECT_TYPE_GLYPH_INFO (hb_gobject_glyph_info_get_type ()) -HB_EXTERN GType hb_gobject_glyph_position_get_type (void); +HB_EXTERN GType +hb_gobject_glyph_position_get_type (void); #define HB_GOBJECT_TYPE_GLYPH_POSITION (hb_gobject_glyph_position_get_type ()) -HB_EXTERN GType hb_gobject_segment_properties_get_type (void); +HB_EXTERN GType +hb_gobject_segment_properties_get_type (void); #define HB_GOBJECT_TYPE_SEGMENT_PROPERTIES (hb_gobject_segment_properties_get_type ()) -HB_EXTERN GType hb_gobject_user_data_key_get_type (void); +HB_EXTERN GType +hb_gobject_user_data_key_get_type (void); #define HB_GOBJECT_TYPE_USER_DATA_KEY (hb_gobject_user_data_key_get_type ()) -HB_EXTERN GType hb_gobject_ot_math_glyph_variant_get_type (void); +HB_EXTERN GType +hb_gobject_ot_math_glyph_variant_get_type (void); #define HB_GOBJECT_TYPE_OT_MATH_GLYPH_VARIANT (hb_gobject_ot_math_glyph_variant_get_type ()) -HB_EXTERN GType hb_gobject_ot_math_glyph_part_get_type (void); +HB_EXTERN GType +hb_gobject_ot_math_glyph_part_get_type (void); #define HB_GOBJECT_TYPE_OT_MATH_GLYPH_PART (hb_gobject_ot_math_glyph_part_get_type ()) diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh index 88ce65a40..e2644eaf9 100644 --- a/src/hb-open-file-private.hh +++ b/src/hb-open-file-private.hh @@ -30,6 +30,7 @@ #define HB_OPEN_FILE_PRIVATE_HH #include "hb-open-type-private.hh" +#include "hb-ot-head-table.hh" namespace OT { @@ -133,39 +134,67 @@ typedef struct OffsetTable unsigned int table_count) { TRACE_SERIALIZE (this); - /* alloc 12 for the OTHeader */ + /* Alloc 12 for the OTHeader. */ if (unlikely (!c->extend_min (*this))) return_trace (false); - /* write sfntVersion (bytes 0..3) */ + /* Write sfntVersion (bytes 0..3). */ sfnt_version.set (sfnt_tag); - /* take space for numTables, searchRange, entrySelector, RangeShift - * and the TableRecords themselves - */ + /* Take space for numTables, searchRange, entrySelector, RangeShift + * and the TableRecords themselves. */ if (unlikely (!tables.serialize (c, table_count))) return_trace (false); - /* write OffsetTables, alloc for and write actual table blobs */ + const char *dir_end = (const char *) c->head; + HBUINT32 *checksum_adjustment = nullptr; + + /* Write OffsetTables, alloc for and write actual table blobs. */ for (unsigned int i = 0; i < table_count; i++) { TableRecord &rec = tables.array[i]; hb_blob_t *blob = blobs[i]; rec.tag.set (tags[i]); rec.length.set (hb_blob_get_length (blob)); - rec.checkSum.set_for_data (hb_blob_get_data (blob, nullptr), rec.length); rec.offset.serialize (c, this); - // take room for the table - void *p = c->allocate_size (rec.length); - if (unlikely (!p)) {return false;} - /* copy the actual table */ - memcpy (p, hb_blob_get_data (blob, nullptr), rec.length); - /* 4-byte allignment */ + + /* Allocate room for the table and copy it. */ + char *start = (char *) c->allocate_size (rec.length); + if (unlikely (!start)) {return false;} + + memcpy (start, hb_blob_get_data (blob, nullptr), rec.length); + + /* 4-byte allignment. */ if (rec.length % 4) - p = c->allocate_size (4 - rec.length % 4); + c->allocate_size (4 - rec.length % 4); + const char *end = (const char *) c->head; + + if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size) + { + head *h = (head *) start; + checksum_adjustment = &h->checkSumAdjustment; + checksum_adjustment->set (0); + } + + rec.checkSum.set_for_data (start, end - start); } tags += table_count; blobs += table_count; - /* TODO: update head table checkSumAdjustment. */ - tables.qsort (); + + if (checksum_adjustment) + { + CheckSum checksum; + + /* The following line is a slower version of the following block. */ + //checksum.set_for_data (this, (const char *) c->head - (const char *) this); + checksum.set_for_data (this, dir_end - (const char *) this); + for (unsigned int i = 0; i < table_count; i++) + { + TableRecord &rec = tables.array[i]; + checksum.set (checksum + rec.checkSum); + } + + checksum_adjustment->set (0xB1B0AFBAu - checksum); + } + return_trace (true); } diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 54eda4c52..f5c20bcb6 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -762,7 +762,8 @@ struct CheckSum : HBUINT32 static inline uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length) { uint32_t Sum = 0L; - const HBUINT32 *EndPtr = Table+((Length+3) & ~3) / HBUINT32::static_size; + assert (0 == (Length & 3)); + const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size; while (Table < EndPtr) Sum += *Table++; diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index 4593152b5..020798986 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -602,7 +602,7 @@ struct cmap + 8 // 1 EncodingRecord + 16 // Format 12 header + 12 * groups.len; // SequentialMapGroup records - void *dest = calloc (dest_sz, 1); + void *dest = malloc (dest_sz); if (unlikely (!dest)) { DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz); return false; @@ -618,9 +618,11 @@ struct cmap hb_blob_t *cmap_prime = hb_blob_create ((const char *)dest, dest_sz, HB_MEMORY_MODE_READONLY, - /* userdata */ nullptr, + dest, free); - return hb_subset_plan_add_table (plan, HB_OT_TAG_cmap, cmap_prime); + bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_cmap, cmap_prime); + hb_blob_destroy (cmap_prime); + return result; } struct accelerator_t diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh new file mode 100644 index 000000000..f08fe39d8 --- /dev/null +++ b/src/hb-ot-hdmx-table.hh @@ -0,0 +1,198 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#ifndef HB_OT_HDMX_TABLE_HH +#define HB_OT_HDMX_TABLE_HH + +#include "hb-open-type-private.hh" + +namespace OT { + + +/* + * hdmx - Horizontal Device Metric + */ + +#define HB_OT_TAG_hdmx HB_TAG('h','d','m','x') + +struct DeviceRecord +{ + struct SubsetView + { + const DeviceRecord *source_device_record; + hb_subset_plan_t *subset_plan; + + inline void init(const DeviceRecord *source_device_record, + hb_subset_plan_t *subset_plan) + { + this->source_device_record = source_device_record; + this->subset_plan = subset_plan; + } + + inline unsigned int len () const + { + return this->subset_plan->gids_to_retain_sorted.len; + } + + inline const HBUINT8& operator [] (unsigned int i) const + { + if (unlikely (i >= len())) return Null(HBUINT8); + hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i]; + return this->source_device_record->widths[gid]; + } + }; + + static inline unsigned int get_size (unsigned int count) + { + unsigned int raw_size = min_size + count * HBUINT8::static_size; + if (raw_size % 4) + /* Align to 32 bits */ + return raw_size + (4 - (raw_size % 4)); + return raw_size; + } + + inline bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view) + { + TRACE_SERIALIZE (this); + + if (unlikely (!c->allocate_size (get_size (subset_view.len())))) + return_trace (false); + + this->pixel_size.set (subset_view.source_device_record->pixel_size); + this->max_width.set (subset_view.source_device_record->max_width); + + for (unsigned int i = 0; i < subset_view.len(); i++) + widths[i].set (subset_view[i]); + + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c, unsigned int size_device_record) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + c->check_range (this, size_device_record))); + } + + HBUINT8 pixel_size; /* Pixel size for following widths (as ppem). */ + HBUINT8 max_width; /* Maximum width. */ + HBUINT8 widths[VAR]; /* Array of widths (numGlyphs is from the 'maxp' table). */ + public: + DEFINE_SIZE_ARRAY (2, widths); +}; + + +struct hdmx +{ + static const hb_tag_t tableTag = HB_OT_TAG_hdmx; + + inline unsigned int get_size (void) const + { + return min_size + num_records * size_device_record; + } + + inline const DeviceRecord& operator [] (unsigned int i) const + { + if (unlikely (i >= num_records)) return Null(DeviceRecord); + return StructAtOffset (this, min_size + i * size_device_record); + } + + inline bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan) + { + TRACE_SERIALIZE (this); + + if (unlikely (!c->extend_min ((*this)))) return_trace (false); + + this->version.set (source_hdmx->version); + this->num_records.set (source_hdmx->num_records); + this->size_device_record.set (DeviceRecord::get_size (plan->gids_to_retain_sorted.len)); + + for (unsigned int i = 0; i < source_hdmx->num_records; i++) + { + DeviceRecord::SubsetView subset_view; + subset_view.init (&(*source_hdmx)[i], plan); + + c->start_embed ()->serialize (c, subset_view); + } + + return_trace (true); + } + + static inline size_t get_subsetted_size (hb_subset_plan_t *plan) + { + return min_size + DeviceRecord::get_size (plan->gids_to_retain_sorted.len); + } + + inline bool subset (hb_subset_plan_t *plan) const + { + size_t dest_size = get_subsetted_size (plan); + hdmx *dest = (hdmx *) malloc (dest_size); + if (unlikely (!dest)) + { + DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for hdmx subset output.", (unsigned long) dest_size); + return false; + } + + hb_serialize_context_t c (dest, dest_size); + hdmx *hdmx_prime = c.start_serialize (); + if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan)) { + free (dest); + return false; + } + c.end_serialize (); + + hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest, + dest_size, + HB_MEMORY_MODE_READONLY, + dest, + free); + bool result = hb_subset_plan_add_table (plan, HB_OT_TAG_hdmx, hdmx_prime_blob); + hb_blob_destroy (hdmx_prime_blob); + + return result; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && version == 0 && + !_hb_unsigned_int_mul_overflows (num_records, size_device_record) && + c->check_range (this, get_size())); + } + + protected: + HBUINT16 version; /* Table version number (0) */ + HBUINT16 num_records; /* Number of device records. */ + HBUINT32 size_device_record; /* Size of a device record, 32-bit aligned. */ + HBUINT8 data[VAR]; /* Array of device records. */ + public: + DEFINE_SIZE_ARRAY (8, data); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_HDMX_TABLE_HH */ diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh index 2024cea7e..1d4584045 100644 --- a/src/hb-ot-head-table.hh +++ b/src/hb-ot-head-table.hh @@ -43,6 +43,8 @@ namespace OT { struct head { + friend struct OffsetTable; + static const hb_tag_t tableTag = HB_OT_TAG_head; inline unsigned int get_upem (void) const diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index 11cc92794..3cd48a62e 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -105,7 +105,7 @@ struct hmtxvmtx /* alloc the new table */ size_t dest_sz = num_advances * 4 + (gids.len - num_advances) * 2; - void *dest = (void *) calloc (dest_sz, 1); + void *dest = (void *) malloc (dest_sz); if (unlikely (!dest)) { return false; @@ -166,9 +166,11 @@ struct hmtxvmtx hb_blob_t *result = hb_blob_create ((const char *)dest, dest_sz, HB_MEMORY_MODE_READONLY, - /* userdata */ nullptr, + dest, free); - return hb_subset_plan_add_table (plan, T::tableTag, result); + bool success = hb_subset_plan_add_table (plan, T::tableTag, result); + hb_blob_destroy (result); + return success; } struct accelerator_t diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc index 654566af2..a97e1b76a 100644 --- a/src/hb-subset-glyf.cc +++ b/src/hb-subset-glyf.cc @@ -284,6 +284,8 @@ hb_subset_glyf_and_loca (hb_subset_plan_t *plan, use_short_loca, glyf_prime, loca_prime); + + hb_blob_destroy (glyf_blob); glyf.fini(); return result; diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 8dfa660db..f8a09efe4 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -168,6 +168,7 @@ _populate_gids_to_retain (hb_face_t *face, while (hb_set_next (all_gids_to_retain, &gid)) *(old_gids_sorted.push ()) = gid; + hb_set_destroy (all_gids_to_retain); glyf.fini (); cmap.fini (); } diff --git a/src/hb-subset.cc b/src/hb-subset.cc index c708e193b..cba05176d 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -35,6 +35,7 @@ #include "hb-open-file-private.hh" #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" +#include "hb-ot-hdmx-table.hh" #include "hb-ot-head-table.hh" #include "hb-ot-hhea-table.hh" #include "hb-ot-hmtx-table.hh" @@ -82,16 +83,19 @@ template static bool _subset (hb_subset_plan_t *plan) { - OT::Sanitizer sanitizer; - hb_blob_t *source_blob = sanitizer.sanitize (plan->source->reference_table (TableType::tableTag)); - const TableType *table = OT::Sanitizer::lock_instance (source_blob); - hb_bool_t result = table->subset(plan); + OT::Sanitizer sanitizer; - hb_blob_destroy (source_blob); + hb_blob_t *source_blob = sanitizer.sanitize (plan->source->reference_table (TableType::tableTag)); + const TableType *table = OT::Sanitizer::lock_instance (source_blob); - hb_tag_t tag = TableType::tableTag; - DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG(tag), result ? "success" : "FAILED!"); - return result; + hb_bool_t result = false; + if (table != &OT::Null(TableType)) + result = table->subset(plan); + + hb_blob_destroy (source_blob); + hb_tag_t tag = TableType::tableTag; + DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG(tag), result ? "success" : "FAILED!"); + return result; } @@ -132,6 +136,9 @@ _hb_subset_face_data_destroy (void *user_data) { hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data; + for (int i = 0; i < data->tables.len; i++) + hb_blob_destroy (data->tables[i].blob); + data->tables.finish (); free (data); @@ -191,6 +198,8 @@ _hb_subset_face_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data) return nullptr; } +/* TODO: Move this to hb-face.h and rename to hb_face_builder_create() + * with hb_face_builder_add_table(). */ hb_face_t * hb_subset_face_create (void) { @@ -229,6 +238,9 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_glyf: result = _subset (plan); break; + case HB_OT_TAG_hdmx: + result = _subset (plan); + break; case HB_OT_TAG_head: // TODO that won't work well if there is no glyf DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf"); @@ -254,13 +266,14 @@ _subset_table (hb_subset_plan_t *plan, break; default: hb_blob_t *source_table = hb_face_reference_table(plan->source, tag); - if (likely(source_table)) + if (likely (source_table)) result = hb_subset_plan_add_table(plan, tag, source_table); else result = false; - DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG(tag), result ? "ok" : "FAILED"); + hb_blob_destroy (source_table); break; } + DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG(tag), result ? "ok" : "FAILED"); return result; } diff --git a/test/api/Makefile.am b/test/api/Makefile.am index ecf447545..e2e6166c0 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -33,6 +33,7 @@ TEST_PROGS = \ test-shape \ test-subset-cmap \ test-subset-glyf \ + test-subset-hdmx \ test-subset-hmtx \ test-subset-os2 \ test-unicode \ @@ -42,6 +43,7 @@ TEST_PROGS = \ test_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_cmap_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_glyf_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la +test_subset_hdmx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_hmtx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la test_subset_os2_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la diff --git a/test/api/test-subset-hdmx.c b/test/api/test-subset-hdmx.c new file mode 100644 index 000000000..291eb7937 --- /dev/null +++ b/test/api/test-subset-hdmx.c @@ -0,0 +1,81 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#include + +#include "hb-test.h" +#include "hb-subset-test.h" + +/* Unit tests for hdmx subsetting */ + + +static void +test_subset_hdmx_simple_subset (void) +{ + hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf"); + hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.ttf"); + + hb_set_t *codepoints = hb_set_create (); + hb_set_add (codepoints, 'a'); + hb_set_add (codepoints, 'c'); + hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints); + hb_set_destroy (codepoints); + + hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('h','d','m','x')); + + hb_face_destroy (face_abc_subset); + hb_face_destroy (face_abc); + hb_face_destroy (face_ac); +} + +static void +test_subset_hdmx_noop (void) +{ + hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf"); + + hb_set_t *codepoints = hb_set_create(); + hb_set_add (codepoints, 'a'); + hb_set_add (codepoints, 'b'); + hb_set_add (codepoints, 'c'); + hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints); + hb_set_destroy (codepoints); + + hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('h','d','m','x')); + + hb_face_destroy (face_abc_subset); + hb_face_destroy (face_abc); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_subset_hdmx_simple_subset); + hb_test_add (test_subset_hdmx_noop); + + return hb_test_run(); +} diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf index 501d1d288..8d7e6b227 100644 Binary files a/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf and b/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf differ diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py index f648627ec..99f97826e 100755 --- a/test/subset/run-tests.py +++ b/test/subset/run-tests.py @@ -6,6 +6,7 @@ from __future__ import print_function import io +from difflib import unified_diff import os import re import subprocess @@ -59,9 +60,12 @@ def run_test(test): return fail_test(test, cli_args, "ttx (actual) returned %d" % (return_code)) expected_ttx = strip_check_sum (expected_ttx) - actual_ttx = strip_check_sum (expected_ttx) + actual_ttx = strip_check_sum (actual_ttx) if not actual_ttx == expected_ttx: + for line in unified_diff(expected_ttx.splitlines(1), actual_ttx.splitlines(1)): + sys.stdout.write(line) + sys.stdout.flush() return fail_test(test, cli_args, 'ttx for expected and actual does not match.') return 0 @@ -73,8 +77,8 @@ def run_ttx(file): return cmd(cli_args) def strip_check_sum (ttx_string): - return re.sub ('checksumAdjustment value=["]0x(\d+)["]', - 'checksumAdjustment value="0x00000000"', + return re.sub ('checkSumAdjustment value=["]0x([0-9a-fA-F])+["]', + 'checkSumAdjustment value="0x00000000"', ttx_string, count=1) args = sys.argv[1:] diff --git a/util/options.cc b/util/options.cc index 7571fe840..db7115cf5 100644 --- a/util/options.cc +++ b/util/options.cc @@ -481,6 +481,25 @@ parse_font_size (const char *name G_GNUC_UNUSED, return false; } } + +static gboolean +parse_font_ppem (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + font_options_t *font_opts = (font_options_t *) data; + switch (sscanf (arg, "%d%*[ ,]%d", &font_opts->x_ppem, &font_opts->y_ppem)) { + case 1: font_opts->y_ppem = font_opts->x_ppem; + case 2: return true; + default: + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "%s argument should be one or two space-separated numbers", + name); + return false; + } +} + void font_options_t::add_options (option_parser_t *parser) { @@ -513,12 +532,13 @@ font_options_t::add_options (option_parser_t *parser) GOptionEntry entries[] = { - {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"}, - {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"}, + {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"}, + {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"}, {"font-size", 0, default_font_size ? 0 : G_OPTION_FLAG_HIDDEN, - G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_size, font_size_text, "1/2 numbers or 'upem'"}, - /* TODO Add font-ppem / font-ptem. */ - {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"}, + G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_size, font_size_text, "1/2 integers or 'upem'"}, + {"font-ppem", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_ppem, "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"}, + {"font-ptem", 0, 0, G_OPTION_ARG_DOUBLE, &this->ptem, "Set font point-size (default: 0; disabled)", "point-size"}, + {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"}, {nullptr} }; parser->add_group (entries, @@ -691,6 +711,9 @@ font_options_t::get_font (void) const if (font_size_y == FONT_SIZE_UPEM) font_size_y = hb_face_get_upem (face); + hb_font_set_ppem (font, x_ppem, y_ppem); + hb_font_set_ptem (font, ptem); + int scale_x = (int) scalbnf (font_size_x, subpixel_bits); int scale_y = (int) scalbnf (font_size_y, subpixel_bits); hb_font_set_scale (font, scale_x, scale_y); diff --git a/util/options.hh b/util/options.hh index cce0eb163..f78156dbb 100644 --- a/util/options.hh +++ b/util/options.hh @@ -452,6 +452,9 @@ struct font_options_t : option_group_t variations = nullptr; num_variations = 0; default_font_size = default_font_size_; + x_ppem = 0; + y_ppem = 0; + ptem = .0; subpixel_bits = subpixel_bits_; font_file = nullptr; face_index = 0; @@ -478,6 +481,9 @@ struct font_options_t : option_group_t hb_variation_t *variations; unsigned int num_variations; int default_font_size; + int x_ppem; + int y_ppem; + double ptem; unsigned int subpixel_bits; mutable double font_size_x; mutable double font_size_y;