diff --git a/gfx/harfbuzz/NEWS b/gfx/harfbuzz/NEWS index af27961e1b14..ba9a886682a6 100644 --- a/gfx/harfbuzz/NEWS +++ b/gfx/harfbuzz/NEWS @@ -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() diff --git a/gfx/harfbuzz/README b/gfx/harfbuzz/README index 69a1bdd9ff3d..0fa35b03eb39 100644 --- a/gfx/harfbuzz/README +++ b/gfx/harfbuzz/README @@ -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/) diff --git a/gfx/harfbuzz/README-mozilla b/gfx/harfbuzz/README-mozilla index ff6340a584ff..2e223b737f43 100644 --- a/gfx/harfbuzz/README-mozilla +++ b/gfx/harfbuzz/README-mozilla @@ -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. diff --git a/gfx/harfbuzz/configure.ac b/gfx/harfbuzz/configure.ac index d3dec0af63b2..7c3aa0336f7f 100644 --- a/gfx/harfbuzz/configure.ac +++ b/gfx/harfbuzz/configure.ac @@ -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 diff --git a/gfx/harfbuzz/git.mk b/gfx/harfbuzz/git.mk index bd39ae10d5ac..6e2708f2dbc0 100644 --- a/gfx/harfbuzz/git.mk +++ b/gfx/harfbuzz/git.mk @@ -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" \ diff --git a/gfx/harfbuzz/src/check-includes.sh b/gfx/harfbuzz/src/check-includes.sh index 37e372d51228..fd565da53fbb 100755 --- a/gfx/harfbuzz/src/check-includes.sh +++ b/gfx/harfbuzz/src/check-includes.sh @@ -34,7 +34,7 @@ grep -v 'hb-private[.]hh:' | grep . >&2 && stat=1 -echo 'Checking that there is no #include ' +echo 'Checking that there is no #include ' for x in $HBHEADERS $HBSOURCES; do test -f "$srcdir/$x" && x="$srcdir/$x" grep '#.*\.*<.*hb' "$x" /dev/null >&2 && stat=1 diff --git a/gfx/harfbuzz/src/harfbuzz-icu.pc b/gfx/harfbuzz/src/harfbuzz-icu.pc index cc8a1384cdee..9b210721a016 100644 --- a/gfx/harfbuzz/src/harfbuzz-icu.pc +++ b/gfx/harfbuzz/src/harfbuzz-icu.pc @@ -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 diff --git a/gfx/harfbuzz/src/harfbuzz.pc b/gfx/harfbuzz/src/harfbuzz.pc index 407b673b017d..d510ae5b6f98 100644 --- a/gfx/harfbuzz/src/harfbuzz.pc +++ b/gfx/harfbuzz/src/harfbuzz.pc @@ -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 diff --git a/gfx/harfbuzz/src/hb-atomic-private.hh b/gfx/harfbuzz/src/hb-atomic-private.hh index 2d5675792de3..93438401400e 100644 --- a/gfx/harfbuzz/src/hb-atomic-private.hh +++ b/gfx/harfbuzz/src/hb-atomic-private.hh @@ -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 diff --git a/gfx/harfbuzz/src/hb-blob.cc b/gfx/harfbuzz/src/hb-blob.cc index e390d7520c57..59c83336374a 100644 --- a/gfx/harfbuzz/src/hb-blob.cc +++ b/gfx/harfbuzz/src/hb-blob.cc @@ -30,6 +30,7 @@ #endif #include "hb-private.hh" +#include "hb-debug.hh" #include "hb-object-private.hh" @@ -44,12 +45,6 @@ #include - -#ifndef HB_DEBUG_BLOB -#define HB_DEBUG_BLOB (HB_DEBUG+0) -#endif - - struct hb_blob_t { hb_object_header_t header; ASSERT_POD (); diff --git a/gfx/harfbuzz/src/hb-buffer-private.hh b/gfx/harfbuzz/src/hb-buffer-private.hh index 1aa87b65c507..4913da6a52eb 100644 --- a/gfx/harfbuzz/src/hb-buffer-private.hh +++ b/gfx/harfbuzz/src/hb-buffer-private.hh @@ -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 (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; + } }; diff --git a/gfx/harfbuzz/src/hb-buffer.cc b/gfx/harfbuzz/src/hb-buffer.cc index 73b3e4bd55b2..f0791780b356 100644 --- a/gfx/harfbuzz/src/hb-buffer.cc +++ b/gfx/harfbuzz/src/hb-buffer.cc @@ -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 (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 (cluster, out_info[i].cluster); /* Extend start */ while (start && out_info[start - 1].cluster == out_info[start].cluster) diff --git a/gfx/harfbuzz/src/hb-common.cc b/gfx/harfbuzz/src/hb-common.cc index 2f9b3b853191..92720d9e7d7d 100644 --- a/gfx/harfbuzz/src/hb-common.cc +++ b/gfx/harfbuzz/src/hb-common.cc @@ -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; } diff --git a/gfx/harfbuzz/src/hb-coretext.cc b/gfx/harfbuzz/src/hb-coretext.cc index 937822b86738..86ca17fb2ddf 100644 --- a/gfx/harfbuzz/src/hb-coretext.cc +++ b/gfx/harfbuzz/src/hb-coretext.cc @@ -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 - -#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: diff --git a/gfx/harfbuzz/src/hb-debug.hh b/gfx/harfbuzz/src/hb-debug.hh new file mode 100644 index 000000000000..ca8c638a79d9 --- /dev/null +++ b/gfx/harfbuzz/src/hb-debug.hh @@ -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 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 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 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 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 (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 (#WHAT, (OBJ), nullptr, true, (LEVEL), (LEVEL_DIR), __VA_ARGS__) +#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg (#WHAT, (OBJ), nullptr, false, 0, 0, __VA_ARGS__) +#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__) + + +/* + * Printer + */ + +template +struct hb_printer_t { + const char *print (const T&) { return "something"; } +}; + +template <> +struct hb_printer_t { + const char *print (bool v) { return v ? "true" : "false"; } +}; + +template <> +struct hb_printer_t { + const char *print (hb_void_t) { return ""; } +}; + + +/* + * Trace + */ + +template +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 (bool returned HB_UNUSED) +{} + +template +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 (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap); + va_end (ap); + } + inline ~hb_auto_trace_t (void) + { + _hb_warn_no_return (returned); + if (!returned) { + _hb_debug_msg (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 (what, obj, nullptr, true, plevel ? *plevel : 1, -1, + "return %s (line %d)", + hb_printer_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 /* 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 +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 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 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 trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "") +#else +#define TRACE_CLOSURE(this) hb_no_trace_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 trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "") +#else +#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_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 trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + ""); +#else +#define TRACE_SANITIZE(this) hb_no_trace_t 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 trace \ + (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ + ""); +#else +#define TRACE_SERIALIZE(this) hb_no_trace_t 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 trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "%d glyphs", c->len); +#else +#define TRACE_WOULD_APPLY(this) hb_no_trace_t 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 trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "format %d", (int) format); +#else +#define TRACE_DISPATCH(this, format) hb_no_trace_t trace +#endif + + +#endif /* HB_DEBUG_HH */ diff --git a/gfx/harfbuzz/src/hb-directwrite.cc b/gfx/harfbuzz/src/hb-directwrite.cc index a6693ef3aedc..0674ef9bcfc6 100644 --- a/gfx/harfbuzz/src/hb-directwrite.cc +++ b/gfx/harfbuzz/src/hb-directwrite.cc @@ -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; } diff --git a/gfx/harfbuzz/src/hb-dsalgs.hh b/gfx/harfbuzz/src/hb-dsalgs.hh new file mode 100644 index 000000000000..e41384754e48 --- /dev/null +++ b/gfx/harfbuzz/src/hb-dsalgs.hh @@ -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; xsafe_to_break_all (); + return true; } diff --git a/gfx/harfbuzz/src/hb-ft.cc b/gfx/harfbuzz/src/hb-ft.cc index f578e9dc49bf..0f15f8c3d0fc 100644 --- a/gfx/harfbuzz/src/hb-ft.cc +++ b/gfx/harfbuzz/src/hb-ft.cc @@ -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. diff --git a/gfx/harfbuzz/src/hb-glib.cc b/gfx/harfbuzz/src/hb-glib.cc index 5b0a1eb32537..50c30e9c7b9b 100644 --- a/gfx/harfbuzz/src/hb-glib.cc +++ b/gfx/harfbuzz/src/hb-glib.cc @@ -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_glib_unicode_funcs); + return hb_unicode_funcs_reference (funcs); } #if GLIB_CHECK_VERSION(2,31,10) diff --git a/gfx/harfbuzz/src/hb-graphite2.cc b/gfx/harfbuzz/src/hb-graphite2.cc index 6f0598dd0b88..62aaae9e87c6 100644 --- a/gfx/harfbuzz/src/hb-graphite2.cc +++ b/gfx/harfbuzz/src/hb-graphite2.cc @@ -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; } diff --git a/gfx/harfbuzz/src/hb-icu.cc b/gfx/harfbuzz/src/hb-icu.cc index 01d15f48e8b1..552eaeca51ea 100644 --- a/gfx/harfbuzz/src/hb-icu.cc +++ b/gfx/harfbuzz/src/hb-icu.cc @@ -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_icu_unicode_funcs); + return hb_unicode_funcs_reference (funcs); } diff --git a/gfx/harfbuzz/src/hb-object-private.hh b/gfx/harfbuzz/src/hb-object-private.hh index d678ae3692e9..baa1f8f05cc3 100644 --- a/gfx/harfbuzz/src/hb-object-private.hh +++ b/gfx/harfbuzz/src/hb-object-private.hh @@ -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 diff --git a/gfx/harfbuzz/src/hb-open-file-private.hh b/gfx/harfbuzz/src/hb-open-file-private.hh index dcfdfd6cab46..741e74ccc20c 100644 --- a/gfx/harfbuzz/src/hb-open-file-private.hh +++ b/gfx/harfbuzz/src/hb-open-file-private.hh @@ -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 (*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 + tables; public: DEFINE_SIZE_ARRAY (12, tables); } OpenTypeFontFace; diff --git a/gfx/harfbuzz/src/hb-open-type-private.hh b/gfx/harfbuzz/src/hb-open-type-private.hh index f25341a8aa9d..a12c4d2369cd 100644 --- a/gfx/harfbuzz/src/hb-open-type-private.hh +++ b/gfx/harfbuzz/src/hb-open-type-private.hh @@ -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 static inline const Type& Null (void) { - static_assert ((sizeof (Type) <= sizeof (_NullPool)), ""); - return *CastP (_NullPool); + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + return *CastP (_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 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 trace \ - (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ - ""); - struct hb_serialize_context_t { @@ -632,10 +615,11 @@ struct IntType inline bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } inline bool operator != (const IntType &o) const { return !(*this == o); } static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } - inline int cmp (Type a) const + template + 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 CHAR; /* 8-bit signed integer. */ -typedef IntType BYTE; /* 8-bit unsigned integer. */ -typedef IntType INT8; /* 8-bit signed integer. */ +typedef IntType CHAR; /* 8-bit signed integer. */ +typedef IntType BYTE; /* 8-bit unsigned integer. */ +typedef IntType INT8; /* 8-bit signed integer. */ typedef IntType USHORT; /* 16-bit unsigned integer. */ typedef IntType SHORT; /* 16-bit signed integer. */ typedef IntType 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 struct SortedArrayOf : ArrayOf { @@ -1064,6 +1050,33 @@ struct SortedArrayOf : ArrayOf } }; +/* + * 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 +struct BinSearchArrayOf : SortedArrayOf {}; + /* Lazy struct and blob loaders. */ diff --git a/gfx/harfbuzz/src/hb-ot-font.cc b/gfx/harfbuzz/src/hb-ot-font.cc index c0ce89df3b57..47416012c9d8 100644 --- a/gfx/harfbuzz/src/hb-ot-font.cc +++ b/gfx/harfbuzz/src/hb-ot-font.cc @@ -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::sanitize (face->reference_table (HB_OT_TAG_post)); - this->post = OT::Sanitizer::lock_instance (this->post_blob); - this->post_len = hb_blob_get_length (this->post_blob); + hb_blob_t *blob = this->post_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_post)); + accel.init (OT::Sanitizer::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::sanitize (face->reference_table (HB_OT_TAG_kern)); + accel.init (OT::Sanitizer::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 glyf; OT::hb_lazy_loader_t cbdt; OT::hb_lazy_loader_t post; + OT::hb_lazy_loader_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 diff --git a/gfx/harfbuzz/src/hb-ot-kern-table.hh b/gfx/harfbuzz/src/hb-ot-kern-table.hh new file mode 100644 index 000000000000..5fd2e20e67dd --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-kern-table.hh @@ -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 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 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 (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 + leftClassTable; /* Offset from beginning of this subtable to + * left-hand class table. */ + OffsetTo + rightClassTable;/* Offset from beginning of this subtable to + * right-hand class table. */ + OffsetTo + 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 +struct KernSubTableWrapper +{ + /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ + inline const T* thiz (void) const { return static_cast (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 +struct KernTable +{ + /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ + inline const T* thiz (void) const { return static_cast (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 (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 (*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 (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 (*st); + } + + return_trace (true); + } +}; + +struct KernOT : KernTable +{ + friend struct KernTable; + + static const uint16_t VERSION = 0x0000u; + + struct SubTableWrapper : KernSubTableWrapper + { + friend struct KernSubTableWrapper; + + 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 +{ + friend struct KernTable; + + static const uint32_t VERSION = 0x00010000u; + + struct SubTableWrapper : KernSubTableWrapper + { + friend struct KernSubTableWrapper; + + 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 */ diff --git a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh index ed18bd88f8c9..8d881add50dc 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.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 trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - "format %d", (int) format); - - #define NOT_COVERED ((unsigned int) -1) diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh index e695d788200b..b0cffa3a85ff 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh @@ -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 trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - struct hb_closure_context_t : hb_dispatch_context_t { @@ -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 trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - "%d glyphs", c->len); - struct hb_would_apply_context_t : hb_dispatch_context_t { @@ -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 trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - struct hb_collect_glyphs_context_t : hb_dispatch_context_t { @@ -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 @@ -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 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 { @@ -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: diff --git a/gfx/harfbuzz/src/hb-ot-layout.cc b/gfx/harfbuzz/src/hb-ot-layout.cc index 71e782686c75..8fe153134173 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.cc +++ b/gfx/harfbuzz/src/hb-ot-layout.cc @@ -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) { diff --git a/gfx/harfbuzz/src/hb-ot-map-private.hh b/gfx/harfbuzz/src/hb-ot-map-private.hh index 105909a1fdbd..97b92cc9a8c2 100644 --- a/gfx/harfbuzz/src/hb-ot-map-private.hh +++ b/gfx/harfbuzz/src/hb-ot-map-private.hh @@ -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 { diff --git a/gfx/harfbuzz/src/hb-ot-name-table.hh b/gfx/harfbuzz/src/hb-ot-name-table.hh index 870f12332517..8e688a6bfa26 100644 --- a/gfx/harfbuzz/src/hb-ot-name-table.hh +++ b/gfx/harfbuzz/src/hb-ot-name-table.hh @@ -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; diff --git a/gfx/harfbuzz/src/hb-ot-post-macroman.hh b/gfx/harfbuzz/src/hb-ot-post-macroman.hh new file mode 100644 index 000000000000..dbbb97e5a9f1 --- /dev/null +++ b/gfx/harfbuzz/src/hb-ot-post-macroman.hh @@ -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 */ diff --git a/gfx/harfbuzz/src/hb-ot-post-table.hh b/gfx/harfbuzz/src/hb-ot-post-table.hh index 3eae7f7f1012..01d626bf1deb 100644 --- a/gfx/harfbuzz/src/hb-ot-post-table.hh +++ b/gfx/harfbuzz/src/hb-ot-post-table.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 + ArrayOfglyphNameIndex; /* 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 (*table); + + glyphNameIndex = &v2.glyphNameIndex; + pool = &StructAfter (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 (*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 (*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 *glyphNameIndex; + hb_prealloced_array_t index_to_offset; + const uint8_t *pool; + mutable uint16_t *gids_sorted_by_name; + }; public: FixedVersion<>version; /* 0x00010000 for version 1.0 diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc index 4a92d41095d0..3ba2d069cb39 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc @@ -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, diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc index 99b53a5a8e7f..68a62a10d44f 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc @@ -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 */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc index 0f3337ff04ee..7508c223c478 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc @@ -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, diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc index fccd76a4505d..ba78186a09c9 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc @@ -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 */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc index 05a513692996..8e2cd620ef38 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc @@ -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 (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, diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc index f446fe625bbb..5ea1dbff27ab 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc @@ -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 */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh index 4951cb5f11aa..fb2f61157a2b 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh @@ -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. diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc index 58a0a41e312f..6ba925c675c4 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc @@ -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 */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc index e87f1a4e3cc6..eaac0bf689fd 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc @@ -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 */ diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc index a2cacac59af1..62acd697bdd2 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc @@ -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, diff --git a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc index 4da53f4cc7da..f3308847e190 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc +++ b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc @@ -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) diff --git a/gfx/harfbuzz/src/hb-ot-shape-private.hh b/gfx/harfbuzz/src/hb-ot-shape-private.hh index d0fe9e6a900f..fe5d2b7f3333 100644 --- a/gfx/harfbuzz/src/hb-ot-shape-private.hh +++ b/gfx/harfbuzz/src/hb-ot-shape-private.hh @@ -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 &); }; diff --git a/gfx/harfbuzz/src/hb-ot-tag.cc b/gfx/harfbuzz/src/hb-ot-tag.cc index 64c6ce0a4c6b..0514c41a34ad 100644 --- a/gfx/harfbuzz/src/hb-ot-tag.cc +++ b/gfx/harfbuzz/src/hb-ot-tag.cc @@ -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; } diff --git a/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh b/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh index 3cb749847678..96bc77f3a6ed 100644 --- a/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh +++ b/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh @@ -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 diff --git a/gfx/harfbuzz/src/hb-private.hh b/gfx/harfbuzz/src/hb-private.hh index b139ed672892..b6d13bd30841 100644 --- a/gfx/harfbuzz/src/hb-private.hh +++ b/gfx/harfbuzz/src/hb-private.hh @@ -44,16 +44,14 @@ #include #include #include - -/* 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 #include +#include #include +#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 // convertible to any type - operator T*() const { // of null non-member - return 0; // pointer... - } - template // 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 @@ -559,7 +535,7 @@ struct hb_auto_array_t : hb_prealloced_array_t template struct hb_lockable_set_t { - hb_prealloced_array_t items; + hb_prealloced_array_t 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 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 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 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 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 (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 (#WHAT, (OBJ), nullptr, true, (LEVEL), (LEVEL_DIR), __VA_ARGS__) -#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg (#WHAT, (OBJ), nullptr, false, 0, 0, __VA_ARGS__) -#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__) - - -/* - * Printer - */ - -template -struct hb_printer_t { - const char *print (const T&) { return "something"; } -}; - -template <> -struct hb_printer_t { - const char *print (bool v) { return v ? "true" : "false"; } -}; - -template <> -struct hb_printer_t { - const char *print (hb_void_t) { return ""; } -}; - - -/* - * Trace - */ - -template -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 (bool returned HB_UNUSED) -{} - -template -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 (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap); - va_end (ap); - } - inline ~hb_auto_trace_t (void) - { - _hb_warn_no_return (returned); - if (!returned) { - _hb_debug_msg (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 (what, obj, nullptr, true, plevel ? *plevel : 1, -1, - "return %s (line %d)", - hb_printer_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 /* 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 */ diff --git a/gfx/harfbuzz/src/hb-shape-plan.cc b/gfx/harfbuzz/src/hb-shape-plan.cc index e58f9ff80b17..6eeba2b3d1f5 100644 --- a/gfx/harfbuzz/src/hb-shape-plan.cc +++ b/gfx/harfbuzz/src/hb-shape-plan.cc @@ -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, diff --git a/gfx/harfbuzz/src/hb-string-array.hh b/gfx/harfbuzz/src/hb-string-array.hh new file mode 100644 index 000000000000..285b4b53574c --- /dev/null +++ b/gfx/harfbuzz/src/hb-string-array.hh @@ -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 */ diff --git a/gfx/harfbuzz/src/hb-ucdn.cc b/gfx/harfbuzz/src/hb-ucdn.cc index c237ee825451..9515bda25673 100644 --- a/gfx/harfbuzz/src/hb-ucdn.cc +++ b/gfx/harfbuzz/src/hb-ucdn.cc @@ -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_ucdn_unicode_funcs); + return hb_unicode_funcs_reference (funcs); } - diff --git a/gfx/harfbuzz/src/hb-uniscribe.cc b/gfx/harfbuzz/src/hb-uniscribe.cc index b19c394b18f7..0b0bad58dbd5 100644 --- a/gfx/harfbuzz/src/hb-uniscribe.cc +++ b/gfx/harfbuzz/src/hb-uniscribe.cc @@ -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; } diff --git a/gfx/harfbuzz/src/hb-version.h b/gfx/harfbuzz/src/hb-version.h index e283983f3ac6..2915571263af 100644 --- a/gfx/harfbuzz/src/hb-version.h +++ b/gfx/harfbuzz/src/hb-version.h @@ -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) <= \ diff --git a/gfx/harfbuzz/src/main.cc b/gfx/harfbuzz/src/main.cc index 93c3b46af2cf..377d1396ab84 100644 --- a/gfx/harfbuzz/src/main.cc +++ b/gfx/harfbuzz/src/main.cc @@ -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) diff --git a/gfx/harfbuzz/src/test-buffer-serialize.cc b/gfx/harfbuzz/src/test-buffer-serialize.cc index c52d88a0fc83..4b429eab3c2a 100644 --- a/gfx/harfbuzz/src/test-buffer-serialize.cc +++ b/gfx/harfbuzz/src/test-buffer-serialize.cc @@ -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; diff --git a/gfx/harfbuzz/src/test-size-params.cc b/gfx/harfbuzz/src/test-size-params.cc index faa828051c5c..9741b87ef887 100644 --- a/gfx/harfbuzz/src/test-size-params.cc +++ b/gfx/harfbuzz/src/test-size-params.cc @@ -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" diff --git a/gfx/harfbuzz/src/test-would-substitute.cc b/gfx/harfbuzz/src/test-would-substitute.cc index cad5b5a048be..efebf2d069f4 100644 --- a/gfx/harfbuzz/src/test-would-substitute.cc +++ b/gfx/harfbuzz/src/test-would-substitute.cc @@ -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" diff --git a/gfx/harfbuzz/src/test.cc b/gfx/harfbuzz/src/test.cc index 2c24fdac82b9..9592b379e9fd 100644 --- a/gfx/harfbuzz/src/test.cc +++ b/gfx/harfbuzz/src/test.cc @@ -24,9 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +#include "hb-private.hh" #include "hb.h"