diff --git a/.circleci/config.yml b/.circleci/config.yml
index af5b478ba..a747ec5c2 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -27,24 +27,11 @@ jobs:
xcode: "10.2.0"
steps:
- checkout
- - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget autoconf automake libtool pkg-config ragel freetype glib cairo icu4c
- - run: brew link --force icu4c
- - run: export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig" && ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-coretext
+ - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget autoconf automake libtool pkg-config ragel freetype glib cairo icu4c graphite2
+ - run: export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig" && ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-coretext --with-graphite2
- run: make -j4
- run: make check || .ci/fail.sh
- macos-notest-ios:
- macos:
- xcode: "10.0.0"
- steps:
- - checkout
- - run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake
- # not needed to be a framework but we like to test that also
- # TODO: wrong way of targeting iOS as it doesn't point to iOS headers thus building
- # CoreText support is not possible, after the fix feel free HB_IOS from CMake altogether
- - run: cmake -DBUILD_FRAMEWORK=ON -H. -Bbuild -GXcode -DHB_HAVE_CORETEXT=OFF -DHB_BUILD_SUBSET=OFF -DHB_BUILD_TESTS=OFF
- - run: cd build && xcodebuild -sdk iphoneos12.0 -configuration Release build -arch arm64
-
distcheck:
docker:
- image: ubuntu:17.10
@@ -93,11 +80,11 @@ jobs:
clang-O3-O0:
docker:
- - image: multiarch/crossbuild
+ - image: ubuntu:18.10
steps:
- checkout
- run: apt update || true
- - run: apt install -y wget autoconf automake libtool pkg-config ragel libfreetype6-dev libfontconfig1-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
+ - run: apt install -y clang wget autoconf automake libtool pkg-config ragel libfreetype6-dev libfontconfig1-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
- run: pip install fonttools
- run: wget http://download.savannah.gnu.org/releases/freetype/freetype-2.9.tar.bz2 && tar xf freetype-2.9.tar.bz2 && cd freetype-2.9 && ./autogen.sh && ./configure && make -j32 && cd ..
- run: CFLAGS="-O3" CXXFLAGS="-O3" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-fontconfig --with-glib --with-cairo --with-icu --with-graphite2
@@ -135,7 +122,7 @@ jobs:
- run: apt update || true
- run: apt install -y clang lld binutils libtool autoconf automake make pkg-config gtk-doc-tools ragel libfreetype6-dev libfontconfig1-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
- run: pip install fonttools
- - run: CFLAGS="-Weverything -Wno-reserved-id-macro -Wno-conversion -Wno-padded -Wno-sign-conversion -Wno-cast-qual -Wno-documentation -Wno-documentation-unknown-command" CXXFLAGS="-Weverything -Wno-old-style-cast -Wno-documentation -Wno-documentation-unknown-command -Wno-c++98-compat -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-sign-conversion -Wno-padded -Wno-shorten-64-to-32 -Wno-reserved-id-macro -Wno-float-conversion -Wno-format-pedantic -Wno-shadow -Wno-conversion -Wno-zero-as-null-pointer-constant -Wno-missing-field-initializers -Wno-used-but-marked-unused -Wno-unused-macros -Wno-comma -Wno-float-equal -Wno-disabled-macro-expansion -Wno-weak-vtables -Wno-unused-parameter -Wno-covered-switch-default -Wno-unreachable-code" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 --with-fontconfig
+ - run: CFLAGS="-Weverything -Wno-reserved-id-macro -Wno-conversion -Wno-padded -Wno-sign-conversion -Wno-cast-qual -Wno-documentation -Wno-documentation-unknown-command" CXXFLAGS="-Weverything -Wno-old-style-cast -Wno-documentation -Wno-documentation-unknown-command -Wno-c++98-compat -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-sign-conversion -Wno-padded -Wno-shorten-64-to-32 -Wno-reserved-id-macro -Wno-float-conversion -Wno-format-pedantic -Wno-shadow -Wno-conversion -Wno-zero-as-null-pointer-constant -Wno-missing-field-initializers -Wno-used-but-marked-unused -Wno-unused-macros -Wno-comma -Wno-float-equal -Wno-disabled-macro-expansion -Wno-weak-vtables -Wno-unused-parameter -Wno-covered-switch-default -Wno-unreachable-code -Wno-unused-template" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 --with-fontconfig
- run: make -j32 CPPFLAGS="-Werror"
- run: make check CPPFLAGS="-Werror" || .ci/fail.sh
@@ -263,6 +250,7 @@ jobs:
steps:
- checkout
- run: git clone https://github.com/vitasdk/vdpm && cd vdpm && ./bootstrap-vitasdk.sh
+ - run: echo "#""!""/bin/true" > /usr/bin/ragel && chmod +x /usr/bin/ragel
- run: ./autogen.sh --prefix=/usr/local/vitasdk/arm-vita-eabi --host=arm-vita-eabi
- run: make -j32
@@ -314,7 +302,6 @@ workflows:
- macos-10.12.6-aat-fonts
- macos-10.13.6-aat-fonts
- macos-10.14.3-aat-fonts
- - macos-notest-ios
# both autotools and cmake
- distcheck
@@ -334,7 +321,7 @@ workflows:
# cmake based builds
- cmake-gcc
- - cmake-oracledeveloperstudio
+ #- cmake-oracledeveloperstudio
# crosscompiles
# they can't be test thus are without tests
diff --git a/NEWS b/NEWS
index ef87dad76..f3e424fbc 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+Overview of changes leading to 2.4.0
+Monday, March 25, 2019
+====================================
+- Unicode 12.
+- Misc fixes.
+- Subsetter improvements.
+- New API:
+HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE
+hb_directwrite_face_create()
+
+
Overview of changes leading to 2.3.1
Wednesday, January 30, 2019
====================================
diff --git a/RELEASING.md b/RELEASING.md
index 1fd836545..5dcce5884 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -33,13 +33,14 @@ HarfBuzz release walk-through checklist:
That's what happened to 2.0.0 going out with 1.8.0 hb-version.h... So, that's
a clue.
-7. "make release-files". Enter your GPG password. This creates a sha256 hash
- and signs it.
-
-8. Now that you have release files, commit NEWS, configure.ac, and src/hb-version.h,
+7. Now that you have release files, commit NEWS, configure.ac, and src/hb-version.h,
as well as any REPLACEME changes you made. The commit message is simply the
release number. Eg. "1.4.7"
+8. "make dist" again to get a tarball with your new commit in the ChangeLog. Then
+ "make release-files". Enter your GPG password. This creates a sha256 hash
+ and signs it. Check the size of the three resulting files.
+
9. Tag the release and sign it: Eg. "git tag -s 1.4.7 -m 1.4.7". Enter your
GPG password again.
diff --git a/configure.ac b/configure.ac
index 718f1d049..98e9c32d8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
- [2.3.1],
+ [2.4.0],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])
@@ -23,7 +23,7 @@ AC_PROG_CC
AC_PROG_CC_C99
AM_PROG_CC_C_O
AC_PROG_CXX
-dnl AX_CXX_COMPILE_STDCXX(11, noext, optional)
+AX_CXX_COMPILE_STDCXX(11,, optional)
AC_SYS_LARGEFILE
PKG_PROG_PKG_CONFIG([0.20])
AM_MISSING_PROG([RAGEL], [ragel])
diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml
index 0c462f38a..f4ad134ea 100644
--- a/docs/harfbuzz-docs.xml
+++ b/docs/harfbuzz-docs.xml
@@ -150,7 +150,6 @@
Index of new symbols in 1.5.0
Index of new symbols in 1.4.3
Index of new symbols in 1.4.2
- Index of new symbols in 1.4.0
Index of new symbols in 1.3.3
Index of new symbols in 1.2.3
Index of new symbols in 1.1.3
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index 27dc1e2d3..f97902f7f 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -216,6 +216,14 @@ hb_coretext_face_get_cg_font
hb_coretext_font_get_ct_font
+
+hb-directwrite
+hb_directwrite_face_create
+hb_directwrite_face_get_font_face
+
+hb_directwrite_shape_experimental_width
+
+
hb-face
hb_face_count
@@ -715,8 +723,6 @@ hb_unicode_script_func_t
hb-uniscribe
hb_uniscribe_font_get_hfont
hb_uniscribe_font_get_logfontw
-
-hb_directwrite_shape_experimental_width
diff --git a/src/Makefile.am b/src/Makefile.am
index 4a130e152..66a3b3177 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -384,12 +384,16 @@ dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
dump_use_data_CPPFLAGS = $(HBCFLAGS)
dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
-COMPILED_TESTS = test-iter test-ot-tag test-unicode-ranges
+COMPILED_TESTS = test-algs test-iter test-ot-tag test-unicode-ranges
COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
check_PROGRAMS += $(COMPILED_TESTS)
TESTS += $(COMPILED_TESTS)
+test_algs_SOURCES = test-algs.cc hb-static.cc
+test_algs_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_algs_LDADD = $(COMPILED_TESTS_LDADD)
+
test_iter_SOURCES = test-iter.cc hb-static.cc
test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_iter_LDADD = $(COMPILED_TESTS_LDADD)
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 6dc7427f6..c698f215b 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -16,6 +16,7 @@ HB_BASE_sources = \
hb-aat-ltag-table.hh \
hb-aat-map.cc \
hb-aat-map.hh \
+ hb-algs.hh \
hb-array.hh \
hb-atomic.hh \
hb-blob.cc \
@@ -31,7 +32,6 @@ HB_BASE_sources = \
hb-cff2-interp-cs.hh \
hb-common.cc \
hb-debug.hh \
- hb-dsalgs.hh \
hb-face.cc \
hb-face.hh \
hb-font.cc \
@@ -42,6 +42,7 @@ HB_BASE_sources = \
hb-map.cc \
hb-map.hh \
hb-bimap.hh \
+ hb-meta.hh \
hb-mutex.hh \
hb-null.hh \
hb-object.hh \
diff --git a/src/hb-aat-map.hh b/src/hb-aat-map.hh
index 3d5ad0e64..f103d276c 100644
--- a/src/hb-aat-map.hh
+++ b/src/hb-aat-map.hh
@@ -84,7 +84,7 @@ struct hb_aat_map_builder_t
hb_face_t *face;
public:
- hb_vector_t features;
+ hb_sorted_vector_t features;
};
diff --git a/src/hb-dsalgs.hh b/src/hb-algs.hh
similarity index 88%
rename from src/hb-dsalgs.hh
rename to src/hb-algs.hh
index 0da244f0a..3eb01d8be 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-algs.hh
@@ -24,16 +24,71 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_DSALGS_HH
-#define HB_DSALGS_HH
+#ifndef HB_ALGS_HH
+#define HB_ALGS_HH
#include "hb.hh"
+#include "hb-meta.hh"
#include "hb-null.hh"
-/* Void! For when we need a expression-type of void. */
-typedef const struct _hb_void_t *hb_void_t;
-#define HB_VOID ((const _hb_void_t *) nullptr)
+static const struct
+{
+ template
+ uint32_t operator () (T v) const
+ {
+ /* Knuth's multiplicative method: */
+ return (uint32_t) v * 2654435761u;
+ }
+ template
+ uint32_t operator () (T *v) const { return hb_hash (*v); }
+ template
+ uint32_t operator () (T&& v) const { return v.hash (); }
+} hb_hash HB_UNUSED;
+
+static const struct
+{
+ template T
+ operator () (const T& v) const { return v; }
+} hb_identity HB_UNUSED;
+
+static const struct
+{
+ template bool
+ operator () (const T& v) const { return bool (v); }
+} hb_bool HB_UNUSED;
+
+template
+struct hb_pair_t
+{
+ typedef T1 first_t;
+ typedef T2 second_t;
+ typedef hb_pair_t pair_t;
+
+ hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
+ hb_pair_t (const pair_t& o) : first (o.first), second (o.second) {}
+
+ bool operator == (const pair_t& o) const { return first == o.first && second == o.second; }
+
+ T1 first;
+ T2 second;
+};
+template static inline hb_pair_t
+hb_pair (T1&& a, T2&& b) { return hb_pair_t (a, b); }
+
+static const struct
+{
+ template decltype (hb_declval (Pair).first)
+ operator () (const Pair& pair) const { return pair.first; }
+} hb_first HB_UNUSED;
+
+static const struct
+{
+ template decltype (hb_declval (Pair).second)
+ operator () (const Pair& pair) const { return pair.second; }
+} hb_second HB_UNUSED;
/*
@@ -233,18 +288,6 @@ hb_ctz (T v)
* Tiny stuff.
*/
-template
-static inline T* hb_addressof (T& arg)
-{
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-align"
- /* https://en.cppreference.com/w/cpp/memory/addressof */
- return reinterpret_cast(
- &const_cast(
- reinterpret_cast(arg)));
-#pragma GCC diagnostic pop
-}
-
/* ASCII tag/character handling */
static inline bool ISALPHA (unsigned char c)
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
@@ -298,17 +341,6 @@ hb_ceil_to_4 (unsigned int v)
return ((v - 1) | 3) + 1;
}
-template struct hb_is_signed;
-/* https://github.com/harfbuzz/harfbuzz/issues/1535 */
-template <> struct hb_is_signed { enum { value = true }; };
-template <> struct hb_is_signed { enum { value = true }; };
-template <> struct hb_is_signed { enum { value = true }; };
-template <> struct hb_is_signed { enum { value = true }; };
-template <> struct hb_is_signed { enum { value = false }; };
-template <> struct hb_is_signed { enum { value = false }; };
-template <> struct hb_is_signed { enum { value = false }; };
-template <> struct hb_is_signed { enum { value = false }; };
-
template static inline bool
hb_in_range (T u, T lo, T hi)
{
@@ -482,16 +514,17 @@ static inline void sort_r_simple(void *base, size_t nel, size_t w,
}
}
-static inline void hb_sort_r(void *base, size_t nel, size_t width,
- int (*compar)(const void *_a, const void *_b, void *_arg),
- void *arg)
+static inline void
+hb_sort_r (void *base, size_t nel, size_t width,
+ int (*compar)(const void *_a, const void *_b, void *_arg),
+ void *arg)
{
sort_r_simple(base, nel, width, compar, arg);
}
-template static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
+template static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
{
for (unsigned int i = 1; i < len; i++)
{
@@ -508,8 +541,8 @@ hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *),
}
if (array2)
{
- T2 t = array2[i];
- memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
+ T3 t = array2[i];
+ memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T3));
array2[j] = t;
}
}
@@ -624,4 +657,4 @@ struct hb_vector_size_t
};
-#endif /* HB_DSALGS_HH */
+#endif /* HB_ALGS_HH */
diff --git a/src/hb-array.hh b/src/hb-array.hh
index 52b775e95..ab453f5a2 100644
--- a/src/hb-array.hh
+++ b/src/hb-array.hh
@@ -28,7 +28,7 @@
#define HB_ARRAY_HH
#include "hb.hh"
-#include "hb-dsalgs.hh"
+#include "hb-algs.hh"
#include "hb-iter.hh"
#include "hb-null.hh"
@@ -37,22 +37,22 @@ template
struct hb_sorted_array_t;
template
-struct hb_array_t :
- hb_iter_t, Type>,
- hb_iter_mixin_t, Type>
+struct hb_array_t : hb_iter_with_fallback_t, Type&>
{
/*
* Constructors.
*/
hb_array_t () : arrayZ (nullptr), length (0) {}
+ template
+ hb_array_t (const hb_array_t &o) : arrayZ (o.arrayZ), length (o.length) {}
hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
template hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {}
-
/*
* Iterator implementation.
*/
- typedef Type __item_type__;
+ typedef Type& __item_t__;
+ static constexpr bool is_random_access_iterator = true;
Type& __item_at__ (unsigned i) const
{
if (unlikely (i >= length)) return CrapOrNull (Type);
@@ -72,7 +72,6 @@ struct hb_array_t :
length -= n;
}
unsigned __len__ () const { return length; }
- bool __random_access__ () const { return true; }
/* Extra operators.
*/
@@ -183,7 +182,6 @@ template inline hb_array_t
hb_array (T (&array_)[length_])
{ return hb_array_t (array_); }
-
enum hb_bfind_not_found_t
{
HB_BFIND_NOT_FOUND_DONT_STORE,
@@ -193,12 +191,18 @@ enum hb_bfind_not_found_t
template
struct hb_sorted_array_t :
- hb_sorted_iter_t, Type>,
- hb_array_t,
- hb_iter_mixin_t, Type>
+ hb_iter_t, Type&>,
+ hb_array_t
{
+ typedef hb_iter_t, Type&> iter_base_t;
+ HB_ITER_USING (iter_base_t);
+ static constexpr bool is_random_access_iterator = true;
+ static constexpr bool is_sorted_iterator = true;
+
hb_sorted_array_t () : hb_array_t () {}
hb_sorted_array_t (const hb_array_t &o) : hb_array_t (o) {}
+ template
+ hb_sorted_array_t (const hb_sorted_array_t &o) : hb_array_t (o) {}
hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t (array_, length_) {}
template hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t (array_) {}
diff --git a/src/hb-atomic.hh b/src/hb-atomic.hh
index f9afd4fff..a2ce8f28d 100644
--- a/src/hb-atomic.hh
+++ b/src/hb-atomic.hh
@@ -33,6 +33,7 @@
#define HB_ATOMIC_HH
#include "hb.hh"
+#include "hb-meta.hh"
/*
@@ -282,7 +283,7 @@ struct hb_atomic_int_t
template
struct hb_atomic_ptr_t
{
- typedef typename hb_remove_pointer (P) T;
+ typedef hb_remove_pointer (P) T;
void init (T* v_ = nullptr) { set_relaxed (v_); }
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
diff --git a/src/hb-blob.hh b/src/hb-blob.hh
index 4ea13f813..3a30efe55 100644
--- a/src/hb-blob.hh
+++ b/src/hb-blob.hh
@@ -81,7 +81,7 @@ struct hb_blob_t
template
struct hb_blob_ptr_t
{
- typedef typename hb_remove_pointer (P) T;
+ typedef hb_remove_pointer (P) T;
hb_blob_ptr_t (hb_blob_t *b_ = nullptr) : b (b_) {}
hb_blob_t * operator = (hb_blob_t *b_) { return b = b_; }
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index 43aeb99db..ac1d4525a 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -287,7 +287,7 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* @HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE:
* flag indicating that a dotted circle should
* not be inserted in the rendering of incorrect
- * character sequences (such at <0905 093E>). Since: REPLACEME
+ * character sequences (such at <0905 093E>). Since: 2.4
*
* Since: 0.9.20
*/
diff --git a/src/hb-cff-interp-common.hh b/src/hb-cff-interp-common.hh
index 72e9e06c8..78ef997b1 100644
--- a/src/hb-cff-interp-common.hh
+++ b/src/hb-cff-interp-common.hh
@@ -272,11 +272,11 @@ struct UnsizedByteStr : UnsizedArrayOf
HBUINT8 *p = c->allocate_size (1);
if (unlikely (p == nullptr)) return_trace (false);
- p->set (intOp);
+ *p = intOp;
INTTYPE *ip = c->allocate_size (INTTYPE::static_size);
if (unlikely (ip == nullptr)) return_trace (false);
- ip->set ((unsigned int)value);
+ *ip = (unsigned int) value;
return_trace (true);
}
diff --git a/src/hb-common.h b/src/hb-common.h
index fbabd71c8..371b2bfc9 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -358,7 +358,7 @@ typedef enum
/*11.0*/HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'),
/*
- * Since REPLACEME
+ * Since 2.4.0
*/
/*12.0*/HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'),
/*12.0*/HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'),
diff --git a/src/hb-debug.hh b/src/hb-debug.hh
index d7d0165a9..d81483bed 100644
--- a/src/hb-debug.hh
+++ b/src/hb-debug.hh
@@ -29,7 +29,7 @@
#include "hb.hh"
#include "hb-atomic.hh"
-#include "hb-dsalgs.hh"
+#include "hb-algs.hh"
#ifndef HB_DEBUG
@@ -437,25 +437,12 @@ struct hb_no_trace_t {
#define TRACE_SUBSET(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_SANITIZE + \
HB_DEBUG_SERIALIZE + \
- HB_DEBUG_SUBSET + \
- HB_DEBUG_WOULD_APPLY + \
+ HB_DEBUG_SUBSET + \
0)
#endif
#if HB_DEBUG_DISPATCH
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index 137cd56c8..d8076c922 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -846,10 +846,23 @@ _hb_directwrite_shape (hb_shape_plan_t *shape_plan,
features, num_features, 0);
}
-/*
- * Public [experimental] API
- */
-
+/**
+ * hb_directwrite_shape_experimental_width:
+ * Experimental API to test DirectWrite's justification algorithm.
+ *
+ * It inserts Kashida at wrong order so don't use the API ever.
+ *
+ * It doesn't work with cygwin/msys due to header bugs so one
+ * should use MSVC toolchain in order to use it for now.
+ *
+ * @font:
+ * @buffer:
+ * @features:
+ * @num_features:
+ * @width:
+ *
+ * Since: 1.4.2
+ **/
hb_bool_t
hb_directwrite_shape_experimental_width (hb_font_t *font,
hb_buffer_t *buffer,
@@ -918,7 +931,8 @@ _hb_directwrite_font_release (void *data)
/**
* hb_directwrite_face_create:
* @font_face:
- * Since: REPLACEME
+ *
+ * Since: 2.4.0
**/
hb_face_t *
hb_directwrite_face_create (IDWriteFontFace *font_face)
@@ -928,3 +942,15 @@ hb_directwrite_face_create (IDWriteFontFace *font_face)
return hb_face_create_for_tables (reference_table, font_face,
_hb_directwrite_font_release);
}
+
+/**
+* hb_directwrite_face_get_font_face:
+* @face:
+*
+* Since: REPLACEME
+**/
+IDWriteFontFace *
+hb_directwrite_face_get_font_face (hb_face_t *face)
+{
+ return face->data.directwrite->fontFace;
+}
diff --git a/src/hb-directwrite.h b/src/hb-directwrite.h
index 09776fd09..de813d069 100644
--- a/src/hb-directwrite.h
+++ b/src/hb-directwrite.h
@@ -37,6 +37,9 @@ hb_directwrite_shape_experimental_width (hb_font_t *font, hb_buffer_t *buffer,
HB_EXTERN hb_face_t *
hb_directwrite_face_create (IDWriteFontFace *font_face);
+HB_EXTERN IDWriteFontFace *
+hb_directwrite_face_get_font_face (hb_face_t *face);
+
HB_END_DECLS
#endif /* HB_DIRECTWRITE_H */
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 1900f30bc..48434dc8c 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -96,7 +96,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
- ft_font->cached_x_scale.set (0);
+ ft_font->cached_x_scale.set_relaxed (0);
ft_font->advance_cache.init ();
return ft_font;
diff --git a/src/hb-iter.hh b/src/hb-iter.hh
index c4ab26dc0..28fc31e1f 100644
--- a/src/hb-iter.hh
+++ b/src/hb-iter.hh
@@ -28,7 +28,7 @@
#define HB_ITER_HH
#include "hb.hh"
-#include "hb-null.hh"
+#include "hb-meta.hh"
/* Unified iterator object.
@@ -41,14 +41,20 @@
* returns rvalues.
*/
+
+/*
+ * Base classes for iterators.
+ */
+
/* Base class for all iterators. */
-template
+template
struct hb_iter_t
{
- typedef Iter iter_t;
- typedef iter_t const_iter_t;
typedef Item item_t;
static constexpr unsigned item_size = hb_static_size (Item);
+ static constexpr bool is_iterator = true;
+ static constexpr bool is_random_access_iterator = false;
+ static constexpr bool is_sorted_iterator = false;
private:
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
@@ -56,32 +62,35 @@ struct hb_iter_t
iter_t* thiz () { return static_cast< iter_t *> (this); }
public:
- /* Operators. */
- operator iter_t () { return iter(); }
- explicit_operator bool () const { return more (); }
- item_t& operator * () const { return item (); }
- item_t& operator [] (signed i) const { return item_at ((unsigned) i); }
- iter_t& operator += (unsigned count) { forward (count); return *thiz(); }
- iter_t& operator ++ () { next (); return *thiz(); }
- iter_t& operator -= (unsigned count) { rewind (count); return *thiz(); }
- iter_t& operator -- () { prev (); return *thiz(); }
- iter_t operator + (unsigned count) { iter_t c (*thiz()); c += count; return c; }
- iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
- iter_t operator - (unsigned count) { iter_t c (*thiz()); c -= count; return c; }
- iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
+ /* TODO:
+ * Port operators below to use hb_enable_if to sniff which method implements
+ * an operator and use it, and remove hb_iter_fallback_mixin_t completely. */
- /* Methods. */
+ /* Operators. */
iter_t iter () const { return *thiz(); }
- const_iter_t const_iter () const { return iter (); }
- item_t& item () const { return thiz()->__item__ (); }
- item_t& item_at (unsigned i) const { return thiz()->__item_at__ (i); }
- bool more () const { return thiz()->__more__ (); }
+ iter_t operator + () const { return *thiz(); }
+ explicit operator bool () const { return thiz()->__more__ (); }
unsigned len () const { return thiz()->__len__ (); }
- void next () { thiz()->__next__ (); }
- void forward (unsigned n) { thiz()->__forward__ (n); }
- void prev () { thiz()->__prev__ (); }
- void rewind (unsigned n) { thiz()->__rewind__ (n); }
- bool random_access () const { return thiz()->__random_access__ (); }
+ /* The following can only be enabled if item_t is reference type. Otherwise
+ * it will be returning pointer to temporary rvalue. */
+ template
+ hb_remove_reference (item_t)* operator -> () const { return hb_addressof (**thiz()); }
+ item_t operator * () const { return thiz()->__item__ (); }
+ item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); }
+ iter_t& operator += (unsigned count) { thiz()->__forward__ (count); return *thiz(); }
+ iter_t& operator ++ () { thiz()->__next__ (); return *thiz(); }
+ iter_t& operator -= (unsigned count) { thiz()->__rewind__ (count); return *thiz(); }
+ iter_t& operator -- () { thiz()->__prev__ (); return *thiz(); }
+ iter_t operator + (unsigned count) const { auto c = thiz()->iter (); c += count; return c; }
+ friend iter_t operator + (unsigned count, const iter_t &it) { return it + count; }
+ iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
+ iter_t operator - (unsigned count) const { auto c = thiz()->iter (); c -= count; return c; }
+ iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
+ template
+ iter_t& operator >> (T &v) { v = **thiz(); ++*thiz(); return *thiz(); }
+ template
+ iter_t& operator << (const T v) { **thiz() = v; ++*thiz(); return *thiz(); }
protected:
hb_iter_t () {}
@@ -89,20 +98,57 @@ struct hb_iter_t
void operator = (const hb_iter_t &o HB_UNUSED) {}
};
-/* Base class for sorted iterators. Does not enforce anything.
- * Just for class taxonomy and requirements. */
-template
-struct hb_sorted_iter_t : hb_iter_t
+#define HB_ITER_USING(Name) \
+ using item_t = typename Name::item_t; \
+ using Name::item_size; \
+ using Name::is_iterator; \
+ using Name::iter; \
+ using Name::operator bool; \
+ using Name::len; \
+ using Name::operator ->; \
+ using Name::operator *; \
+ using Name::operator []; \
+ using Name::operator +=; \
+ using Name::operator ++; \
+ using Name::operator -=; \
+ using Name::operator --; \
+ using Name::operator +; \
+ using Name::operator -; \
+ using Name::operator >>; \
+ using Name::operator <<; \
+ static_assert (true, "")
+
+/* Returns iterator type of a type. */
+#define hb_iter_t(Iterable) decltype (hb_declval (Iterable).iter ())
+
+
+/* TODO Change to function-object. */
+
+template struct hb_array_t;
+
+static const struct
{
- protected:
- hb_sorted_iter_t () {}
- hb_sorted_iter_t (const hb_sorted_iter_t &o) : hb_iter_t (o) {}
- void operator = (const hb_sorted_iter_t &o HB_UNUSED) {}
-};
+ template
+ hb_iter_t (T)
+ operator () (T&& c) const
+ { return c.iter (); }
+
+ /* Specialization for C arrays. */
+
+ template inline hb_array_t
+ operator () (Type *array, unsigned int length) const
+ { return hb_array_t (array, length); }
+
+ template hb_array_t
+ operator () (Type (&array)[length]) const
+ { return hb_array_t (array, length); }
+
+} hb_iter HB_UNUSED;
+
/* Mixin to fill in what the subclass doesn't provide. */
-template
-struct hb_iter_mixin_t
+template
+struct hb_iter_fallback_mixin_t
{
private:
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
@@ -111,38 +157,438 @@ struct hb_iter_mixin_t
public:
/* Access: Implement __item__(), or __item_at__() if random-access. */
- item_t& __item__ () const { return thiz()->item_at (0); }
- item_t& __item_at__ (unsigned i) const { return *(thiz() + i); }
+ item_t __item__ () const { return (*thiz())[0]; }
+ item_t __item_at__ (unsigned i) const { return *(*thiz() + i); }
/* Termination: Implement __more__(), or __len__() if random-access. */
- bool __more__ () const { return thiz()->__len__ (); }
+ bool __more__ () const { return thiz()->len (); }
unsigned __len__ () const
{ iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; }
/* Advancing: Implement __next__(), or __forward__() if random-access. */
- void __next__ () { thiz()->forward (1); }
- void __forward__ (unsigned n) { while (n--) thiz()->next (); }
+ void __next__ () { *thiz() += 1; }
+ void __forward__ (unsigned n) { while (n--) ++*thiz(); }
/* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
- void __prev__ () { thiz()->rewind (1); }
- void __rewind__ (unsigned n) { while (n--) thiz()->prev (); }
+ void __prev__ () { *thiz() -= 1; }
+ void __rewind__ (unsigned n) { while (n--) --*thiz(); }
- /* Random access: Return true if item_at(), len(), forward() are fast. */
- bool __random_access__ () const { return false; }
+ protected:
+ hb_iter_fallback_mixin_t () {}
+ hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) {}
+ void operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) {}
};
-
-/* Functions operating on iterators or iteratables. */
-
-template inline void
-hb_fill (const C& c, const V &v)
+template
+struct hb_iter_with_fallback_t :
+ hb_iter_t,
+ hb_iter_fallback_mixin_t
{
- for (typename C::iter_t i (c); i; i++)
- hb_assign (*i, v);
+ protected:
+ hb_iter_with_fallback_t () {}
+ hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) :
+ hb_iter_t (o),
+ hb_iter_fallback_mixin_t (o) {}
+ void operator = (const hb_iter_with_fallback_t &o HB_UNUSED) {}
+};
+
+/*
+ * Meta-programming predicates.
+ */
+
+/* hb_is_iterable() */
+
+template
+struct _hb_is_iterable
+{ enum { value = false }; };
+template
+struct _hb_is_iterable >
+{ enum { value = true }; };
+
+template
+struct hb_is_iterable { enum { value = _hb_is_iterable::value }; };
+#define hb_is_iterable(Iterable) hb_is_iterable::value
+
+/* TODO Add hb_is_iterable_of().
+ * TODO Add random_access / sorted variants. */
+
+
+/* hb_is_iterator() / hb_is_random_access_iterator() / hb_is_sorted_iterator() */
+
+template
+struct _hb_is_iterator_of
+{
+ char operator () (...) { return 0; }
+ template int operator () (hb_iter_t *) { return 0; }
+ template int operator () (hb_iter_t *) { return 0; }
+ template int operator () (hb_iter_t *) { return 0; }
+ template int operator () (hb_iter_t *) { return 0; }
+ static_assert (sizeof (char) != sizeof (int), "");
+};
+template
+struct hb_is_iterator_of { enum {
+ value = sizeof (int) == sizeof (hb_declval (_hb_is_iterator_of) (hb_declval (Iter*))) }; };
+#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of::value
+#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
+
+#define hb_is_random_access_iterator_of(Iter, Item) \
+ hb_is_iterator_of (Iter, Item) && Iter::is_random_access_iterator
+#define hb_is_random_access_iterator(Iter) \
+ hb_is_random_access_iterator_of (Iter, typename Iter::item_t)
+
+#define hb_is_sorted_iterator_of(Iter, Item) \
+ hb_is_iterator_of (Iter, Item) && Iter::is_sorted_iterator
+#define hb_is_sorted_iterator(Iter) \
+ hb_is_sorted_iterator_of (Iter, typename Iter::item_t)
+
+
+/*
+ * Adaptors, combiners, etc.
+ */
+
+template
+static inline decltype (hb_declval (Rhs) (hb_declval (Lhs)))
+operator | (Lhs lhs, const Rhs &rhs) { return rhs (lhs); }
+
+/* hb_map(), hb_filter(), hb_reduce() */
+
+template
+struct hb_map_iter_t :
+ hb_iter_t,
+ decltype (hb_declval (Proj) (hb_declval (typename Iter::item_t)))>
+{
+ hb_map_iter_t (const Iter& it, Proj f) : it (it), f (f) {}
+
+ typedef decltype (hb_declval (Proj) (hb_declval (typename Iter::item_t))) __item_t__;
+ static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
+ __item_t__ __item__ () const { return f (*it); }
+ __item_t__ __item_at__ (unsigned i) const { return f (it[i]); }
+ bool __more__ () const { return bool (it); }
+ unsigned __len__ () const { return it.len (); }
+ void __next__ () { ++it; }
+ void __forward__ (unsigned n) { it += n; }
+ void __prev__ () { --it; }
+ void __rewind__ (unsigned n) { it -= n; }
+
+ private:
+ Iter it;
+ Proj f;
+};
+
+template
+struct hb_map_iter_factory_t
+{
+ hb_map_iter_factory_t (Proj f) : f (f) {}
+
+ template
+ hb_map_iter_t
+ operator () (Iter it) const
+ { return hb_map_iter_t (it, f); }
+
+ private:
+ Proj f;
+};
+static const struct
+{
+ template
+ hb_map_iter_factory_t
+ operator () (Proj&& f) const
+ { return hb_map_iter_factory_t (f); }
+} hb_map HB_UNUSED;
+
+template
+struct hb_filter_iter_t :
+ hb_iter_with_fallback_t,
+ typename Iter::item_t>
+{
+ hb_filter_iter_t (const Iter& it_, Pred p, Proj f) : it (it_), p (p), f (f)
+ { while (it && !p (f (*it))) ++it; }
+
+ typedef typename Iter::item_t __item_t__;
+ static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
+ __item_t__ __item__ () const { return *it; }
+ bool __more__ () const { return bool (it); }
+ void __next__ () { do ++it; while (it && !p (f (*it))); }
+ void __prev__ () { --it; }
+
+ private:
+ Iter it;
+ Pred p;
+ Proj f;
+};
+template
+struct hb_filter_iter_factory_t
+{
+ hb_filter_iter_factory_t (Pred p, Proj f) : p (p), f (f) {}
+
+ template
+ hb_filter_iter_t
+ operator () (Iter it) const
+ { return hb_filter_iter_t (it, p, f); }
+
+ private:
+ Pred p;
+ Proj f;
+};
+static const struct
+{
+ template
+ hb_filter_iter_factory_t
+ operator () (Pred&& p = hb_bool, Proj&& f = hb_identity) const
+ { return hb_filter_iter_factory_t (p, f); }
+} hb_filter HB_UNUSED;
+
+/* hb_zip() */
+
+template
+struct hb_zip_iter_t :
+ hb_iter_t,
+ hb_pair_t >
+{
+ hb_zip_iter_t () {}
+ hb_zip_iter_t (const A& a, const B& b) : a (a), b (b) {}
+
+ typedef hb_pair_t __item_t__;
+ static constexpr bool is_random_access_iterator =
+ A::is_random_access_iterator &&
+ B::is_random_access_iterator;
+ static constexpr bool is_sorted_iterator =
+ A::is_sorted_iterator &&
+ B::is_sorted_iterator;
+ __item_t__ __item__ () const { return __item_t__ (*a, *b); }
+ __item_t__ __item_at__ (unsigned i) const { return __item_t__ (a[i], b[i]); }
+ bool __more__ () const { return a && b; }
+ unsigned __len__ () const { return MIN (a.len (), b.len ()); }
+ void __next__ () { ++a; ++b; }
+ void __forward__ (unsigned n) { a += n; b += n; }
+ void __prev__ () { --a; --b; }
+ void __rewind__ (unsigned n) { a -= n; b -= n; }
+
+ private:
+ A a;
+ B b;
+};
+static const struct
+{
+ template
+ hb_zip_iter_t
+ operator () (A& a, B &b) const
+ { return hb_zip_iter_t (hb_iter (a), hb_iter (b)); }
+} hb_zip HB_UNUSED;
+
+/* hb_enumerate */
+
+template
+struct hb_enumerate_iter_t :
+ hb_iter_t,
+ hb_pair_t >
+{
+ hb_enumerate_iter_t (const Iter& it) : i (0), it (it) {}
+
+ typedef hb_pair_t __item_t__;
+ static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
+ static constexpr bool is_sorted_iterator = true;
+ __item_t__ __item__ () const { return __item_t__ (+i, *it); }
+ __item_t__ __item_at__ (unsigned j) const { return __item_t__ (i + j, it[j]); }
+ bool __more__ () const { return bool (it); }
+ unsigned __len__ () const { return it.len (); }
+ void __next__ () { ++i; ++it; }
+ void __forward__ (unsigned n) { i += n; it += n; }
+ void __prev__ () { --i; --it; }
+ void __rewind__ (unsigned n) { i -= n; it -= n; }
+
+ private:
+ unsigned i;
+ Iter it;
+};
+static const struct
+{
+ template
+ hb_enumerate_iter_t
+ operator () (Iterable& it) const
+ { return hb_enumerate_iter_t (hb_iter (it)); }
+} hb_enumerate HB_UNUSED;
+
+/* hb_apply() */
+
+template
+struct hb_apply_t
+{
+ hb_apply_t (Appl a) : a (a) {}
+
+ template
+ void
+ operator () (Iter it) const
+ {
+ for (; it; ++it)
+ a (*it);
+ }
+
+ private:
+ Appl a;
+};
+static const struct
+{
+ template hb_apply_t
+ operator () (Appl&& a) const
+ { return hb_apply_t (a); }
+
+ template hb_apply_t
+ operator () (Appl *a) const
+ { return hb_apply_t (*a); }
+} hb_apply HB_UNUSED;
+
+/* hb_sink() */
+
+template
+struct hb_sink_t
+{
+ hb_sink_t (Sink&& s) : s (s) {}
+
+ template
+ void
+ operator () (Iter it) const
+ {
+ for (; it; ++it)
+ s << *it;
+ }
+
+ private:
+ Sink s;
+};
+static const struct
+{
+ template hb_sink_t
+ operator () (Sink&& s) const
+ { return hb_sink_t (s); }
+
+ template hb_sink_t
+ operator () (Sink *s) const
+ { return hb_sink_t (*s); }
+} hb_sink HB_UNUSED;
+
+/* hb-drain: hb_sink to void / blackhole / /dev/null. */
+
+static const struct
+{
+ template
+ void
+ operator () (Iter it) const
+ {
+ for (; it; ++it)
+ (void) *it;
+ }
+} hb_drain HB_UNUSED;
+
+/* hb_unzip(): unzip and sink to two sinks. */
+
+template
+struct hb_unzip_t
+{
+ hb_unzip_t (Sink1&& s1, Sink2&& s2) : s1 (s1), s2 (s2) {}
+
+ template
+ void
+ operator () (Iter it) const
+ {
+ for (; it; ++it)
+ {
+ const auto &v = *it;
+ s1 << v.first;
+ s2 << v.second;
+ }
+ }
+
+ private:
+ Sink1 s1;
+ Sink2 s2;
+};
+static const struct
+{
+ template hb_unzip_t
+ operator () (Sink1&& s1, Sink2&& s2) const
+ { return hb_unzip_t (s1, s2); }
+
+ template hb_unzip_t
+ operator () (Sink1 *s1, Sink2 *s2) const
+ { return hb_unzip_t (*s1, *s2); }
+} hb_unzip HB_UNUSED;
+
+
+/* hb-all, hb-any, hb-none. */
+
+static const struct
+{
+ template
+ bool
+ operator () (Iterable&& c) const
+ {
+ for (auto it = hb_iter (c); it; ++it)
+ if (!*it)
+ return false;
+ return true;
+ }
+} hb_all HB_UNUSED;
+
+static const struct
+{
+ template
+ bool
+ operator () (Iterable&& c) const
+ {
+ for (auto it = hb_iter (c); it; ++it)
+ if (it)
+ return true;
+ return false;
+ }
+} hb_any HB_UNUSED;
+
+static const struct
+{
+ template
+ bool
+ operator () (Iterable&& c) const
+ {
+ for (auto it = hb_iter (c); it; ++it)
+ if (it)
+ return false;
+ return true;
+ }
+} hb_none HB_UNUSED;
+
+/*
+ * Algorithms operating on iterators.
+ */
+
+template
+inline void
+hb_fill (C& c, const V &v)
+{
+ for (auto i = hb_iter (c); i; i++)
+ *i = v;
}
-template inline bool
-hb_copy (hb_iter_t &id, hb_iter_t &is)
+template
+inline bool
+hb_copy (D id, S is)
{
for (; id && is; ++id, ++is)
*id = *is;
diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh
index ffa423d2f..89ad8ac63 100644
--- a/src/hb-machinery.hh
+++ b/src/hb-machinery.hh
@@ -405,7 +405,7 @@ struct hb_sanitize_context_t :
{
if (this->may_edit (obj, hb_static_size (Type)))
{
- hb_assign (* const_cast (obj), v);
+ * const_cast (obj) = v;
return true;
}
return false;
@@ -682,7 +682,11 @@ template
struct BEInt
{
public:
- void set (Type V) { v = V; }
+ BEInt& operator = (Type V)
+ {
+ v = V;
+ return *this;
+ }
operator Type () const { return v; }
private: uint8_t v;
};
@@ -690,10 +694,11 @@ template
struct BEInt
{
public:
- void set (Type V)
+ BEInt& operator = (Type V)
{
v[0] = (V >> 8) & 0xFF;
v[1] = (V ) & 0xFF;
+ return *this;
}
operator Type () const
{
@@ -718,11 +723,12 @@ template
struct BEInt
{
public:
- void set (Type V)
+ BEInt& operator = (Type V)
{
v[0] = (V >> 16) & 0xFF;
v[1] = (V >> 8) & 0xFF;
v[2] = (V ) & 0xFF;
+ return *this;
}
operator Type () const
{
@@ -736,13 +742,13 @@ template
struct BEInt
{
public:
- typedef Type type;
- void set (Type V)
+ BEInt& operator = (Type V)
{
v[0] = (V >> 24) & 0xFF;
v[1] = (V >> 16) & 0xFF;
v[2] = (V >> 8) & 0xFF;
v[3] = (V ) & 0xFF;
+ return *this;
}
operator Type () const
{
@@ -816,7 +822,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t
const Returned * operator -> () const { return get (); }
const Returned & operator * () const { return *get (); }
- explicit_operator bool () const
+ explicit operator bool () const
{ return get_stored () != Funcs::get_null (); }
template operator const C * () const { return get (); }
diff --git a/src/hb-map.hh b/src/hb-map.hh
index f7156e51a..f2a65a821 100644
--- a/src/hb-map.hh
+++ b/src/hb-map.hh
@@ -30,14 +30,6 @@
#include "hb.hh"
-template
-inline uint32_t Hash (const T &v)
-{
- /* Knuth's multiplicative method: */
- return (uint32_t) v * 2654435761u;
-}
-
-
/*
* hb_map_t
*/
@@ -160,14 +152,16 @@ struct hb_map_t
void del (hb_codepoint_t key) { set (key, INVALID); }
- bool has (hb_codepoint_t key) const
- { return get (key) != INVALID; }
-
- hb_codepoint_t operator [] (unsigned int key) const
- { return get (key); }
-
static constexpr hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
+ /* Has interface. */
+ static constexpr hb_codepoint_t SENTINEL = INVALID;
+ typedef hb_codepoint_t value_t;
+ value_t operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ /* Projection. */
+ hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); }
+
void clear ()
{
if (items) memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t));
@@ -182,7 +176,7 @@ struct hb_map_t
unsigned int bucket_for (hb_codepoint_t key) const
{
- unsigned int i = Hash (key) % prime;
+ unsigned int i = hb_hash (key) % prime;
unsigned int step = 0;
unsigned int tombstone = INVALID;
while (!items[i].is_unused ())
diff --git a/src/hb-meta.hh b/src/hb-meta.hh
new file mode 100644
index 000000000..6d9dd6b6c
--- /dev/null
+++ b/src/hb-meta.hh
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2018 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_META_HH
+#define HB_META_HH
+
+#include "hb.hh"
+
+
+/*
+ * C++ template meta-programming & fundamentals used with them.
+ */
+
+
+template static inline T*
+hb_addressof (const T& arg)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ /* https://en.cppreference.com/w/cpp/memory/addressof */
+ return reinterpret_cast(
+ &const_cast(
+ reinterpret_cast(arg)));
+#pragma GCC diagnostic pop
+}
+
+template static inline T hb_declval ();
+#define hb_declval(T) (hb_declval ())
+
+template struct hb_match_const { typedef T type; enum { value = false }; };
+template struct hb_match_const { typedef T type; enum { value = true }; };
+#define hb_remove_const(T) typename hb_match_const::type
+#define hb_is_const(T) hb_match_const::value
+template struct hb_match_reference { typedef T type; enum { value = false }; };
+template struct hb_match_reference { typedef T type; enum { value = true }; };
+#define hb_remove_reference(T) typename hb_match_reference::type
+#define hb_is_reference(T) hb_match_reference::value
+template struct hb_match_pointer { typedef T type; enum { value = false }; };
+template struct hb_match_pointer { typedef T type; enum { value = true }; };
+#define hb_remove_pointer(T) typename hb_match_pointer::type
+#define hb_is_pointer(T) hb_match_pointer::value
+
+
+/* Void! For when we need a expression-type of void. */
+struct hb_void_t { typedef void value; };
+
+/* Bool! For when we need to evaluate type-dependent expressions
+ * in a template argument. */
+template struct hb_bool_tt { enum { value = b }; };
+typedef hb_bool_tt hb_true_t;
+typedef hb_bool_tt hb_false_t;
+
+
+template
+struct hb_enable_if {};
+
+template
+struct hb_enable_if { typedef T type; };
+
+#define hb_enable_if(Cond) typename hb_enable_if<(Cond)>::type* = nullptr
+
+
+/*
+ * Meta-functions.
+ */
+
+template struct hb_is_signed;
+/* https://github.com/harfbuzz/harfbuzz/issues/1535 */
+template <> struct hb_is_signed { enum { value = true }; };
+template <> struct hb_is_signed { enum { value = true }; };
+template <> struct hb_is_signed { enum { value = true }; };
+template <> struct hb_is_signed { enum { value = true }; };
+template <> struct hb_is_signed { enum { value = false }; };
+template <> struct hb_is_signed { enum { value = false }; };
+template <> struct hb_is_signed { enum { value = false }; };
+template <> struct hb_is_signed { enum { value = false }; };
+#define hb_is_signed(T) hb_is_signed::value
+
+template struct hb_signedness_int;
+template <> struct hb_signedness_int { typedef unsigned int value; };
+template <> struct hb_signedness_int { typedef signed int value; };
+#define hb_signedness_int(T) hb_signedness_int::value
+
+template struct hb_is_integer { enum { value = false }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+template <> struct hb_is_integer { enum { value = true }; };
+#define hb_is_integer(T) hb_is_integer::value
+
+
+#endif /* HB_META_HH */
diff --git a/src/hb-null.hh b/src/hb-null.hh
index baddd99b5..9d23d50c3 100644
--- a/src/hb-null.hh
+++ b/src/hb-null.hh
@@ -28,6 +28,7 @@
#define HB_NULL_HH
#include "hb.hh"
+#include "hb-meta.hh"
/*
@@ -45,18 +46,16 @@
* https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
*/
-template struct _hb_bool_type {};
-
template
struct _hb_null_size
{ enum { value = sizeof (T) }; };
template
-struct _hb_null_size >
+struct _hb_null_size >
{ enum { value = T::null_size }; };
template
struct hb_null_size
-{ enum { value = _hb_null_size >::value }; };
+{ enum { value = _hb_null_size::value }; };
#define hb_null_size(T) hb_null_size::value
/* These doesn't belong here, but since is copy/paste from above, put it here. */
@@ -68,34 +67,15 @@ template