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:
Coroiu Cristina 2020-05-12 13:43:26 +03:00
Родитель 7738900e5b
Коммит a43b568040
184 изменённых файлов: 4270 добавлений и 9286 удалений

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

@ -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 &param)
{
/* 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 &param, const point_t &pt1)
{
param.line_to (pt1);
env.moveto (pt1);
}
static void curve (cff1_cs_interp_env_t &env, cff1_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);
}
};
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 glyphs 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 doesnt 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,

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше