Bug 1417131 - Update HarfBuzz to 1.7.1. r=jfkthame

This commit is contained in:
Ryan VanderMeulen 2017-11-28 10:14:22 -05:00
Родитель ded0cee6bf
Коммит aac3a947d7
59 изменённых файлов: 1973 добавлений и 748 удалений

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

@ -1,3 +1,23 @@
Overview of changes leading to 1.7.1
Tuesday, November 14, 2017
====================================
- Fix atexit object destruction regression.
- Fix minor integer-overflow.
Overview of changes leading to 1.7.0
Monday, November 13, 2017
====================================
- Minor Indic fixes.
- Implement kerning and glyph names in hb-ot-font.
- Various DSO optimization re .data and .bss sizes.
- Make C++11 optional; build fixes.
- Mark all other backends "unsafe-to-break".
- Graphite fix.
Overview of changes leading to 1.6.3
Thursday, October 26th, 2017
====================================
@ -809,7 +829,7 @@ Wednesday, July 16, 2014
U+FFFD REPLACEMENT CHARACTER now.
- With all changes in this release, the buffer will contain fully
valid Unicode after hb_buffer_add_utf8/16/32 no matter how
broken the input is. This can be overriden though. See below.
broken the input is. This can be overridden though. See below.
- Fix Mongolian Variation Selectors for fonts without GDEF.
- Fix minor invalid buffer access.
- Accept zh-Hant and zh-Hans language tags. hb_ot_tag_to_language()

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

@ -1,5 +1,6 @@
[![Build Status](https://travis-ci.org/behdad/harfbuzz.svg)](https://travis-ci.org/behdad/harfbuzz)
[![Build Status](https://ci.appveyor.com/api/projects/status/4oaq58ns2h0m2soa?svg=true)](https://ci.appveyor.com/project/behdad/harfbuzz)
[![CircleCI](https://circleci.com/gh/behdad/harfbuzz.svg?style=svg)](https://circleci.com/gh/behdad/harfbuzz)
[![Coverage Status](https://img.shields.io/coveralls/behdad/harfbuzz.svg)](https://coveralls.io/r/behdad/harfbuzz)
[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)

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

@ -1,18 +1,18 @@
gfx/harfbuzz status as of 2017-10-26:
gfx/harfbuzz status as of 2017-11-14:
This directory contains the harfbuzz source from the 'master' branch of
This directory contains the HarfBuzz source from the 'master' branch of
https://github.com/behdad/harfbuzz.
Current version: 1.6.3
Current version: 1.7.1
UPDATING:
Note that gfx/harfbuzz/src/hb-version.h is not present in the upstream Git
repository. It is created at build time by the harfbuzz build system;
repository. It is created at build time by the HarfBuzz build system;
but as we don't use that build system in mozilla, it is necessary to refresh
this file when updating harfbuzz, and check it into the mozilla tree.
this file when updating HarfBuzz, and check it into the mozilla tree.
The normal approach to updating harfbuzz, therefore, is to pull the latest HB
The normal approach to updating HarfBuzz, therefore, is to pull the latest HB
source into a scratch directory and do a local build; then copy the original
sources AND the generated header mentioned above from the build directory into
the mozilla tree.

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

@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
[1.6.3],
[1.7.1],
[https://github.com/behdad/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])
@ -23,6 +23,7 @@ AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CXX
AX_CXX_COMPILE_STDCXX(11, noext, optional)
AC_SYS_LARGEFILE
PKG_PROG_PKG_CONFIG([0.20])
AM_MISSING_PROG([RAGEL], [ragel])
@ -80,9 +81,6 @@ if test "x$GCC" = "xyes"; then
# Make symbols link locally
LDFLAGS="$LDFLAGS -Bsymbolic-functions"
# Choose C++ version
CXXFLAGS="$CXXFLAGS -std=c++11"
# Make sure we don't link to libstdc++
CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions"
@ -167,7 +165,7 @@ dnl ===========================================================================
AC_ARG_WITH(gobject,
[AS_HELP_STRING([--with-gobject=@<:@yes/no/auto@:>@],
[Use gobject @<:@default=auto@:>@])],,
[Use gobject @<:@default=no@:>@])],,
[with_gobject=no])
have_gobject=false
if test "x$with_gobject" = "xyes" -o "x$with_gobject" = "xauto"; then

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

@ -48,7 +48,7 @@ GIT_MK_URL = https://raw.githubusercontent.com/behdad/git.mk/master/git.mk
#
# This file knows how to handle autoconf, automake, libtool, gtk-doc,
# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata,
# appstream.
# appstream, hotdoc.
#
# This makefile provides the following targets:
#
@ -86,6 +86,7 @@ GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL = \
ar-lib \
compile \
config.guess \
config.rpath \
config.sub \
depcomp \
install-sh \
@ -120,6 +121,47 @@ GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL = \
lt~obsolete.m4 \
; do echo "$$MACRO_DIR/$$x"; done; \
fi`
#
# Modules that use gettext and use AC_CONFIG_MACRO_DIR() may also include this,
# though it's harmless to include regardless.
GITIGNORE_MAINTAINERCLEANFILES_M4_GETTEXT = \
`MACRO_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_MACRO_DIR:$$1' ./configure.ac); \
if test "x$$MACRO_DIR" != "x$(srcdir)/"; then \
for x in \
codeset.m4 \
extern-inline.m4 \
fcntl-o.m4 \
gettext.m4 \
glibc2.m4 \
glibc21.m4 \
iconv.m4 \
intdiv0.m4 \
intl.m4 \
intldir.m4 \
intlmacosx.m4 \
intmax.m4 \
inttypes-pri.m4 \
inttypes_h.m4 \
lcmessage.m4 \
lib-ld.m4 \
lib-link.m4 \
lib-prefix.m4 \
lock.m4 \
longlong.m4 \
nls.m4 \
po.m4 \
printf-posix.m4 \
progtest.m4 \
size_max.m4 \
stdint_h.m4 \
threadlib.m4 \
uintmax_t.m4 \
visibility.m4 \
wchar_t.m4 \
wint_t.m4 \
xsize.m4 \
; do echo "$$MACRO_DIR/$$x"; done; \
fi`
@ -208,6 +250,15 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
"*/*.omf.out" \
; do echo /$$x; done; \
fi; \
if test "x$(HOTDOC)" = x; then :; else \
$(foreach project, $(HOTDOC_PROJECTS),echo "/$(call HOTDOC_TARGET,$(project))"; \
echo "/$(shell $(call HOTDOC_PROJECT_COMMAND,$(project)) --get-conf-path output)" ; \
echo "/$(shell $(call HOTDOC_PROJECT_COMMAND,$(project)) --get-private-folder)" ; \
) \
for x in \
.hotdoc.d \
; do echo "/$$x"; done; \
fi; \
if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \
for lc in $(HELP_LINGUAS); do \
for x in \
@ -235,6 +286,7 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
fi; \
if test -f $(srcdir)/po/Makefile.in.in; then \
for x in \
ABOUT-NLS \
po/Makefile.in.in \
po/Makefile.in.in~ \
po/Makefile.in \
@ -243,6 +295,7 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
po/POTFILES \
po/Rules-quot \
po/stamp-it \
po/stamp-po \
po/.intltool-merge-cache \
"po/*.gmo" \
"po/*.header" \
@ -274,7 +327,7 @@ $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
if test "x$(am__dirstamp)" = x; then :; else \
echo "$(am__dirstamp)"; \
fi; \
if test "x$(LTCOMPILE)" = x -a "x$(LTCXXCOMPILE)" = x -a "x$(GTKDOC_RUN)" = x; then :; else \
if test "x$(findstring libtool,$(LTCOMPILE))" = x -a "x$(findstring libtool,$(LTCXXCOMPILE))" = x -a "x$(GTKDOC_RUN)" = x; then :; else \
for x in \
"*.lo" \
".libs" "_libs" \

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

@ -34,7 +34,7 @@ grep -v 'hb-private[.]hh:' |
grep . >&2 && stat=1
echo 'Checking that there is no #include <hb.*.h>'
echo 'Checking that there is no #include <hb-*.h>'
for x in $HBHEADERS $HBSOURCES; do
test -f "$srcdir/$x" && x="$srcdir/$x"
grep '#.*\<include\>.*<.*hb' "$x" /dev/null >&2 && stat=1

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

@ -5,7 +5,7 @@ includedir=/usr/local/include
Name: harfbuzz
Description: HarfBuzz text shaping library ICU integration
Version: 1.6.3
Version: 1.7.1
Requires: harfbuzz
Requires.private: icu-uc

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

@ -5,7 +5,7 @@ includedir=/usr/local/include
Name: harfbuzz
Description: HarfBuzz text shaping library
Version: 1.6.3
Version: 1.7.1
Libs: -L${libdir} -lharfbuzz
Libs.private: -lm

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

@ -89,9 +89,9 @@ typedef int32_t hb_atomic_int_impl_t;
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
#else
#if __ppc64__ || __x86_64__ || __aarch64__
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (void *) (O), (int64_t) (void *) (N), (int64_t*) (P))
#else
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (void *) (O), (int32_t) (void *) (N), (int32_t*) (P))
#endif
#endif

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

@ -30,6 +30,7 @@
#endif
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-object-private.hh"
@ -44,12 +45,6 @@
#include <errno.h>
#ifndef HB_DEBUG_BLOB
#define HB_DEBUG_BLOB (HB_DEBUG+0)
#endif
struct hb_blob_t {
hb_object_header_t header;
ASSERT_POD ();

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

@ -305,16 +305,16 @@ struct hb_buffer_t {
info.cluster = cluster;
}
int
inline int
_unsafe_to_break_find_min_cluster (const hb_glyph_info_t *info,
unsigned int start, unsigned int end,
unsigned int cluster) const
{
for (unsigned int i = start; i < end; i++)
cluster = MIN (cluster, info[i].cluster);
cluster = MIN<unsigned int> (cluster, info[i].cluster);
return cluster;
}
void
inline void
_unsafe_to_break_set_mask (hb_glyph_info_t *info,
unsigned int start, unsigned int end,
unsigned int cluster)
@ -326,6 +326,19 @@ struct hb_buffer_t {
info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
}
}
inline void
unsafe_to_break_all (void)
{
for (unsigned int i = 0; i < len; i++)
info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
}
inline void
safe_to_break_all (void)
{
for (unsigned int i = 0; i < len; i++)
info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
}
};

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

@ -554,7 +554,7 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
unsigned int cluster = info[start].cluster;
for (unsigned int i = start + 1; i < end; i++)
cluster = MIN (cluster, info[i].cluster);
cluster = MIN<unsigned int> (cluster, info[i].cluster);
/* Extend end */
while (end < len && info[end - 1].cluster == info[end].cluster)
@ -585,7 +585,7 @@ hb_buffer_t::merge_out_clusters (unsigned int start,
unsigned int cluster = out_info[start].cluster;
for (unsigned int i = start + 1; i < end; i++)
cluster = MIN (cluster, out_info[i].cluster);
cluster = MIN<unsigned int> (cluster, out_info[i].cluster);
/* Extend start */
while (start && out_info[start - 1].cluster == out_info[start].cluster)

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

@ -85,7 +85,7 @@ hb_tag_from_string (const char *str, int len)
for (; i < 4; i++)
tag[i] = ' ';
return HB_TAG_CHAR4 (tag);
return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
}
/**
@ -699,34 +699,43 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv)
#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
static locale_t C_locale;
static HB_LOCALE_T C_locale;
#ifdef HB_USE_ATEXIT
static void
free_C_locale (void)
{
if (C_locale)
freelocale (C_locale);
HB_FREE_LOCALE (C_locale);
}
#endif
static locale_t
static HB_LOCALE_T
get_C_locale (void)
{
retry:
locale_t C = (locale_t) hb_atomic_ptr_get (&C_locale);
HB_LOCALE_T C = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
if (unlikely (!C))
{
C = newlocale (LC_ALL_MASK, "C", nullptr);
C = HB_CREATE_LOCALE ("C");
if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C))
{
freelocale (C_locale);
HB_FREE_LOCALE (C_locale);
goto retry;
}

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

@ -27,16 +27,14 @@
*/
#define HB_SHAPER coretext
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-shaper-impl-private.hh"
#include "hb-coretext.h"
#include <math.h>
#ifndef HB_DEBUG_CORETEXT
#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
#endif
/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
@ -351,7 +349,9 @@ struct active_feature_t {
feature_record_t rec;
unsigned int order;
static int cmp (const active_feature_t *a, const active_feature_t *b) {
static int cmp (const void *pa, const void *pb) {
const active_feature_t *a = (const active_feature_t *) pa;
const active_feature_t *b = (const active_feature_t *) pb;
return a->rec.feature < b->rec.feature ? -1 : a->rec.feature > b->rec.feature ? 1 :
a->order < b->order ? -1 : a->order > b->order ? 1 :
a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 :
@ -367,7 +367,9 @@ struct feature_event_t {
bool start;
active_feature_t feature;
static int cmp (const feature_event_t *a, const feature_event_t *b) {
static int cmp (const void *pa, const void *pb) {
const feature_event_t *a = (const feature_event_t *) pa;
const feature_event_t *b = (const feature_event_t *) pb;
return a->index < b->index ? -1 : a->index > b->index ? 1 :
a->start < b->start ? -1 : a->start > b->start ? 1 :
active_feature_t::cmp (&a->feature, &b->feature);
@ -1260,6 +1262,8 @@ resize_and_retry:
}
}
buffer->unsafe_to_break_all ();
#undef FAIL
fail:

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

@ -0,0 +1,419 @@
/*
* Copyright © 2017 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_DEBUG_HH
#define HB_DEBUG_HH
#include "hb-private.hh"
#ifndef HB_DEBUG
#define HB_DEBUG 0
#endif
static inline bool
_hb_debug (unsigned int level,
unsigned int max_level)
{
return level < max_level;
}
#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
static inline void
_hb_print_func (const char *func)
{
if (func)
{
unsigned int func_len = strlen (func);
/* Skip "static" */
if (0 == strncmp (func, "static ", 7))
func += 7;
/* Skip "typename" */
if (0 == strncmp (func, "typename ", 9))
func += 9;
/* Skip return type */
const char *space = strchr (func, ' ');
if (space)
func = space + 1;
/* Skip parameter list */
const char *paren = strchr (func, '(');
if (paren)
func_len = paren - func;
fprintf (stderr, "%.*s", func_len, func);
}
}
template <int max_level> static inline void
_hb_debug_msg_va (const char *what,
const void *obj,
const char *func,
bool indented,
unsigned int level,
int level_dir,
const char *message,
va_list ap) HB_PRINTF_FUNC(7, 0);
template <int max_level> static inline void
_hb_debug_msg_va (const char *what,
const void *obj,
const char *func,
bool indented,
unsigned int level,
int level_dir,
const char *message,
va_list ap)
{
if (!_hb_debug (level, max_level))
return;
fprintf (stderr, "%-10s", what ? what : "");
if (obj)
fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
else
fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), "");
if (indented) {
#define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
#define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
#define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
#define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
#define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */
static const char bars[] =
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
fprintf (stderr, "%2u %s" VRBAR "%s",
level,
bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
} else
fprintf (stderr, " " VRBAR LBAR);
_hb_print_func (func);
if (message)
{
fprintf (stderr, ": ");
vfprintf (stderr, message, ap);
}
fprintf (stderr, "\n");
}
template <> inline void
_hb_debug_msg_va<0> (const char *what HB_UNUSED,
const void *obj HB_UNUSED,
const char *func HB_UNUSED,
bool indented HB_UNUSED,
unsigned int level HB_UNUSED,
int level_dir HB_UNUSED,
const char *message HB_UNUSED,
va_list ap HB_UNUSED) {}
template <int max_level> static inline void
_hb_debug_msg (const char *what,
const void *obj,
const char *func,
bool indented,
unsigned int level,
int level_dir,
const char *message,
...) HB_PRINTF_FUNC(7, 8);
template <int max_level> static inline void
_hb_debug_msg (const char *what,
const void *obj,
const char *func,
bool indented,
unsigned int level,
int level_dir,
const char *message,
...)
{
va_list ap;
va_start (ap, message);
_hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
va_end (ap);
}
template <> inline void
_hb_debug_msg<0> (const char *what HB_UNUSED,
const void *obj HB_UNUSED,
const char *func HB_UNUSED,
bool indented HB_UNUSED,
unsigned int level HB_UNUSED,
int level_dir HB_UNUSED,
const char *message HB_UNUSED,
...) HB_PRINTF_FUNC(7, 8);
template <> inline void
_hb_debug_msg<0> (const char *what HB_UNUSED,
const void *obj HB_UNUSED,
const char *func HB_UNUSED,
bool indented HB_UNUSED,
unsigned int level HB_UNUSED,
int level_dir HB_UNUSED,
const char *message 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_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
/*
* Printer
*/
template <typename T>
struct hb_printer_t {
const char *print (const T&) { return "something"; }
};
template <>
struct hb_printer_t<bool> {
const char *print (bool v) { return v ? "true" : "false"; }
};
template <>
struct hb_printer_t<hb_void_t> {
const char *print (hb_void_t) { return ""; }
};
/*
* Trace
*/
template <typename T>
static inline void _hb_warn_no_return (bool returned)
{
if (unlikely (!returned)) {
fprintf (stderr, "OUCH, returned with no call to return_trace(). This is a bug, please report.\n");
}
}
template <>
/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
{}
template <int max_level, typename ret_t>
struct hb_auto_trace_t {
explicit inline hb_auto_trace_t (unsigned int *plevel_,
const char *what_,
const void *obj_,
const char *func,
const char *message,
...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
{
if (plevel) ++*plevel;
va_list ap;
va_start (ap, message);
_hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
va_end (ap);
}
inline ~hb_auto_trace_t (void)
{
_hb_warn_no_return<ret_t> (returned);
if (!returned) {
_hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, " ");
}
if (plevel) --*plevel;
}
inline ret_t ret (ret_t v, unsigned int line = 0)
{
if (unlikely (returned)) {
fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n");
return v;
}
_hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
"return %s (line %d)",
hb_printer_t<ret_t>().print (v), line);
if (plevel) --*plevel;
plevel = nullptr;
returned = true;
return v;
}
private:
unsigned int *plevel;
const char *what;
const void *obj;
bool returned;
};
template <typename ret_t> /* Make sure we don't use hb_auto_trace_t when not tracing. */
struct hb_auto_trace_t<0, ret_t>;
/* For disabled tracing; optimize out everything.
* https://github.com/behdad/harfbuzz/pull/605 */
template <typename ret_t>
struct hb_no_trace_t {
inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
};
#define return_trace(RET) return trace.ret (RET, __LINE__)
/*
* Instances.
*/
#ifndef HB_DEBUG_ARABIC
#define HB_DEBUG_ARABIC (HB_DEBUG+0)
#endif
#ifndef HB_DEBUG_BLOB
#define HB_DEBUG_BLOB (HB_DEBUG+0)
#endif
#ifndef HB_DEBUG_CORETEXT
#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
#endif
#ifndef HB_DEBUG_DIRECTWRITE
#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
#endif
#ifndef HB_DEBUG_FT
#define HB_DEBUG_FT (HB_DEBUG+0)
#endif
#ifndef HB_DEBUG_GET_COVERAGE
#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
#endif
#ifndef HB_DEBUG_OBJECT
#define HB_DEBUG_OBJECT (HB_DEBUG+0)
#endif
#ifndef HB_DEBUG_SHAPE_PLAN
#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
#endif
#ifndef HB_DEBUG_UNISCRIBE
#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
#endif
/*
* With tracing.
*/
#ifndef HB_DEBUG_APPLY
#define HB_DEBUG_APPLY (HB_DEBUG+0)
#endif
#if HB_DEBUG_APPLY
#define TRACE_APPLY(this) \
hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"idx %d gid %u lookup %d", \
c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index)
#else
#define TRACE_APPLY(this) hb_no_trace_t<bool> trace
#endif
#ifndef HB_DEBUG_CLOSURE
#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
#endif
#if HB_DEBUG_CLOSURE
#define TRACE_CLOSURE(this) \
hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"")
#else
#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
#endif
#ifndef HB_DEBUG_COLLECT_GLYPHS
#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
#endif
#if HB_DEBUG_COLLECT_GLYPHS
#define TRACE_COLLECT_GLYPHS(this) \
hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"")
#else
#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
#endif
#ifndef HB_DEBUG_SANITIZE
#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
#endif
#if HB_DEBUG_SANITIZE
#define TRACE_SANITIZE(this) \
hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"");
#else
#define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace
#endif
#ifndef HB_DEBUG_SERIALIZE
#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
#endif
#if HB_DEBUG_SERIALIZE
#define TRACE_SERIALIZE(this) \
hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
"");
#else
#define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
#endif
#ifndef HB_DEBUG_WOULD_APPLY
#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
#endif
#if HB_DEBUG_WOULD_APPLY
#define TRACE_WOULD_APPLY(this) \
hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"%d glyphs", c->len);
#else
#define TRACE_WOULD_APPLY(this) hb_no_trace_t<bool> trace
#endif
#ifndef HB_DEBUG_DISPATCH
#define HB_DEBUG_DISPATCH ( \
HB_DEBUG_APPLY + \
HB_DEBUG_CLOSURE + \
HB_DEBUG_COLLECT_GLYPHS + \
HB_DEBUG_SANITIZE + \
HB_DEBUG_SERIALIZE + \
HB_DEBUG_WOULD_APPLY + \
0)
#endif
#if HB_DEBUG_DISPATCH
#define TRACE_DISPATCH(this, format) \
hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"format %d", (int) format);
#else
#define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace
#endif
#endif /* HB_DEBUG_HH */

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

@ -22,6 +22,8 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include "hb-private.hh"
#include "hb-debug.hh"
#define HB_SHAPER directwrite
#include "hb-shaper-impl-private.hh"
@ -30,10 +32,6 @@
#include "hb-directwrite.h"
#ifndef HB_DEBUG_DIRECTWRITE
#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
#endif
HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, face)
HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, font)
@ -929,8 +927,7 @@ hb_directwrite_shape_experimental_width(hb_font_t *font,
hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer,
features, num_features, width);
if (res)
buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
buffer->unsafe_to_break_all ();
return res;
}

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

@ -0,0 +1,161 @@
/*
* Copyright © 2017 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_DSALGS_HH
#define HB_DSALGS_HH
#include "hb-private.hh"
static inline void *
hb_bsearch_r (const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *_key, const void *_item, void *_arg),
void *arg)
{
int min = 0, max = (int) nmemb - 1;
while (min <= max)
{
int mid = (min + max) / 2;
const void *p = (const void *) (((const char *) base) + (mid * size));
int c = compar (key, p, arg);
if (c < 0)
max = mid - 1;
else if (c > 0)
min = mid + 1;
else
return (void *) p;
}
return NULL;
}
/* From https://github.com/noporpoise/sort_r */
/* Isaac Turner 29 April 2014 Public Domain */
/*
hb_sort_r function to be exported.
Parameters:
base is the array to be sorted
nel is the number of elements in the array
width is the size in bytes of each element of the array
compar is the comparison function
arg is a pointer to be passed to the comparison function
void hb_sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *_a, const void *_b, void *_arg),
void *arg);
*/
/* swap a, b iff a>b */
/* __restrict is same as restrict but better support on old machines */
static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
int (*compar)(const void *_a, const void *_b,
void *_arg),
void *arg)
{
char tmp, *end = a+w;
if(compar(a, b, arg) > 0) {
for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; }
return 1;
}
return 0;
}
/* Note: quicksort is not stable, equivalent values may be swapped */
static inline void sort_r_simple(void *base, size_t nel, size_t w,
int (*compar)(const void *_a, const void *_b,
void *_arg),
void *arg)
{
char *b = (char *)base, *end = b + nel*w;
if(nel < 7) {
/* Insertion sort for arbitrarily small inputs */
char *pi, *pj;
for(pi = b+w; pi < end; pi += w) {
for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
}
}
else
{
/* nel > 6; Quicksort */
/* Use median of first, middle and last items as pivot */
char *x, *y, *xend, ch;
char *pl, *pr;
char *last = b+w*(nel-1), *tmp;
char *l[3];
l[0] = b;
l[1] = b+w*(nel/2);
l[2] = last;
if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
if(compar(l[1],l[2],arg) > 0) {
tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */
if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
}
/* swap l[id], l[2] to put pivot as last element */
for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) {
ch = *x; *x = *y; *y = ch;
}
pl = b;
pr = last;
while(pl < pr) {
for(; pl < pr; pl += w) {
if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
pr -= w; /* pivot now at pl */
break;
}
}
for(; pl < pr; pr -= w) {
if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
pl += w; /* pivot now at pr */
break;
}
}
}
sort_r_simple(b, (pl-b)/w, w, compar, arg);
sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
}
}
static inline void hb_sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *_a, const void *_b, void *_arg),
void *arg)
{
sort_r_simple(base, nel, width, compar, arg);
}
#endif /* HB_DSALGS_HH */

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

@ -143,5 +143,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
if (HB_DIRECTION_IS_BACKWARD (direction))
hb_buffer_reverse (buffer);
buffer->safe_to_break_all ();
return true;
}

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

@ -28,6 +28,7 @@
*/
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-ft.h"
@ -38,12 +39,6 @@
#include FT_TRUETYPE_TABLES_H
#ifndef HB_DEBUG_FT
#define HB_DEBUG_FT (HB_DEBUG+0)
#endif
/* TODO:
*
* In general, this file does a fine job of what it's supposed to do.

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

@ -364,22 +364,44 @@ hb_glib_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
return utf8_decomposed_len;
}
static hb_unicode_funcs_t *static_glib_funcs = nullptr;
#ifdef HB_USE_ATEXIT
static
void free_static_glib_funcs (void)
{
hb_unicode_funcs_destroy (static_glib_funcs);
}
#endif
hb_unicode_funcs_t *
hb_glib_get_unicode_funcs (void)
{
static const hb_unicode_funcs_t _hb_glib_unicode_funcs = {
HB_OBJECT_HEADER_STATIC,
retry:
hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_glib_funcs);
nullptr, /* parent */
true, /* immutable */
{
#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_glib_unicode_##name,
if (unlikely (!funcs))
{
funcs = hb_unicode_funcs_create (nullptr);
#define HB_UNICODE_FUNC_IMPLEMENT(name) \
hb_unicode_funcs_set_##name##_func (funcs, hb_glib_unicode_##name, nullptr, nullptr);
HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_UNICODE_FUNC_IMPLEMENT
hb_unicode_funcs_make_immutable (funcs);
if (!hb_atomic_ptr_cmpexch (&static_glib_funcs, nullptr, funcs)) {
hb_unicode_funcs_destroy (funcs);
goto retry;
}
#ifdef HB_USE_ATEXIT
atexit (free_static_glib_funcs); /* First person registers atexit() callback. */
#endif
};
return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
return hb_unicode_funcs_reference (funcs);
}
#if GLIB_CHECK_VERSION(2,31,10)

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

@ -307,6 +307,8 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
curradv = gr_slot_origin_X(gr_seg_first_slot(seg));
clusters[0].advance = gr_seg_advance_X(seg) - curradv;
}
else
clusters[0].advance = 0;
for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++)
{
unsigned int before = gr_slot_before (is);
@ -332,7 +334,10 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
c->advance = curradv - gr_slot_origin_X(is);
else
clusters[ci].advance = gr_slot_origin_X(is) - curradv;
{
c->advance = 0;
clusters[ci].advance += gr_slot_origin_X(is) - curradv;
}
ci++;
curradv = gr_slot_origin_X(is);
}
@ -345,7 +350,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
clusters[ci].advance += curradv;
else
clusters[ci].advance = gr_seg_advance_X(seg) - curradv;
clusters[ci].advance += gr_seg_advance_X(seg) - curradv;
ci++;
for (unsigned int i = 0; i < ci; ++i)
@ -411,5 +416,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan,
if (feats) gr_featureval_destroy (feats);
gr_seg_destroy (seg);
buffer->unsafe_to_break_all ();
return true;
}

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

@ -345,27 +345,50 @@ hb_icu_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
}
static hb_unicode_funcs_t *static_icu_funcs = nullptr;
#ifdef HB_USE_ATEXIT
static
void free_static_icu_funcs (void)
{
hb_unicode_funcs_destroy (static_icu_funcs);
}
#endif
hb_unicode_funcs_t *
hb_icu_get_unicode_funcs (void)
{
static const hb_unicode_funcs_t _hb_icu_unicode_funcs = {
HB_OBJECT_HEADER_STATIC,
retry:
hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_icu_funcs);
nullptr, /* parent */
true, /* immutable */
{
#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_icu_unicode_##name,
if (unlikely (!funcs))
{
#if U_ICU_VERSION_MAJOR_NUM >= 49
if (!hb_atomic_ptr_get (&normalizer)) {
UErrorCode icu_err = U_ZERO_ERROR;
/* We ignore failure in getNFCInstace(). */
(void) hb_atomic_ptr_cmpexch (&normalizer, nullptr, unorm2_getNFCInstance (&icu_err));
}
#endif
funcs = hb_unicode_funcs_create (nullptr);
#define HB_UNICODE_FUNC_IMPLEMENT(name) \
hb_unicode_funcs_set_##name##_func (funcs, hb_icu_unicode_##name, nullptr, nullptr);
HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_UNICODE_FUNC_IMPLEMENT
hb_unicode_funcs_make_immutable (funcs);
if (!hb_atomic_ptr_cmpexch (&static_icu_funcs, nullptr, funcs)) {
hb_unicode_funcs_destroy (funcs);
goto retry;
}
#ifdef HB_USE_ATEXIT
atexit (free_static_icu_funcs); /* First person registers atexit() callback. */
#endif
};
#if U_ICU_VERSION_MAJOR_NUM >= 49
if (!hb_atomic_ptr_get (&normalizer)) {
UErrorCode icu_err = U_ZERO_ERROR;
/* We ignore failure in getNFCInstace(). */
(void) hb_atomic_ptr_cmpexch (&normalizer, nullptr, unorm2_getNFCInstance (&icu_err));
}
#endif
return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs);
return hb_unicode_funcs_reference (funcs);
}

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

@ -33,18 +33,12 @@
#define HB_OBJECT_PRIVATE_HH
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-atomic-private.hh"
#include "hb-mutex-private.hh"
/* Debug */
#ifndef HB_DEBUG_OBJECT
#define HB_DEBUG_OBJECT (HB_DEBUG+0)
#endif
/* reference_count */
#define HB_REFERENCE_COUNT_INERT_VALUE -1

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

@ -53,6 +53,9 @@ struct TTCHeader;
typedef struct TableRecord
{
int cmp (Tag t) const
{ return t.cmp (tag); }
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -73,10 +76,9 @@ typedef struct OffsetTable
friend struct OpenTypeFontFile;
inline unsigned int get_table_count (void) const
{ return numTables; }
{ return tables.len; }
inline const TableRecord& get_table (unsigned int i) const
{
if (unlikely (i >= numTables)) return Null(TableRecord);
return tables[i];
}
inline unsigned int get_table_tags (unsigned int start_offset,
@ -85,33 +87,28 @@ typedef struct OffsetTable
{
if (table_count)
{
if (start_offset >= numTables)
if (start_offset >= tables.len)
*table_count = 0;
else
*table_count = MIN (*table_count, numTables - start_offset);
*table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
const TableRecord *sub_tables = tables + start_offset;
const TableRecord *sub_tables = tables.array + start_offset;
unsigned int count = *table_count;
for (unsigned int i = 0; i < count; i++)
table_tags[i] = sub_tables[i].tag;
}
return numTables;
return tables.len;
}
inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
{
Tag t;
t.set (tag);
unsigned int count = numTables;
for (unsigned int i = 0; i < count; i++)
{
if (t == tables[i].tag)
{
if (table_index) *table_index = i;
return true;
}
}
if (table_index) *table_index = Index::NOT_FOUND_INDEX;
return false;
/* Linear-search for small tables to work around fonts with unsorted
* table list. */
int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
if (table_index)
*table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i;
return i != -1;
}
inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
{
@ -124,16 +121,13 @@ typedef struct OffsetTable
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables));
return_trace (c->check_struct (this) && tables.sanitize (c));
}
protected:
Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
USHORT numTables; /* Number of tables. */
USHORT searchRangeZ; /* (Maximum power of 2 <= numTables) x 16 */
USHORT entrySelectorZ; /* Log2(maximum power of 2 <= numTables). */
USHORT rangeShiftZ; /* NumTables x 16-searchRange. */
TableRecord tables[VAR]; /* TableRecord entries. numTables items */
BinSearchArrayOf<TableRecord>
tables;
public:
DEFINE_SIZE_ARRAY (12, tables);
} OpenTypeFontFace;

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

@ -30,6 +30,7 @@
#define HB_OPEN_TYPE_PRIVATE_HH
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-face-private.hh"
@ -130,14 +131,16 @@ static inline Type& StructAfter(TObject &X)
*/
/* Global nul-content Null pool. Enlarge as necessary. */
/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
static const void *_NullPool[(256+8) / sizeof (void *)];
#define HB_NULL_POOL_SIZE 264
static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
extern HB_INTERNAL const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)];
/* Generic nul-content Null objects. */
template <typename Type>
static inline const Type& Null (void) {
static_assert ((sizeof (Type) <= sizeof (_NullPool)), "");
return *CastP<Type> (_NullPool);
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
return *CastP<Type> (_hb_NullPool);
}
/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
@ -172,16 +175,6 @@ struct hb_dispatch_context_t
* Sanitize
*/
#ifndef HB_DEBUG_SANITIZE
#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
#endif
#define TRACE_SANITIZE(this) \
hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"");
/* This limits sanitizing time on really broken fonts. */
#ifndef HB_SANITIZE_MAX_EDITS
#define HB_SANITIZE_MAX_EDITS 32
@ -385,16 +378,6 @@ struct Sanitizer
* Serialize
*/
#ifndef HB_DEBUG_SERIALIZE
#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
#endif
#define TRACE_SERIALIZE(this) \
hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
"");
struct hb_serialize_context_t
{
@ -632,10 +615,11 @@ struct IntType
inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
inline int cmp (Type a) const
template <typename Type2>
inline int cmp (Type2 a) const
{
Type b = v;
if (sizeof (Type) < sizeof (int))
if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
return (int) a - (int) b;
else
return a < b ? -1 : a == b ? 0 : +1;
@ -651,9 +635,9 @@ struct IntType
DEFINE_SIZE_STATIC (Size);
};
typedef IntType<int8_t , 1> CHAR; /* 8-bit signed integer. */
typedef IntType<uint8_t , 1> BYTE; /* 8-bit unsigned integer. */
typedef IntType<int8_t , 1> INT8; /* 8-bit signed integer. */
typedef IntType<int8_t, 1> CHAR; /* 8-bit signed integer. */
typedef IntType<uint8_t, 1> BYTE; /* 8-bit unsigned integer. */
typedef IntType<int8_t, 1> INT8; /* 8-bit signed integer. */
typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */
typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */
typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */
@ -713,10 +697,7 @@ struct Tag : ULONG
DEFINE_NULL_DATA (Tag, " ");
/* Glyph index number, same as uint16 (length = 16 bits) */
struct GlyphID : USHORT {
static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); }
inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; }
};
typedef USHORT GlyphID;
/* Script/language-system/feature index */
struct Index : USHORT {
@ -943,7 +924,7 @@ struct ArrayOf
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len));
return_trace (len.sanitize (c) && c->check_array (array, Type::static_size, len));
}
public:
@ -1009,12 +990,6 @@ struct HeadlessArrayOf
return_trace (true);
}
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
return c->check_struct (this)
&& c->check_array (this, Type::static_size, len);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -1032,6 +1007,15 @@ struct HeadlessArrayOf
return_trace (true);
}
private:
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (len.sanitize (c) &&
(!len || c->check_array (array, Type::static_size, len - 1)));
}
public:
LenType len;
Type array[VAR];
public:
@ -1039,7 +1023,9 @@ struct HeadlessArrayOf
};
/* An array with sorted elements. Supports binary searching. */
/*
* An array with sorted elements. Supports binary searching.
*/
template <typename Type, typename LenType=USHORT>
struct SortedArrayOf : ArrayOf<Type, LenType>
{
@ -1064,6 +1050,33 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
}
};
/*
* Binary-search arrays
*/
struct BinSearchHeader
{
inline operator uint32_t (void) const { return len; }
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
protected:
USHORT len;
USHORT searchRangeZ;
USHORT entrySelectorZ;
USHORT rangeShiftZ;
public:
DEFINE_SIZE_STATIC (8);
};
template <typename Type>
struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
/* Lazy struct and blob loaders. */

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

@ -36,9 +36,10 @@
#include "hb-ot-head-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-kern-table.hh"
#include "hb-ot-os2-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-ot-post-table.hh"
#include "hb-ot-var-hvar-table.hh"
struct hb_ot_face_metrics_accelerator_t
@ -304,25 +305,24 @@ struct hb_ot_face_cbdt_accelerator_t
struct hb_ot_face_post_accelerator_t
{
hb_blob_t *post_blob;
unsigned int post_len;
const OT::post *post;
OT::post::accelerator_t accel;
inline void init (hb_face_t *face)
{
this->post_blob = OT::Sanitizer<OT::post>::sanitize (face->reference_table (HB_OT_TAG_post));
this->post = OT::Sanitizer<OT::post>::lock_instance (this->post_blob);
this->post_len = hb_blob_get_length (this->post_blob);
hb_blob_t *blob = this->post_blob = OT::Sanitizer<OT::post>::sanitize (face->reference_table (HB_OT_TAG_post));
accel.init (OT::Sanitizer<OT::post>::lock_instance (blob), hb_blob_get_length (blob));
}
inline void fini (void)
{
accel.fini ();
hb_blob_destroy (this->post_blob);
}
inline bool get_glyph_name (hb_codepoint_t glyph,
char *name, unsigned int size) const
{
return this->post->get_glyph_name (glyph, name, size, this->post_len);
return this->accel.get_glyph_name (glyph, name, size);
}
inline bool get_glyph_from_name (const char *name, int len,
@ -331,10 +331,31 @@ struct hb_ot_face_post_accelerator_t
if (unlikely (!len))
return false;
return this->post->get_glyph_from_name (name, len, glyph, this->post_len);
return this->accel.get_glyph_from_name (name, len, glyph);
}
};
struct hb_ot_face_kern_accelerator_t
{
hb_blob_t *kern_blob;
OT::kern::accelerator_t accel;
inline void init (hb_face_t *face)
{
hb_blob_t *blob = this->kern_blob = OT::Sanitizer<OT::kern>::sanitize (face->reference_table (HB_OT_TAG_kern));
accel.init (OT::Sanitizer<OT::kern>::lock_instance (blob), hb_blob_get_length (blob));
}
inline void fini (void)
{
accel.fini ();
hb_blob_destroy (this->kern_blob);
}
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{ return accel.get_h_kerning (left, right); }
};
typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph);
@ -471,6 +492,7 @@ struct hb_ot_font_t
OT::hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf;
OT::hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt;
OT::hb_lazy_loader_t<hb_ot_face_post_accelerator_t> post;
OT::hb_lazy_loader_t<hb_ot_face_kern_accelerator_t> kern;
};
@ -489,6 +511,7 @@ _hb_ot_font_create (hb_face_t *face)
ot_font->glyf.init (face);
ot_font->cbdt.init (face);
ot_font->post.init (face);
ot_font->kern.init (face);
return ot_font;
}
@ -504,6 +527,7 @@ _hb_ot_font_destroy (void *data)
ot_font->glyf.fini ();
ot_font->cbdt.fini ();
ot_font->post.fini ();
ot_font->kern.fini ();
free (ot_font);
}
@ -553,6 +577,17 @@ hb_ot_get_glyph_v_advance (hb_font_t *font,
return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font));
}
static hb_position_t
hb_ot_get_glyph_h_kerning (hb_font_t *font,
void *font_data,
hb_codepoint_t left_glyph,
hb_codepoint_t right_glyph,
void *user_data HB_UNUSED)
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph));
}
static hb_bool_t
hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
void *font_data,
@ -650,7 +685,7 @@ retry:
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr);
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
//hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
//hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr); TODO
hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr);
//hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr);
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
//hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); TODO

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

@ -0,0 +1,389 @@
/*
* Copyright © 2017 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_OT_KERN_TABLE_HH
#define HB_OT_KERN_TABLE_HH
#include "hb-open-type-private.hh"
namespace OT {
/*
* kern -- Kerning
*/
#define HB_OT_TAG_kern HB_TAG('k','e','r','n')
struct hb_glyph_pair_t
{
hb_codepoint_t left;
hb_codepoint_t right;
};
struct KernPair
{
inline int get_kerning (void) const
{ return value; }
inline int cmp (const hb_glyph_pair_t &o) const
{
int ret = left.cmp (o.left);
if (ret) return ret;
return right.cmp (o.right);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
protected:
GlyphID left;
GlyphID right;
FWORD value;
public:
DEFINE_SIZE_STATIC (6);
};
struct KernSubTableFormat0
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{
hb_glyph_pair_t pair = {left, right};
int i = pairs.bsearch (pair);
if (i == -1)
return 0;
return pairs[i].get_kerning ();
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (pairs.sanitize (c));
}
protected:
BinSearchArrayOf<KernPair> pairs; /* Array of kerning pairs. */
public:
DEFINE_SIZE_ARRAY (8, pairs);
};
struct KernClassTable
{
inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
}
protected:
USHORT firstGlyph; /* First glyph in class range. */
ArrayOf<USHORT> classes; /* Glyph classes. */
public:
DEFINE_SIZE_ARRAY (4, classes);
};
struct KernSubTableFormat2
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
{
unsigned int l = (this+leftClassTable).get_class (left);
unsigned int r = (this+leftClassTable).get_class (left);
unsigned int offset = l * rowWidth + r * sizeof (FWORD);
const FWORD *arr = &(this+array);
if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
return 0;
const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
return 0;
return *v;
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (rowWidth.sanitize (c) &&
leftClassTable.sanitize (c, this) &&
rightClassTable.sanitize (c, this) &&
array.sanitize (c, this));
}
protected:
USHORT rowWidth; /* The width, in bytes, of a row in the table. */
OffsetTo<KernClassTable>
leftClassTable; /* Offset from beginning of this subtable to
* left-hand class table. */
OffsetTo<KernClassTable>
rightClassTable;/* Offset from beginning of this subtable to
* right-hand class table. */
OffsetTo<FWORD>
array; /* Offset from beginning of this subtable to
* the start of the kerning array. */
public:
DEFINE_SIZE_MIN (8);
};
struct KernSubTable
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const
{
switch (format) {
case 0: return u.format0.get_kerning (left, right);
case 2: return u.format2.get_kerning (left, right, end);
default:return 0;
}
}
inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const
{
TRACE_SANITIZE (this);
switch (format) {
case 0: return_trace (u.format0.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
default:return_trace (true);
}
}
protected:
union {
KernSubTableFormat0 format0;
KernSubTableFormat2 format2;
} u;
public:
DEFINE_SIZE_MIN (0);
};
template <typename T>
struct KernSubTableWrapper
{
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
inline const T* thiz (void) const { return static_cast<const T *> (this); }
inline bool is_horizontal (void) const
{ return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; }
inline bool is_override (void) const
{ return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); }
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
{ return thiz()->subtable.get_kerning (left, right, end, thiz()->format); }
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
{ return is_horizontal () ? get_kerning (left, right, end) : 0; }
inline unsigned int get_size (void) const { return thiz()->length; }
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (thiz()) &&
thiz()->length >= thiz()->min_size &&
c->check_array (thiz(), 1, thiz()->length) &&
thiz()->subtable.sanitize (c, thiz()->format));
}
};
template <typename T>
struct KernTable
{
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
inline const T* thiz (void) const { return static_cast<const T *> (this); }
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
{
int v = 0;
const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
unsigned int count = thiz()->nTables;
for (unsigned int i = 0; i < count; i++)
{
if (st->is_override ())
v = 0;
v += st->get_h_kerning (left, right, table_length + (const char *) this);
st = &StructAfter<typename T::SubTableWrapper> (*st);
}
return v;
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (thiz()) ||
thiz()->version != T::VERSION))
return_trace (false);
const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
unsigned int count = thiz()->nTables;
for (unsigned int i = 0; i < count; i++)
{
if (unlikely (!st->sanitize (c)))
return_trace (false);
st = &StructAfter<typename T::SubTableWrapper> (*st);
}
return_trace (true);
}
};
struct KernOT : KernTable<KernOT>
{
friend struct KernTable<KernOT>;
static const uint16_t VERSION = 0x0000u;
struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
{
friend struct KernSubTableWrapper<SubTableWrapper>;
enum coverage_flags_t {
COVERAGE_DIRECTION_FLAG = 0x01u,
COVERAGE_MINIMUM_FLAG = 0x02u,
COVERAGE_CROSSSTREAM_FLAG = 0x04u,
COVERAGE_OVERRIDE_FLAG = 0x08u,
COVERAGE_VARIATION_FLAG = 0x00u, /* Not supported. */
COVERAGE_CHECK_FLAGS = 0x07u,
COVERAGE_CHECK_HORIZONTAL = 0x01u
};
protected:
USHORT versionZ; /* Unused. */
USHORT length; /* Length of the subtable (including this header). */
BYTE format; /* Subtable format. */
BYTE coverage; /* Coverage bits. */
KernSubTable subtable; /* Subtable data. */
public:
DEFINE_SIZE_MIN (6);
};
protected:
USHORT version; /* Version--0x0000u */
USHORT nTables; /* Number of subtables in the kerning table. */
BYTE data[VAR];
public:
DEFINE_SIZE_ARRAY (4, data);
};
struct KernAAT : KernTable<KernAAT>
{
friend struct KernTable<KernAAT>;
static const uint32_t VERSION = 0x00010000u;
struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
{
friend struct KernSubTableWrapper<SubTableWrapper>;
enum coverage_flags_t {
COVERAGE_DIRECTION_FLAG = 0x80u,
COVERAGE_CROSSSTREAM_FLAG = 0x40u,
COVERAGE_VARIATION_FLAG = 0x20u,
COVERAGE_OVERRIDE_FLAG = 0x00u, /* Not supported. */
COVERAGE_CHECK_FLAGS = 0xE0u,
COVERAGE_CHECK_HORIZONTAL = 0x00u
};
protected:
ULONG length; /* Length of the subtable (including this header). */
BYTE coverage; /* Coverage bits. */
BYTE format; /* Subtable format. */
USHORT tupleIndex; /* The tuple index (used for variations fonts).
* This value specifies which tuple this subtable covers. */
KernSubTable subtable; /* Subtable data. */
public:
DEFINE_SIZE_MIN (8);
};
protected:
ULONG version; /* Version--0x00010000u */
ULONG nTables; /* Number of subtables in the kerning table. */
BYTE data[VAR];
public:
DEFINE_SIZE_ARRAY (8, data);
};
struct kern
{
static const hb_tag_t tableTag = HB_OT_TAG_kern;
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
{
switch (u.major) {
case 0: return u.ot.get_h_kerning (left, right, table_length);
case 1: return u.aat.get_h_kerning (left, right, table_length);
default:return 0;
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!u.major.sanitize (c)) return_trace (false);
switch (u.major) {
case 0: return_trace (u.ot.sanitize (c));
case 1: return_trace (u.aat.sanitize (c));
default:return_trace (true);
}
}
struct accelerator_t
{
inline void init (const kern *table_, unsigned int table_length_)
{
table = table_;
table_length = table_length_;
}
inline void fini (void) {}
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{ return table->get_h_kerning (left, right, table_length); }
private:
const kern *table;
unsigned int table_length;
};
protected:
union {
USHORT major;
KernOT ot;
KernAAT aat;
} u;
public:
DEFINE_SIZE_UNION (2, major);
};
} /* namespace OT */
#endif /* HB_OT_KERN_TABLE_HH */

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

@ -29,6 +29,8 @@
#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-ot-layout-private.hh"
#include "hb-open-type-private.hh"
#include "hb-set-private.hh"
@ -45,12 +47,6 @@
namespace OT {
#define TRACE_DISPATCH(this, format) \
hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"format %d", (int) format);
#define NOT_COVERED ((unsigned int) -1)

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

@ -29,6 +29,8 @@
#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-buffer-private.hh"
#include "hb-ot-layout-gdef-table.hh"
#include "hb-set-private.hh"
@ -37,15 +39,6 @@
namespace OT {
#ifndef HB_DEBUG_CLOSURE
#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
#endif
#define TRACE_CLOSURE(this) \
hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"");
struct hb_closure_context_t :
hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
{
@ -85,16 +78,6 @@ struct hb_closure_context_t :
};
#ifndef HB_DEBUG_WOULD_APPLY
#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
#endif
#define TRACE_WOULD_APPLY(this) \
hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"%d glyphs", c->len);
struct hb_would_apply_context_t :
hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
{
@ -122,16 +105,6 @@ struct hb_would_apply_context_t :
};
#ifndef HB_DEBUG_COLLECT_GLYPHS
#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
#endif
#define TRACE_COLLECT_GLYPHS(this) \
hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"");
struct hb_collect_glyphs_context_t :
hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
{
@ -219,10 +192,6 @@ struct hb_collect_glyphs_context_t :
#ifndef HB_DEBUG_GET_COVERAGE
#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
#endif
/* XXX Can we remove this? */
template <typename set_t>
@ -249,17 +218,6 @@ struct hb_add_coverage_context_t :
};
#ifndef HB_DEBUG_APPLY
#define HB_DEBUG_APPLY (HB_DEBUG+0)
#endif
#define TRACE_APPLY(this) \
hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"idx %d gid %u lookup %d", \
c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index);
struct hb_apply_context_t :
hb_dispatch_context_t<hb_apply_context_t, bool, HB_DEBUG_APPLY>
{
@ -1247,11 +1205,11 @@ struct Rule
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return inputCount.sanitize (c)
&& lookupCount.sanitize (c)
&& c->check_range (inputZ,
inputZ[0].static_size * inputCount
+ lookupRecordX[0].static_size * lookupCount);
return_trace (inputCount.sanitize (c) &&
lookupCount.sanitize (c) &&
c->check_range (inputZ,
inputZ[0].static_size * inputCount +
lookupRecordX[0].static_size * lookupCount));
}
protected:

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

@ -35,10 +35,14 @@
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
#include "hb-ot-name-table.hh" // Just so we compile it; unused otherwise.
#include "hb-ot-map-private.hh"
const void * const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
hb_ot_layout_t *
_hb_ot_layout_create (hb_face_t *face)
{

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

@ -63,8 +63,12 @@ struct hb_ot_map_t
unsigned short auto_zwj : 1;
hb_mask_t mask;
static int cmp (const lookup_map_t *a, const lookup_map_t *b)
{ return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; }
static int cmp (const void *pa, const void *pb)
{
const lookup_map_t *a = (const lookup_map_t *) pa;
const lookup_map_t *b = (const lookup_map_t *) pb;
return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
}
};
typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
@ -210,9 +214,13 @@ struct hb_ot_map_builder_t
unsigned int default_value; /* for non-global features, what should the unset glyphs take */
unsigned int stage[2]; /* GSUB/GPOS */
static int cmp (const feature_info_t *a, const feature_info_t *b)
{ return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) :
(a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); }
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;
return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) :
(a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
}
};
struct stage_info_t {

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

@ -42,8 +42,10 @@ namespace OT {
struct NameRecord
{
static int cmp (const NameRecord *a, const NameRecord *b)
static int cmp (const void *pa, const void *pb)
{
const NameRecord *a = (const NameRecord *) pa;
const NameRecord *b = (const NameRecord *) pb;
int ret;
ret = b->platformID.cmp (a->platformID);
if (ret) return ret;
@ -89,7 +91,7 @@ struct name
key.encodingID.set (encoding_id);
key.languageID.set (language_id);
key.nameID.set (name_id);
NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), (hb_compare_func_t) NameRecord::cmp);
NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), NameRecord::cmp);
if (!match)
return 0;

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

@ -0,0 +1,294 @@
/*
* Copyright © 2017 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_OT_POST_MACROMAN_HH
#if 0 /* Make checks happy. */
#define HB_OT_POST_MACROMAN_HH
#include "hb-private.hh"
#endif
_S(".notdef")
_S(".null")
_S("nonmarkingreturn")
_S("space")
_S("exclam")
_S("quotedbl")
_S("numbersign")
_S("dollar")
_S("percent")
_S("ampersand")
_S("quotesingle")
_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("grave")
_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("Adieresis")
_S("Aring")
_S("Ccedilla")
_S("Eacute")
_S("Ntilde")
_S("Odieresis")
_S("Udieresis")
_S("aacute")
_S("agrave")
_S("acircumflex")
_S("adieresis")
_S("atilde")
_S("aring")
_S("ccedilla")
_S("eacute")
_S("egrave")
_S("ecircumflex")
_S("edieresis")
_S("iacute")
_S("igrave")
_S("icircumflex")
_S("idieresis")
_S("ntilde")
_S("oacute")
_S("ograve")
_S("ocircumflex")
_S("odieresis")
_S("otilde")
_S("uacute")
_S("ugrave")
_S("ucircumflex")
_S("udieresis")
_S("dagger")
_S("degree")
_S("cent")
_S("sterling")
_S("section")
_S("bullet")
_S("paragraph")
_S("germandbls")
_S("registered")
_S("copyright")
_S("trademark")
_S("acute")
_S("dieresis")
_S("notequal")
_S("AE")
_S("Oslash")
_S("infinity")
_S("plusminus")
_S("lessequal")
_S("greaterequal")
_S("yen")
_S("mu")
_S("partialdiff")
_S("summation")
_S("product")
_S("pi")
_S("integral")
_S("ordfeminine")
_S("ordmasculine")
_S("Omega")
_S("ae")
_S("oslash")
_S("questiondown")
_S("exclamdown")
_S("logicalnot")
_S("radical")
_S("florin")
_S("approxequal")
_S("Delta")
_S("guillemotleft")
_S("guillemotright")
_S("ellipsis")
_S("nonbreakingspace")
_S("Agrave")
_S("Atilde")
_S("Otilde")
_S("OE")
_S("oe")
_S("endash")
_S("emdash")
_S("quotedblleft")
_S("quotedblright")
_S("quoteleft")
_S("quoteright")
_S("divide")
_S("lozenge")
_S("ydieresis")
_S("Ydieresis")
_S("fraction")
_S("currency")
_S("guilsinglleft")
_S("guilsinglright")
_S("fi")
_S("fl")
_S("daggerdbl")
_S("periodcentered")
_S("quotesinglbase")
_S("quotedblbase")
_S("perthousand")
_S("Acircumflex")
_S("Ecircumflex")
_S("Aacute")
_S("Edieresis")
_S("Egrave")
_S("Iacute")
_S("Icircumflex")
_S("Idieresis")
_S("Igrave")
_S("Oacute")
_S("Ocircumflex")
_S("apple")
_S("Ograve")
_S("Uacute")
_S("Ucircumflex")
_S("Ugrave")
_S("dotlessi")
_S("circumflex")
_S("tilde")
_S("macron")
_S("breve")
_S("dotaccent")
_S("ring")
_S("cedilla")
_S("hungarumlaut")
_S("ogonek")
_S("caron")
_S("Lslash")
_S("lslash")
_S("Scaron")
_S("scaron")
_S("Zcaron")
_S("zcaron")
_S("brokenbar")
_S("Eth")
_S("eth")
_S("Yacute")
_S("yacute")
_S("Thorn")
_S("thorn")
_S("minus")
_S("multiply")
_S("onesuperior")
_S("twosuperior")
_S("threesuperior")
_S("onehalf")
_S("onequarter")
_S("threequarters")
_S("franc")
_S("Gbreve")
_S("gbreve")
_S("Idotaccent")
_S("Scedilla")
_S("scedilla")
_S("Cacute")
_S("cacute")
_S("Ccaron")
_S("ccaron")
_S("dcroat")
#endif /* HB_OT_POST_MACROMAN_HH */

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

@ -28,50 +28,16 @@
#define HB_OT_POST_TABLE_HH
#include "hb-open-type-private.hh"
#include "hb-dsalgs.hh"
#define HB_STRING_ARRAY_NAME format1_names
#define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
#include "hb-string-array.hh"
#undef HB_STRING_ARRAY_LIST
#undef HB_STRING_ARRAY_NAME
#define NUM_FORMAT1_NAMES 258
static const char* const format1_names[NUM_FORMAT1_NAMES] =
{
".notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl",
"numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft",
"parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
"nine", "colon", "semicolon", "less", "equal", "greater", "question", "at",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft",
"backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b",
"c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
"r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar",
"braceright", "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute",
"Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex",
"adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave",
"ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
"ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute",
"ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling",
"section", "bullet", "paragraph", "germandbls", "registered", "copyright",
"trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity",
"plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff",
"summation", "product", "pi", "integral", "ordfeminine", "ordmasculine",
"Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
"radical", "florin", "approxequal", "Delta", "guillemotleft",
"guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
"Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright",
"quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis",
"fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl",
"daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase",
"perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave",
"Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
"apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
"circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla",
"hungarumlaut", "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron",
"Zcaron", "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn",
"thorn", "minus", "multiply", "onesuperior", "twosuperior", "threesuperior",
"onehalf", "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
"Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", "Ccaron", "ccaron",
"dcroat",
};
namespace OT {
@ -87,13 +53,10 @@ struct postV2Tail
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (numberOfGlyphs.sanitize (c) &&
c->check_array (glyphNameIndex, sizeof (USHORT), numberOfGlyphs));
return_trace (glyphNameIndex.sanitize (c));
}
USHORT numberOfGlyphs; /* Number of glyphs (this should be the
* same as numGlyphs in 'maxp' table). */
USHORT glyphNameIndex[VAR]; /* This is not an offset, but is the
ArrayOf<USHORT>glyphNameIndex; /* This is not an offset, but is the
* ordinal number of the glyph in 'post'
* string tables. */
BYTE namesX[VAR]; /* Glyph names with length bytes [variable]
@ -119,134 +82,157 @@ struct post
return_trace (true);
}
inline bool get_glyph_name (hb_codepoint_t glyph,
char *buffer, unsigned int buffer_length,
unsigned int blob_len) const
struct accelerator_t
{
if (version.to_int () == 0x00010000)
inline void init (const post *table, unsigned int post_len)
{
if (glyph >= NUM_FORMAT1_NAMES)
return false;
version = table->version.to_int ();
index_to_offset.init ();
if (version != 0x00020000)
return;
if (!buffer_length)
const postV2Tail &v2 = StructAfter<postV2Tail> (*table);
glyphNameIndex = &v2.glyphNameIndex;
pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
const uint8_t *end = (uint8_t *) table + post_len;
for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data)
{
uint32_t *offset = index_to_offset.push ();
if (unlikely (!offset))
break;
*offset = data - pool;
}
}
inline void fini (void)
{
index_to_offset.finish ();
free (gids_sorted_by_name);
}
inline bool get_glyph_name (hb_codepoint_t glyph,
char *buf, unsigned int buf_len) const
{
hb_string_t s = find_glyph_name (glyph);
if (!s.len)
return false;
if (!buf_len)
return true;
strncpy (buffer, format1_names[glyph], buffer_length);
buffer[buffer_length - 1] = '\0';
if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
return false;
strncpy (buf, s.bytes, s.len);
buf[s.len] = '\0';
return true;
}
if (version.to_int () == 0x00020000)
inline bool get_glyph_from_name (const char *name, int len,
hb_codepoint_t *glyph) const
{
const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
unsigned int count = get_glyph_count ();
if (unlikely (!count))
return false;
if (glyph >= v2.numberOfGlyphs)
if (len < 0)
len = strlen (name);
if (unlikely (!len))
return false;
if (!buffer_length)
return true;
retry:
uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name);
unsigned int index = v2.glyphNameIndex[glyph];
if (index < NUM_FORMAT1_NAMES)
if (unlikely (!gids))
{
if (!buffer_length)
return true;
strncpy (buffer, format1_names[index], buffer_length);
buffer[buffer_length - 1] = '\0';
gids = (uint16_t *) malloc (count * sizeof (gids[0]));
if (unlikely (!gids))
return false; /* Anything better?! */
for (unsigned int i = 0; i < count; i++)
gids[i] = i;
hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) {
free (gids);
goto retry;
}
}
hb_string_t st (name, len);
const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
if (gid)
{
*glyph = *gid;
return true;
}
return false;
}
protected:
inline unsigned int get_glyph_count (void) const
{
if (version == 0x00010000)
return NUM_FORMAT1_NAMES;
if (version == 0x00020000)
return glyphNameIndex->len;
return 0;
}
static inline int cmp_gids (const void *pa, const void *pb, void *arg)
{
const accelerator_t *thiz = (const accelerator_t *) arg;
uint16_t a = * (const uint16_t *) pa;
uint16_t b = * (const uint16_t *) pb;
return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a));
}
static inline int cmp_key (const void *pk, const void *po, void *arg)
{
const accelerator_t *thiz = (const accelerator_t *) arg;
const hb_string_t *key = (const hb_string_t *) pk;
uint16_t o = * (const uint16_t *) po;
return thiz->find_glyph_name (o).cmp (*key);
}
inline hb_string_t find_glyph_name (hb_codepoint_t glyph) const
{
if (version == 0x00010000)
{
if (glyph >= NUM_FORMAT1_NAMES)
return hb_string_t ();
return format1_names (glyph);
}
if (version != 0x00020000 || glyph >= glyphNameIndex->len)
return hb_string_t ();
unsigned int index = glyphNameIndex->array[glyph];
if (index < NUM_FORMAT1_NAMES)
return format1_names (index);
index -= NUM_FORMAT1_NAMES;
unsigned int offset = min_size + v2.min_size + 2 * v2.numberOfGlyphs;
unsigned char *data = (unsigned char *) this + offset;
unsigned char *end = (unsigned char *) this + blob_len;
for (unsigned int i = 0; data < end; i++)
{
unsigned int name_length = data[0];
data++;
if (i == index)
{
if (unlikely (!name_length))
return false;
if (index >= index_to_offset.len)
return hb_string_t ();
unsigned int offset = index_to_offset.array[index];
unsigned int remaining = end - data;
name_length = MIN (name_length, buffer_length - 1);
name_length = MIN (name_length, remaining);
memcpy (buffer, data, name_length);
buffer[name_length] = '\0';
return true;
}
data += name_length;
}
const uint8_t *data = pool + offset;
unsigned int name_length = *data;
data++;
return false;
return hb_string_t ((const char *) data, name_length);
}
return false;
}
inline bool get_glyph_from_name (const char *name, int len,
hb_codepoint_t *glyph,
unsigned int blob_len) const
{
if (len < 0)
len = strlen (name);
if (version.to_int () == 0x00010000)
{
for (int i = 0; i < NUM_FORMAT1_NAMES; i++)
{
if (strncmp (name, format1_names[i], len) == 0 && format1_names[i][len] == '\0')
{
*glyph = i;
return true;
}
}
return false;
}
if (version.to_int () == 0x00020000)
{
const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
unsigned int offset = min_size + v2.min_size + 2 * v2.numberOfGlyphs;
char* data = (char*) this + offset;
/* XXX The following code is wrong. */
return false;
for (hb_codepoint_t gid = 0; gid < v2.numberOfGlyphs; gid++)
{
unsigned int index = v2.glyphNameIndex[gid];
if (index < NUM_FORMAT1_NAMES)
{
if (strncmp (name, format1_names[index], len) == 0 && format1_names[index][len] == '\0')
{
*glyph = gid;
return true;
}
continue;
}
index -= NUM_FORMAT1_NAMES;
for (unsigned int i = 0; data < (char*) this + blob_len; i++)
{
unsigned int name_length = data[0];
unsigned int remaining = (char*) this + blob_len - data - 1;
name_length = MIN (name_length, remaining);
if (name_length == (unsigned int) len && strncmp (name, data + 1, len) == 0)
{
*glyph = gid;
return true;
}
data += name_length + 1;
}
return false;
}
return false;
}
return false;
}
uint32_t version;
const ArrayOf<USHORT> *glyphNameIndex;
hb_prealloced_array_t<uint32_t, 1> index_to_offset;
const uint8_t *pool;
mutable uint16_t *gids_sorted_by_name;
};
public:
FixedVersion<>version; /* 0x00010000 for version 1.0

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

@ -24,15 +24,12 @@
* Google Author(s): Behdad Esfahbod
*/
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-ot-shape-complex-arabic-private.hh"
#include "hb-ot-shape-private.hh"
#ifndef HB_DEBUG_ARABIC
#define HB_DEBUG_ARABIC (HB_DEBUG+0)
#endif
/* buffer var allocations */
#define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */
@ -563,6 +560,7 @@ apply_stch (const hb_ot_shape_plan_t *plan,
}
else
{
buffer->unsafe_to_break (context, end);
hb_position_t x_offset = 0;
for (unsigned int k = end; k > start; k--)
{
@ -689,7 +687,6 @@ reorder_marks_arabic (const hb_ot_shape_plan_t *plan,
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
{
"arabic",
collect_features_arabic,
nullptr, /* override_features */
data_create_arabic,

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

@ -29,7 +29,6 @@
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
{
"default",
nullptr, /* collect_features */
nullptr, /* override_features */
nullptr, /* data_create */

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

@ -414,7 +414,6 @@ setup_masks_hangul (const hb_ot_shape_plan_t *plan,
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
{
"hangul",
collect_features_hangul,
override_features_hangul,
data_create_hangul,

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

@ -169,7 +169,6 @@ disable_otl_hebrew (const hb_ot_shape_plan_t *plan)
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
{
"hebrew",
nullptr, /* collect_features */
nullptr, /* override_features */
nullptr, /* data_create */

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

@ -217,7 +217,7 @@ set_indic_properties (hb_glyph_info_t &info)
/* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
* so the Indic shaper needs to know their categories. */
else if (unlikely (u == 0x11303u)) cat = OT_SM;
else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
else if (unlikely (u == 0x1133cu)) cat = OT_N;
else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/behdad/harfbuzz/issues/552 */
@ -508,7 +508,7 @@ struct indic_shape_plan_t
/* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
* during shape planning... Instead, overwrite it here. It's safe. Don't worry! */
(const_cast<indic_shape_plan_t *> (this))->virama_glyph = glyph;
virama_glyph = glyph;
}
*pglyph = glyph;
@ -518,7 +518,7 @@ struct indic_shape_plan_t
const indic_config_t *config;
bool is_old_spec;
hb_codepoint_t virama_glyph;
mutable hb_codepoint_t virama_glyph;
would_substitute_feature_t rphf;
would_substitute_feature_t pref;
@ -692,7 +692,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
hb_glyph_info_t *info = buffer->info;
/* https://github.com/behdad/harfbuzz/issues/435#issuecomment-335560167
* // For compatibility with legacy useage in Kannada,
* // For compatibility with legacy usage in Kannada,
* // Ra+h+ZWJ must behave like Ra+ZWJ+h...
*/
if (buffer->props.script == HB_SCRIPT_KANNADA &&
@ -1686,11 +1686,15 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
/* Apply 'init' to the Left Matra if it's a word start. */
if (info[start].indic_position () == POS_PRE_M &&
(!start ||
!(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) &
FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))))
info[start].mask |= indic_plan->mask_array[INIT];
if (info[start].indic_position () == POS_PRE_M)
{
if (!start ||
!(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) &
FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
info[start].mask |= indic_plan->mask_array[INIT];
else
buffer->unsafe_to_break (start - 1, start + 1);
}
/*
@ -1843,7 +1847,6 @@ compose_indic (const hb_ot_shape_normalize_context_t *c,
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
{
"indic",
collect_features_indic,
override_features_indic,
data_create_indic,

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

@ -512,7 +512,6 @@ final_reordering (const hb_ot_shape_plan_t *plan,
* generic shaper, except that it zeros mark advances GDEF_LATE. */
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
{
"default",
nullptr, /* collect_features */
nullptr, /* override_features */
nullptr, /* data_create */
@ -531,7 +530,6 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
{
"myanmar",
collect_features_myanmar,
override_features_myanmar,
nullptr, /* data_create */

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

@ -65,8 +65,6 @@ enum hb_ot_shape_zero_width_marks_type_t {
struct hb_ot_complex_shaper_t
{
char name[8];
/* collect_features()
* Called during shape_plan().
* Shapers should use plan->map to add their features and callbacks.

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

@ -366,7 +366,6 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
{
"thai",
nullptr, /* collect_features */
nullptr, /* override_features */
nullptr, /* data_create */

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

@ -46,7 +46,6 @@ collect_features_tibetan (hb_ot_shape_planner_t *plan)
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
{
"default",
collect_features_tibetan,
nullptr, /* override_features */
nullptr, /* data_create */

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

@ -595,7 +595,6 @@ compose_use (const hb_ot_shape_normalize_context_t *c,
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
{
"use",
collect_features_use,
nullptr, /* override_features */
data_create_use,

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

@ -210,7 +210,7 @@ position_mark (const hb_ot_shape_plan_t *plan,
pos.x_offset = pos.y_offset = 0;
/* We dont position LEFT and RIGHT marks. */
/* We don't position LEFT and RIGHT marks. */
/* X positioning */
switch (combining_class)

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

@ -99,7 +99,9 @@ struct hb_ot_shape_planner_t
}
private:
NO_COPY (hb_ot_shape_planner_t);
/* No copy. */
hb_ot_shape_planner_t (const hb_ot_shape_planner_t &);
hb_ot_shape_planner_t &operator = (const hb_ot_shape_planner_t &);
};

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

@ -879,9 +879,11 @@ static const LangTagLong ot_languages_zh[] = {
};
static int
lang_compare_first_component (const char *a,
const char *b)
lang_compare_first_component (const void *pa,
const void *pb)
{
const char *a = (const char *) pa;
const char *b = (const char *) pb;
unsigned int da, db;
const char *p;
@ -923,7 +925,7 @@ hb_ot_tag_from_language (hb_language_t language)
if (i) {
for (; i < 4; i++)
tag[i] = ' ';
return HB_TAG_CHAR4 (tag);
return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
}
}
@ -972,7 +974,7 @@ hb_ot_tag_from_language (hb_language_t language)
const LangTag *lang_tag;
lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
ARRAY_LENGTH (ot_languages), sizeof (LangTag),
(hb_compare_func_t) lang_compare_first_component);
lang_compare_first_component);
if (lang_tag)
return lang_tag->tag;
}

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

@ -77,7 +77,7 @@ struct MVAR
const VariationValueRecord *record;
record = (VariationValueRecord *) bsearch (&tag, values,
valueRecordCount, valueRecordSize,
(hb_compare_func_t) tag_compare);
tag_compare);
if (!record)
return 0.;
@ -85,8 +85,12 @@ struct MVAR
}
protected:
static inline int tag_compare (const hb_tag_t *a, const Tag *b)
{ return b->cmp (*a); }
static inline int tag_compare (const void *pa, const void *pb)
{
const hb_tag_t *a = (const hb_tag_t *) pa;
const Tag *b = (const Tag *) pb;
return b->cmp (*a);
}
protected:
FixedVersion<>version; /* Version of the metrics variation table

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

@ -44,16 +44,14 @@
#include <stddef.h>
#include <string.h>
#include <assert.h>
/* We only use these two for debug output. However, the debug code is
* always seen by the compiler (and optimized out in non-debug builds.
* If including these becomes a problem, we can start thinking about
* someway around that. */
#include <stdio.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#define HB_PASTE1(a,b) a##b
#define HB_PASTE(a,b) HB_PASTE1(a,b)
/* Compile-time custom allocator support. */
#if defined(hb_malloc_impl) \
@ -76,36 +74,19 @@ extern "C" void hb_free_impl(void *ptr);
#if __cplusplus < 201103L
// Null pointer literal
// Source: SC22/WG21/N2431 = J16/07-0301
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf
const // this is a const object...
class {
public:
template<class T> // convertible to any type
operator T*() const { // of null non-member
return 0; // pointer...
}
template<class C, class T> // or any type of null
operator T C::*() const { // member pointer...
return 0;
}
private:
void operator&() const; // whose address can't be taken
} _hb_nullptr = {}; // and whose name is nullptr
#define nullptr _hb_nullptr
#ifndef nullptr
#define nullptr NULL
#endif
// Static assertions
#ifndef static_assert
#define _PASTE1(a,b) a##b
#define _PASTE(a,b) _PASTE1(a,b)
#define static_assert(e, msg) \
HB_UNUSED typedef int _PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
#endif // static_assert
#endif // __cplusplus < 201103L
#define _GNU_SOURCE 1
#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
#define likely(expr) (__builtin_expect (!!(expr), 1))
@ -386,11 +367,6 @@ _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
}
/* Type of bsearch() / qsort() compare function */
typedef int (*hb_compare_func_t) (const void *, const void *);
/* arrays and maps */
@ -494,12 +470,12 @@ struct hb_prealloced_array_t
inline void qsort (void)
{
::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
::qsort (array, len, sizeof (Type), Type::cmp);
}
inline void qsort (unsigned int start, unsigned int end)
{
::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
::qsort (array + start, end - start, sizeof (Type), Type::cmp);
}
template <typename T>
@ -559,7 +535,7 @@ struct hb_auto_array_t : hb_prealloced_array_t <Type>
template <typename item_t, typename lock_t>
struct hb_lockable_set_t
{
hb_prealloced_array_t <item_t, 2> items;
hb_prealloced_array_t <item_t, 1> items;
inline void init (void) { items.init (); }
@ -664,22 +640,6 @@ static inline unsigned char TOUPPER (unsigned char c)
static inline unsigned char TOLOWER (unsigned char c)
{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
#define HB_TAG_CHAR4(s) (HB_TAG(((const char *) s)[0], \
((const char *) s)[1], \
((const char *) s)[2], \
((const char *) s)[3]))
/* C++ helpers */
/* Makes class uncopyable. Use in private: section. */
#define NO_COPY(T) \
T (const T &o); \
T &operator = (const T &o)
/* Debug */
/* HB_NDEBUG disables some sanity checks that are very safe to disable and
* should be disabled in production systems. If NDEBUG is defined, enable
@ -690,255 +650,6 @@ static inline unsigned char TOLOWER (unsigned char c)
#define HB_NDEBUG
#endif
#ifndef HB_DEBUG
#define HB_DEBUG 0
#endif
static inline bool
_hb_debug (unsigned int level,
unsigned int max_level)
{
return level < max_level;
}
#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
static inline void
_hb_print_func (const char *func)
{
if (func)
{
unsigned int func_len = strlen (func);
/* Skip "static" */
if (0 == strncmp (func, "static ", 7))
func += 7;
/* Skip "typename" */
if (0 == strncmp (func, "typename ", 9))
func += 9;
/* Skip return type */
const char *space = strchr (func, ' ');
if (space)
func = space + 1;
/* Skip parameter list */
const char *paren = strchr (func, '(');
if (paren)
func_len = paren - func;
fprintf (stderr, "%.*s", func_len, func);
}
}
template <int max_level> static inline void
_hb_debug_msg_va (const char *what,
const void *obj,
const char *func,
bool indented,
unsigned int level,
int level_dir,
const char *message,
va_list ap) HB_PRINTF_FUNC(7, 0);
template <int max_level> static inline void
_hb_debug_msg_va (const char *what,
const void *obj,
const char *func,
bool indented,
unsigned int level,
int level_dir,
const char *message,
va_list ap)
{
if (!_hb_debug (level, max_level))
return;
fprintf (stderr, "%-10s", what ? what : "");
if (obj)
fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
else
fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), "");
if (indented) {
#define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
#define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
#define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
#define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
#define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */
static const char bars[] =
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
fprintf (stderr, "%2u %s" VRBAR "%s",
level,
bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
} else
fprintf (stderr, " " VRBAR LBAR);
_hb_print_func (func);
if (message)
{
fprintf (stderr, ": ");
vfprintf (stderr, message, ap);
}
fprintf (stderr, "\n");
}
template <> inline void
_hb_debug_msg_va<0> (const char *what HB_UNUSED,
const void *obj HB_UNUSED,
const char *func HB_UNUSED,
bool indented HB_UNUSED,
unsigned int level HB_UNUSED,
int level_dir HB_UNUSED,
const char *message HB_UNUSED,
va_list ap HB_UNUSED) {}
template <int max_level> static inline void
_hb_debug_msg (const char *what,
const void *obj,
const char *func,
bool indented,
unsigned int level,
int level_dir,
const char *message,
...) HB_PRINTF_FUNC(7, 8);
template <int max_level> static inline void
_hb_debug_msg (const char *what,
const void *obj,
const char *func,
bool indented,
unsigned int level,
int level_dir,
const char *message,
...)
{
va_list ap;
va_start (ap, message);
_hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
va_end (ap);
}
template <> inline void
_hb_debug_msg<0> (const char *what HB_UNUSED,
const void *obj HB_UNUSED,
const char *func HB_UNUSED,
bool indented HB_UNUSED,
unsigned int level HB_UNUSED,
int level_dir HB_UNUSED,
const char *message HB_UNUSED,
...) HB_PRINTF_FUNC(7, 8);
template <> inline void
_hb_debug_msg<0> (const char *what HB_UNUSED,
const void *obj HB_UNUSED,
const char *func HB_UNUSED,
bool indented HB_UNUSED,
unsigned int level HB_UNUSED,
int level_dir HB_UNUSED,
const char *message 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_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
/*
* Printer
*/
template <typename T>
struct hb_printer_t {
const char *print (const T&) { return "something"; }
};
template <>
struct hb_printer_t<bool> {
const char *print (bool v) { return v ? "true" : "false"; }
};
template <>
struct hb_printer_t<hb_void_t> {
const char *print (hb_void_t) { return ""; }
};
/*
* Trace
*/
template <typename T>
static inline void _hb_warn_no_return (bool returned)
{
if (unlikely (!returned)) {
fprintf (stderr, "OUCH, returned with no call to return_trace(). This is a bug, please report.\n");
}
}
template <>
/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
{}
template <int max_level, typename ret_t>
struct hb_auto_trace_t {
explicit inline hb_auto_trace_t (unsigned int *plevel_,
const char *what_,
const void *obj_,
const char *func,
const char *message,
...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
{
if (plevel) ++*plevel;
va_list ap;
va_start (ap, message);
_hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
va_end (ap);
}
inline ~hb_auto_trace_t (void)
{
_hb_warn_no_return<ret_t> (returned);
if (!returned) {
_hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, " ");
}
if (plevel) --*plevel;
}
inline ret_t ret (ret_t v, unsigned int line = 0)
{
if (unlikely (returned)) {
fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n");
return v;
}
_hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
"return %s (line %d)",
hb_printer_t<ret_t>().print (v), line);
if (plevel) --*plevel;
plevel = nullptr;
returned = true;
return v;
}
private:
unsigned int *plevel;
const char *what;
const void *obj;
bool returned;
};
template <typename ret_t> /* Optimize when tracing is disabled */
struct hb_auto_trace_t<0, ret_t> {
explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED,
const char *what HB_UNUSED,
const void *obj HB_UNUSED,
const char *func HB_UNUSED,
const char *message HB_UNUSED,
...) {}
inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
};
#define return_trace(RET) return trace.ret (RET, __LINE__)
/* Misc */
@ -1156,4 +867,31 @@ hb_options (void)
/* Size signifying variable-sized array */
#define VAR 1
/* String type. */
struct hb_string_t
{
inline hb_string_t (void) : bytes (nullptr), len (0) {}
inline hb_string_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
inline int cmp (const hb_string_t &a) const
{
if (len != a.len)
return (int) a.len - (int) len;
return memcmp (a.bytes, bytes, len);
}
static inline int cmp (const void *pa, const void *pb)
{
hb_string_t *a = (hb_string_t *) pa;
hb_string_t *b = (hb_string_t *) pb;
return b->cmp (*a);
}
const char *bytes;
unsigned int len;
};
#endif /* HB_PRIVATE_HH */

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

@ -24,17 +24,14 @@
* Google Author(s): Behdad Esfahbod
*/
#include "hb-private.hh"
#include "hb-debug.hh"
#include "hb-shape-plan-private.hh"
#include "hb-shaper-private.hh"
#include "hb-font-private.hh"
#include "hb-buffer-private.hh"
#ifndef HB_DEBUG_SHAPE_PLAN
#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
#endif
static void
hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
const hb_feature_t *user_features,

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

@ -0,0 +1,81 @@
/*
* Copyright © 2017 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Behdad Esfahbod
*/
#ifndef HB_STRING_ARRAY_HH
#if 0 /* Make checks happy. */
#define HB_STRING_ARRAY_HH
#endif
#include "hb-private.hh"
/* Based on Bruno Haible's code in Appendix B of Ulrich Drepper's dsohowto.pdf:
* https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf */
#define HB_STRING_ARRAY_TYPE_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _msgstr_t)
#define HB_STRING_ARRAY_POOL_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _msgstr)
#define HB_STRING_ARRAY_OFFS_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _msgidx)
static const union HB_STRING_ARRAY_TYPE_NAME {
struct {
/* I like to avoid storing the nul-termination byte since we don't need it,
* but C++ does not allow that.
* https://stackoverflow.com/questions/28433862/why-initializer-string-for-array-of-chars-is-too-long-compiles-fine-in-c-not
*/
#define _S(s) char HB_PASTE (str, __LINE__)[sizeof (s)];
#include HB_STRING_ARRAY_LIST
#undef _S
} st;
char str[0];
}
HB_STRING_ARRAY_POOL_NAME =
{
{
#define _S(s) s,
#include HB_STRING_ARRAY_LIST
#undef _S
}
};
static const unsigned int HB_STRING_ARRAY_OFFS_NAME[] =
{
#define _S(s) offsetof (union HB_STRING_ARRAY_TYPE_NAME, st.HB_PASTE(str, __LINE__)),
#include HB_STRING_ARRAY_LIST
#undef _S
sizeof (HB_STRING_ARRAY_TYPE_NAME)
};
static inline hb_string_t
HB_STRING_ARRAY_NAME (unsigned int i)
{
assert (i < ARRAY_LENGTH (HB_STRING_ARRAY_OFFS_NAME) - 1);
return hb_string_t (HB_STRING_ARRAY_POOL_NAME.str + HB_STRING_ARRAY_OFFS_NAME[i],
HB_STRING_ARRAY_OFFS_NAME[i + 1] - HB_STRING_ARRAY_OFFS_NAME[i] - 1);
}
#undef HB_STRING_ARRAY_TYPE_NAME
#undef HB_STRING_ARRAY_POOL_NAME
#undef HB_STRING_ARRAY_OFFS_NAME
#endif /* HB_STRING_ARRAY_HH */

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

@ -231,22 +231,43 @@ hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs HB_UNUSED,
return ucdn_compat_decompose(u, decomposed);
}
static hb_unicode_funcs_t *static_ucdn_funcs = nullptr;
#ifdef HB_USE_ATEXIT
static
void free_static_ucdn_funcs (void)
{
hb_unicode_funcs_destroy (static_ucdn_funcs);
}
#endif
extern "C" HB_INTERNAL
hb_unicode_funcs_t *
hb_ucdn_get_unicode_funcs (void)
{
static const hb_unicode_funcs_t _hb_ucdn_unicode_funcs = {
HB_OBJECT_HEADER_STATIC,
retry:
hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
nullptr, /* parent */
true, /* immutable */
{
#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_ucdn_##name,
if (unlikely (!funcs))
{
funcs = hb_unicode_funcs_create (nullptr);
#define HB_UNICODE_FUNC_IMPLEMENT(name) \
hb_unicode_funcs_set_##name##_func (funcs, hb_ucdn_##name, nullptr, nullptr);
HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_UNICODE_FUNC_IMPLEMENT
hb_unicode_funcs_make_immutable (funcs);
if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, nullptr, funcs)) {
hb_unicode_funcs_destroy (funcs);
goto retry;
}
#ifdef HB_USE_ATEXIT
atexit (free_static_ucdn_funcs); /* First person registers atexit() callback. */
#endif
};
return const_cast<hb_unicode_funcs_t *> (&_hb_ucdn_unicode_funcs);
return hb_unicode_funcs_reference (funcs);
}

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

@ -24,6 +24,8 @@
* Google Author(s): Behdad Esfahbod
*/
#include "hb-private.hh"
#include "hb-debug.hh"
#define HB_SHAPER uniscribe
#include "hb-shaper-impl-private.hh"
@ -38,11 +40,6 @@
#include "hb-ot-tag.h"
#ifndef HB_DEBUG_UNISCRIBE
#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
#endif
static inline uint16_t hb_uint16_swap (const uint16_t v)
{ return (v >> 8) | (v << 8); }
static inline uint32_t hb_uint32_swap (const uint32_t v)
@ -264,7 +261,9 @@ struct active_feature_t {
OPENTYPE_FEATURE_RECORD rec;
unsigned int order;
static int cmp (const active_feature_t *a, const active_feature_t *b) {
static int cmp (const void *pa, const void *pb) {
const active_feature_t *a = (const active_feature_t *) pa;
const active_feature_t *b = (const active_feature_t *) pb;
return a->rec.tagFeature < b->rec.tagFeature ? -1 : a->rec.tagFeature > b->rec.tagFeature ? 1 :
a->order < b->order ? -1 : a->order > b->order ? 1 :
a->rec.lParameter < b->rec.lParameter ? -1 : a->rec.lParameter > b->rec.lParameter ? 1 :
@ -280,7 +279,9 @@ struct feature_event_t {
bool start;
active_feature_t feature;
static int cmp (const feature_event_t *a, const feature_event_t *b) {
static int cmp (const void *pa, const void *pb) {
const feature_event_t *a = (const feature_event_t *) pa;
const feature_event_t *b = (const feature_event_t *) pb;
return a->index < b->index ? -1 : a->index > b->index ? 1 :
a->start < b->start ? -1 : a->start > b->start ? 1 :
active_feature_t::cmp (&a->feature, &b->feature);
@ -495,7 +496,7 @@ populate_log_font (LOGFONTW *lf,
unsigned int font_size)
{
memset (lf, 0, sizeof (*lf));
lf->lfHeight = -font_size;
lf->lfHeight = - (int) font_size;
lf->lfCharSet = DEFAULT_CHARSET;
hb_face_t *face = font->face;
@ -854,7 +855,7 @@ retry:
unsigned int glyphs_offset = 0;
unsigned int glyphs_len;
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
for (unsigned int i = 0; i < item_count; i++)
for (int i = 0; i < item_count; i++)
{
unsigned int chars_offset = items[i].iCharPos;
unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
@ -1031,6 +1032,8 @@ retry:
if (backward)
hb_buffer_reverse (buffer);
buffer->unsafe_to_break_all ();
/* Wow, done! */
return true;
}

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

@ -37,10 +37,10 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 1
#define HB_VERSION_MINOR 6
#define HB_VERSION_MICRO 3
#define HB_VERSION_MINOR 7
#define HB_VERSION_MICRO 1
#define HB_VERSION_STRING "1.6.3"
#define HB_VERSION_STRING "1.7.1"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \

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

@ -38,6 +38,7 @@
using namespace OT;
const void * const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
int
main (int argc, char **argv)

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

@ -24,11 +24,10 @@
* Google Author(s): Behdad Esfahbod
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "hb-private.hh"
#include "hb.h"
#include "hb-ot.h"
#ifdef HAVE_FREETYPE
#include "hb-ft.h"
#endif
@ -92,8 +91,9 @@ main (int argc, char **argv)
hb_font_t *font = hb_font_create (face);
hb_face_destroy (face);
hb_font_set_scale (font, upem, upem);
hb_ot_font_set_funcs (font);
#ifdef HAVE_FREETYPE
hb_ft_font_set_funcs (font);
//hb_ft_font_set_funcs (font);
#endif
hb_buffer_t *buf;

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

@ -24,9 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "hb-private.hh"
#include "hb.h"
#include "hb-ot.h"

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

@ -24,9 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "hb-private.hh"
#include "hb.h"
#include "hb-ot.h"

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

@ -24,9 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "hb-private.hh"
#include "hb.h"