diff --git a/.travis.yml b/.travis.yml
index e2de5038d03137d901b2ec79246465105af3a1c0..fa9e5bc60ad7aeb0eda1567118c45d56ae21e87c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,6 +13,7 @@ env:
- NOCONFIGURE=1
# COVERITY_SCAN_TOKEN
- secure: "MRJtVu/fQoWNwMAamvIJBCX/1SMvEuEUk/ljAif/y2/3syyWgxFGp17UGnDILdoZYyCqTM+jQciY2P0nVqbjjOAUlML4QOAalqw8kPp8iTsnHUe+KOMVrOVP6p6qAQxk1im1O41cCMkmVKvk+NXe/on5euz6LGF2laHZaOAMoes="
+ - PROJECT_NAME="behdad/harfbuzz" # the project name on coverity
matrix:
include:
diff --git a/configure.ac b/configure.ac
index f77e0874295e418aed9cb17e7b67ce04594e339d..d8c38fe29f71609dcf8a63f4c8908ccb3277b926 100644
--- a/configure.ac
+++ b/configure.ac
@@ -57,11 +57,12 @@ m4_define([hb_libtool_current],
HB_LIBTOOL_VERSION_INFO=hb_libtool_current:hb_libtool_revision:hb_libtool_age
AC_SUBST(HB_LIBTOOL_VERSION_INFO)
-AC_ARG_WITH([stdcpp],
- [AS_HELP_STRING([--with-stdcpp],
- [Do not try suppressing linkage to libstdcpp])],,
- [with_stdcpp=no])
-AM_CONDITIONAL(WITHSTDCPP, [test "x$with_stdcpp" = "xyes"])
+AC_ARG_WITH([libstdc++],
+ [AS_HELP_STRING([--with-libstdc++=@<:@yes/no@:>@],
+ [Allow linking with libstdc++ @<:@default=no@:>@])],
+ [with_libstdcxx=$withval],
+ [with_libstdcxx=no])
+AM_CONDITIONAL(WITH_LIBSTDCXX, [test "x$with_libstdcxx" = "xyes"])
# Documentation
have_gtk_doc=false
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index a9b4d53eb5b028d286a38400de9731846a34edbe..91faa0b7590d52b0fc2a2c0d8ce1b56645555bd7 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -9,6 +9,7 @@ HB_EXTERN
hb-blob
hb_blob_create
hb_blob_create_sub_blob
+hb_blob_copy_writable_or_fail
hb_blob_destroy
hb_blob_get_data
hb_blob_get_data_writable
@@ -527,7 +528,9 @@ hb_set_intersect
hb_set_is_empty
hb_set_is_equal
hb_set_next
+hb_set_previous
hb_set_next_range
+hb_set_previous_range
hb_set_reference
hb_set_set
hb_set_set_user_data
diff --git a/src/Makefile.am b/src/Makefile.am
index 25728563639595967558ffa31c57b8fb2b92cb93..3b18ebd3e969aaadf26140f16d35bf612687563b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,8 @@ CLEANFILES =
DISTCLEANFILES =
MAINTAINERCLEANFILES =
DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
+TESTS =
+check_PROGRAMS =
# The following warning options are useful for debugging: -Wpadded
#AM_CXXFLAGS =
@@ -30,12 +32,13 @@ HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
HBHEADERS = $(HB_BASE_headers)
HBNODISTHEADERS = $(HB_NODIST_headers)
-if !WITHSTDCPP
+if WITH_LIBSTDCXX
+HBNOLIBCXXCFLAGS =
+else
# Make sure we don't link to libstdc++
-HBCFLAGS += -fno-rtti -fno-exceptions
-
-# No threadsafe statics and C++ as we do it ourselves
-HBCFLAGS += -fno-threadsafe-statics
+# No threadsafe statics in C++ as we do it ourselves
+HBNOLIBCXXFLAGS = -fno-threadsafe-statics -fno-rtti -fno-exceptions
+HBLIBCXXFLAGS = -fno-threadsafe-statics
endif
if HAVE_OT
@@ -126,27 +129,24 @@ export_symbols_icu = -export-symbols harfbuzz-icu.def
harfbuzz_icu_def_dependency = harfbuzz-icu.def
export_symbols_subset = -export-symbols harfbuzz-subset.def
harfbuzz_subset_def_dependency = harfbuzz-subset.def
-choosed_linker = $(CXXLINK)
+chosen_linker = $(CXXLINK)
else
-if WITHSTDCPP
-choosed_linker = $(CXXLINK)
+if WITH_LIBSTDCXX
+chosen_linker = $(CXXLINK)
else
if HAVE_GCC
# Use a C linker for GCC, not C++; Don't link to libstdc++
-choosed_linker = $(LINK)
+chosen_linker = $(LINK)
else
-choosed_linker = $(CXXLINK)
+chosen_linker = $(CXXLINK)
endif
endif
endif
-libharfbuzz_la_LINK = $(choosed_linker) $(libharfbuzz_la_LDFLAGS)
-libharfbuzz_icu_la_LINK = $(choosed_linker) $(libharfbuzz_icu_la_LDFLAGS)
-libharfbuzz_subset_la_LINK = $(choosed_linker) $(libharfbuzz_subset_la_LDFLAGS)
-
base_link_flags = $(AM_LDFLAGS) -lm -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
+libharfbuzz_la_LINK = $(chosen_linker) $(libharfbuzz_la_LDFLAGS)
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS) $(HBNODISTHEADERS)
-libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
+libharfbuzz_la_CPPFLAGS = $(HBCFLAGS) $(HBNOLIBCXXFLAGS)
libharfbuzz_la_LDFLAGS = $(base_link_flags) $(export_symbols)
libharfbuzz_la_LIBADD = $(HBLIBS)
EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
@@ -158,7 +158,7 @@ EXTRA_DIST += harfbuzz.pc.in
lib_LTLIBRARIES += libharfbuzz-subset.la
libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources)
-libharfbuzz_subset_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS)
+libharfbuzz_subset_la_CPPFLAGS = $(HBCFLAGS) $(HBNOLIBCXXFLAGS)
libharfbuzz_subset_la_LDFLAGS = $(base_link_flags) $(export_symbols_subset)
libharfbuzz_subset_la_LIBADD = libharfbuzz.la
EXTRA_libharfbuzz_subset_la_DEPENDENCIES = $(harfbuzz_subset_def_dependency)
@@ -178,9 +178,9 @@ FUZZING_CPPFLAGS = \
-DHB_BUFFER_MAX_OPS_DEFAULT=1024 \
$(NULL)
EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la
-libharfbuzz_fuzzing_la_LINK = $(libharfbuzz_la_LINK)
+libharfbuzz_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_fuzzing_la_LDFLAGS)
libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES)
-libharfbuzz_fuzzing_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(FUZZING_CPPFLAGS)
+libharfbuzz_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(HBLIBCXXFLAGS) $(FUZZING_CPPFLAGS)
libharfbuzz_fuzzing_la_LDFLAGS = $(AM_LDFLAGS)
libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
@@ -195,7 +195,7 @@ HBHEADERS += $(HB_ICU_headers)
else
lib_LTLIBRARIES += libharfbuzz-icu.la
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
-libharfbuzz_icu_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(ICU_CFLAGS)
+libharfbuzz_icu_la_CPPFLAGS = $(HBCFLAGS) $(HBLIBCXXFLAGS) $(ICU_CFLAGS)
libharfbuzz_icu_la_LDFLAGS = $(base_link_flags) $(export_symbols_icu)
libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency)
@@ -207,11 +207,11 @@ EXTRA_DIST += harfbuzz-icu.pc.in
if HAVE_GOBJECT
lib_LTLIBRARIES += libharfbuzz-gobject.la
-libharfbuzz_gobject_la_LINK = $(libharfbuzz_la_LINK)
+libharfbuzz_gobject_la_LINK = $(chosen_linker) $(libharfbuzz_gobject_la_LDFLAGS)
libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_sources)
nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_ENUM_sources)
-libharfbuzz_gobject_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(GOBJECT_CFLAGS)
-libharfbuzz_gobject_la_LDFLAGS = $(libharfbuzz_la_LDFLAGS)
+libharfbuzz_gobject_la_CPPFLAGS = $(HBCFLAGS) $(HBNOLIBCXXFLAGS) $(GOBJECT_CFLAGS)
+libharfbuzz_gobject_la_LDFLAGS = $(base_link_flags)
libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la
pkginclude_HEADERS += $(HB_GOBJECT_headers)
nodist_pkginclude_HEADERS += $(HB_GOBJECT_ENUM_headers)
@@ -340,19 +340,42 @@ dist_check_SCRIPTS = \
check-externs.sh \
check-header-guards.sh \
check-includes.sh \
- check-libstdc++.sh \
check-static-inits.sh \
check-symbols.sh \
$(NULL)
+TESTS += $(dist_check_SCRIPTS)
+
+if !WITH_LIBSTDCXX
+dist_check_SCRIPTS += \
+ check-libstdc++.sh \
+ $(NULL)
+endif
-check_PROGRAMS = \
- test-ot-tag \
+check_PROGRAMS += \
+ dump-indic-data \
+ dump-khmer-data \
+ dump-myanmar-data \
+ dump-use-data \
$(NULL)
+dump_indic_data_SOURCES = dump-indic-data.cc hb-ot-shape-complex-indic-table.cc
+dump_indic_data_CPPFLAGS = $(HBCFLAGS)
+dump_indic_data_LDADD = libharfbuzz.la $(HBLIBS)
+dump_khmer_data_SOURCES = dump-khmer-data.cc hb-ot-shape-complex-indic-table.cc
+dump_khmer_data_CPPFLAGS = $(HBCFLAGS)
+dump_khmer_data_LDADD = libharfbuzz.la $(HBLIBS)
+dump_myanmar_data_SOURCES = dump-myanmar-data.cc hb-ot-shape-complex-indic-table.cc
+dump_myanmar_data_CPPFLAGS = $(HBCFLAGS)
+dump_myanmar_data_LDADD = libharfbuzz.la $(HBLIBS)
+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)
+
+check_PROGRAMS += test-ot-tag
+TESTS += test-ot-tag
test_ot_tag_SOURCES = hb-ot-tag.cc
test_ot_tag_CPPFLAGS = $(HBCFLAGS) -DMAIN
test_ot_tag_LDADD = libharfbuzz.la $(HBLIBS)
-TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS)
TESTS_ENVIRONMENT = \
srcdir="$(srcdir)" \
MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
diff --git a/src/Makefile.sources b/src/Makefile.sources
index f2821e3de2819d6aefd0e3dfaa53b2d16102cc16..ec60ec0a6ea5729dcd2d1253dd49751e3e731558 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -109,7 +109,9 @@ HB_OT_sources = \
hb-ot-shape-complex-indic.cc \
hb-ot-shape-complex-indic-private.hh \
hb-ot-shape-complex-indic-table.cc \
+ hb-ot-shape-complex-khmer-private.hh \
hb-ot-shape-complex-khmer.cc \
+ hb-ot-shape-complex-myanmar-private.hh \
hb-ot-shape-complex-myanmar.cc \
hb-ot-shape-complex-thai.cc \
hb-ot-shape-complex-tibetan.cc \
@@ -185,6 +187,7 @@ HB_ICU_headers = hb-icu.h
HB_SUBSET_sources = \
hb-subset.cc \
hb-subset-glyf.cc \
+ hb-subset-input.cc \
hb-subset-plan.cc \
$(NULL)
diff --git a/src/check-libstdc++.sh b/src/check-libstdc++.sh
index a7b4c495ffb4443c13b08e38cb3e562b003fcbd9..ce0bdab755f9ac5bbf1d1e68abac3fa1bbb13457 100755
--- a/src/check-libstdc++.sh
+++ b/src/check-libstdc++.sh
@@ -22,7 +22,8 @@ fi
tested=false
# harfbuzz-icu links to libstdc++ because icu does.
-for soname in harfbuzz harfbuzz-subset harfbuzz-gobject; do
+# harfbuzz-subset uses libstdc++.
+for soname in harfbuzz harfbuzz-gobject; do
for suffix in so dylib; do
so=$libs/lib$soname.$suffix
if ! test -f "$so"; then continue; fi
diff --git a/src/dump-indic-data.cc b/src/dump-indic-data.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d57413884be3b4603d7bc6a288e27c75355b54cd
--- /dev/null
+++ b/src/dump-indic-data.cc
@@ -0,0 +1,43 @@
+/*
+ * 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
+ */
+
+#include "hb-ot-shape-complex-indic-private.hh"
+
+int
+main (void)
+{
+ for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
+ {
+ hb_glyph_info_t info;
+ info.codepoint = u;
+ set_indic_properties (info);
+ if (info.indic_category() != INDIC_SYLLABIC_CATEGORY_OTHER ||
+ info.indic_position() != INDIC_MATRA_CATEGORY_NOT_APPLICABLE)
+ printf("U+%04X %u %u\n", u,
+ info.indic_category(),
+ info.indic_position());
+ }
+}
diff --git a/src/dump-khmer-data.cc b/src/dump-khmer-data.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7dd09b2b5ca57a6b710796d942d433492e3418a9
--- /dev/null
+++ b/src/dump-khmer-data.cc
@@ -0,0 +1,43 @@
+/*
+ * 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
+ */
+
+#include "hb-ot-shape-complex-khmer-private.hh"
+
+int
+main (void)
+{
+ for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
+ {
+ hb_glyph_info_t info;
+ info.codepoint = u;
+ set_khmer_properties (info);
+ if (info.khmer_category() != INDIC_SYLLABIC_CATEGORY_OTHER ||
+ info.khmer_position() != INDIC_MATRA_CATEGORY_NOT_APPLICABLE)
+ printf("U+%04X %u %u\n", u,
+ info.khmer_category(),
+ info.khmer_position());
+ }
+}
diff --git a/src/dump-myanmar-data.cc b/src/dump-myanmar-data.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2df9cd987f341a7471b5b40cb1ac57f76efffebc
--- /dev/null
+++ b/src/dump-myanmar-data.cc
@@ -0,0 +1,43 @@
+/*
+ * 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
+ */
+
+#include "hb-ot-shape-complex-myanmar-private.hh"
+
+int
+main (void)
+{
+ for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
+ {
+ hb_glyph_info_t info;
+ info.codepoint = u;
+ set_myanmar_properties (info);
+ if (info.myanmar_category() != INDIC_SYLLABIC_CATEGORY_OTHER ||
+ info.myanmar_position() != INDIC_MATRA_CATEGORY_NOT_APPLICABLE)
+ printf("U+%04X %u %u\n", u,
+ info.myanmar_category(),
+ info.myanmar_position());
+ }
+}
diff --git a/src/dump-use-data.cc b/src/dump-use-data.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0e64688f1e06f202fed4cec79a9d942d6cf50544
--- /dev/null
+++ b/src/dump-use-data.cc
@@ -0,0 +1,38 @@
+/*
+ * 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
+ */
+
+#include "hb-ot-shape-complex-use-private.hh"
+
+int
+main (void)
+{
+ for (hb_codepoint_t u = 0; u <= 0x10FFFF; u++)
+ {
+ unsigned int category = hb_use_get_category (u);
+ if (category != USE_O)
+ printf("U+%04X %u\n", u, category);
+ }
+}
diff --git a/src/gen-use-table.py b/src/gen-use-table.py
index 5391f27eb3e18e74b2f4a4801bd8fe1d72ad906a..06817255c92c5dfd134e5390ef3f63eb234c83b4 100755
--- a/src/gen-use-table.py
+++ b/src/gen-use-table.py
@@ -449,7 +449,7 @@ page_bits = 12
print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy)
print
print "USE_TABLE_ELEMENT_TYPE"
-print "hb_use_get_categories (hb_codepoint_t u)"
+print "hb_use_get_category (hb_codepoint_t u)"
print "{"
print " switch (u >> %d)" % page_bits
print " {"
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 2bb80891335f87e090a45c4be7e05f0e5217a022..4cc2824214e4325accf259bfa72ce65b71df2506 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -40,6 +40,8 @@ using namespace OT;
struct RearrangementSubtable
{
+ typedef void EntryData;
+
struct driver_context_t
{
static const bool in_place = true;
@@ -60,13 +62,13 @@ struct RearrangementSubtable
ret (false),
start (0), end (0) {}
- inline bool is_actionable (StateTableDriver *driver,
- const Entry *entry)
+ inline bool is_actionable (StateTableDriver *driver,
+ const Entry *entry)
{
return (entry->flags & Verb) && start < end;
}
- inline bool transition (StateTableDriver *driver,
- const Entry *entry)
+ inline bool transition (StateTableDriver *driver,
+ const Entry *entry)
{
hb_buffer_t *buffer = driver->buffer;
unsigned int flags = entry->flags;
@@ -169,7 +171,7 @@ struct RearrangementSubtable
}
protected:
- StateTable machine;
+ StateTable machine;
public:
DEFINE_SIZE_STATIC (16);
};
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 80460125826a8764b1e8ccd7423d0647a4c74043..b5291f650cc81fb74fb01725250170169de638c3 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -170,6 +170,31 @@ hb_blob_create_sub_blob (hb_blob_t *parent,
return blob;
}
+/**
+ * hb_blob_copy_writable_or_fail:
+ * @blob: A blob.
+ *
+ * Makes a writable copy of @blob.
+ *
+ * Return value: New blob, or nullptr if allocation failed.
+ *
+ * Since: 1.8.0
+ **/
+hb_blob_t *
+hb_blob_copy_writable_or_fail (hb_blob_t *blob)
+{
+ blob = hb_blob_create (blob->data,
+ blob->length,
+ HB_MEMORY_MODE_DUPLICATE,
+ nullptr,
+ nullptr);
+
+ if (unlikely (blob == hb_blob_get_empty ()))
+ blob = nullptr;
+
+ return blob;
+}
+
/**
* hb_blob_get_empty:
*
diff --git a/src/hb-blob.h b/src/hb-blob.h
index 53682d3eb1c94333b0e514d204db86ef0d695ac8..fd561f73869740eb6e02e1056a134630c551d788 100644
--- a/src/hb-blob.h
+++ b/src/hb-blob.h
@@ -82,6 +82,9 @@ hb_blob_create_sub_blob (hb_blob_t *parent,
unsigned int offset,
unsigned int length);
+HB_EXTERN hb_blob_t *
+hb_blob_copy_writable_or_fail (hb_blob_t *blob);
+
HB_EXTERN hb_blob_t *
hb_blob_get_empty (void);
diff --git a/src/hb-face.h b/src/hb-face.h
index 9842d52b650034b7010d3a77b0274e40257dce39..0ce8d0462d5cb3fc39bc271ea3e0ea7cd140545a 100644
--- a/src/hb-face.h
+++ b/src/hb-face.h
@@ -71,7 +71,6 @@ hb_face_set_user_data (hb_face_t *face,
hb_destroy_func_t destroy,
hb_bool_t replace);
-
HB_EXTERN void *
hb_face_get_user_data (hb_face_t *face,
hb_user_data_key_t *key);
diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh
index 6c2b9a88ee1388bf46656dd899bc4896167ac148..e4519529b1e4e228981d6fd7227a38fe24a472f7 100644
--- a/src/hb-ot-cbdt-table.hh
+++ b/src/hb-ot-cbdt-table.hh
@@ -377,7 +377,7 @@ struct CBDT
{
inline void init (hb_face_t *face)
{
- upem = face->get_upem();
+ upem = hb_face_get_upem (face);
cblc_blob = Sanitizer().sanitize (face->reference_table (HB_OT_TAG_CBLC));
cbdt_blob = Sanitizer().sanitize (face->reference_table (HB_OT_TAG_CBDT));
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index eed489026116be4bd0cf317899de06d92544acc2..b4ba2490ca4dc7d25aff5a9d27822a9f6b677d61 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -69,7 +69,7 @@ struct hmtxvmtx
inline void init (hb_face_t *face,
unsigned int default_advance_ = 0)
{
- default_advance = default_advance_ ? default_advance_ : face->get_upem ();
+ default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
bool got_font_extents = false;
if (T::os2Tag)
diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh
index a64e9d03919d2e32a743af5bc0a5595de9b22fca..867b936278beb6e18c72853a68c2a9ae57c22d7c 100644
--- a/src/hb-ot-shape-complex-indic-private.hh
+++ b/src/hb-ot-shape-complex-indic-private.hh
@@ -34,6 +34,11 @@
#include "hb-ot-shape-private.hh" /* XXX Remove */
+/* buffer var allocations */
+#define indic_category() complex_var_u8_0() /* indic_category_t */
+#define indic_position() complex_var_u8_1() /* indic_position_t */
+
+
#define INDIC_TABLE_ELEMENT_TYPE uint16_t
/* Cateories used in the OpenType spec:
@@ -77,29 +82,29 @@ enum indic_category_t {
/* Visual positions in a syllable from left to right. */
enum indic_position_t {
- POS_START,
+ POS_START = 0,
- POS_RA_TO_BECOME_REPH,
- POS_PRE_M,
- POS_PRE_C,
+ POS_RA_TO_BECOME_REPH = 1,
+ POS_PRE_M = 2,
+ POS_PRE_C = 3,
- POS_BASE_C,
- POS_AFTER_MAIN,
+ POS_BASE_C = 4,
+ POS_AFTER_MAIN = 5,
- POS_ABOVE_C,
+ POS_ABOVE_C = 6,
- POS_BEFORE_SUB,
- POS_BELOW_C,
- POS_AFTER_SUB,
+ POS_BEFORE_SUB = 7,
+ POS_BELOW_C = 8,
+ POS_AFTER_SUB = 9,
- POS_BEFORE_POST,
- POS_POST_C,
- POS_AFTER_POST,
+ POS_BEFORE_POST = 10,
+ POS_POST_C = 11,
+ POS_AFTER_POST = 12,
- POS_FINAL_C,
- POS_SMVD,
+ POS_FINAL_C = 13,
+ POS_SMVD = 14,
- POS_END
+ POS_END = 15
};
/* Categories used in IndicSyllabicCategory.txt from UCD. */
@@ -186,4 +191,211 @@ enum indic_matra_category_t {
HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
hb_indic_get_categories (hb_codepoint_t u);
+
+static inline bool
+is_one_of (const hb_glyph_info_t &info, unsigned int flags)
+{
+ /* If it ligated, all bets are off. */
+ if (_hb_glyph_info_ligated (&info)) return false;
+ return !!(FLAG_UNSAFE (info.indic_category()) & flags);
+}
+
+static inline bool
+is_joiner (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, JOINER_FLAGS);
+}
+
+static inline bool
+is_consonant (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, CONSONANT_FLAGS);
+}
+
+static inline bool
+is_halant (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, FLAG (OT_H));
+}
+
+#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
+
+#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
+#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
+#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
+#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
+#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
+#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
+#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
+#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
+#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
+#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
+
+
+#define MATRA_POS_LEFT(u) POS_PRE_M
+#define MATRA_POS_RIGHT(u) ( \
+ IS_DEVA(u) ? POS_AFTER_SUB : \
+ IS_BENG(u) ? POS_AFTER_POST : \
+ IS_GURU(u) ? POS_AFTER_POST : \
+ IS_GUJR(u) ? POS_AFTER_POST : \
+ IS_ORYA(u) ? POS_AFTER_POST : \
+ IS_TAML(u) ? POS_AFTER_POST : \
+ IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+ IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+ IS_MLYM(u) ? POS_AFTER_POST : \
+ IS_SINH(u) ? POS_AFTER_SUB : \
+ /*default*/ POS_AFTER_SUB \
+ )
+#define MATRA_POS_TOP(u) ( /* BENG and MLYM don't have top matras. */ \
+ IS_DEVA(u) ? POS_AFTER_SUB : \
+ IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
+ IS_GUJR(u) ? POS_AFTER_SUB : \
+ IS_ORYA(u) ? POS_AFTER_MAIN : \
+ IS_TAML(u) ? POS_AFTER_SUB : \
+ IS_TELU(u) ? POS_BEFORE_SUB : \
+ IS_KNDA(u) ? POS_BEFORE_SUB : \
+ IS_SINH(u) ? POS_AFTER_SUB : \
+ /*default*/ POS_AFTER_SUB \
+ )
+#define MATRA_POS_BOTTOM(u) ( \
+ IS_DEVA(u) ? POS_AFTER_SUB : \
+ IS_BENG(u) ? POS_AFTER_SUB : \
+ IS_GURU(u) ? POS_AFTER_POST : \
+ IS_GUJR(u) ? POS_AFTER_POST : \
+ IS_ORYA(u) ? POS_AFTER_SUB : \
+ IS_TAML(u) ? POS_AFTER_POST : \
+ IS_TELU(u) ? POS_BEFORE_SUB : \
+ IS_KNDA(u) ? POS_BEFORE_SUB : \
+ IS_MLYM(u) ? POS_AFTER_POST : \
+ IS_SINH(u) ? POS_AFTER_SUB : \
+ /*default*/ POS_AFTER_SUB \
+ )
+
+static inline indic_position_t
+matra_position_indic (hb_codepoint_t u, indic_position_t side)
+{
+ switch ((int) side)
+ {
+ case POS_PRE_C: return MATRA_POS_LEFT (u);
+ case POS_POST_C: return MATRA_POS_RIGHT (u);
+ case POS_ABOVE_C: return MATRA_POS_TOP (u);
+ case POS_BELOW_C: return MATRA_POS_BOTTOM (u);
+ };
+ return side;
+}
+
+/* XXX
+ * This is a hack for now. We should move this data into the main Indic table.
+ * Or completely remove it and just check in the tables.
+ */
+static const hb_codepoint_t ra_chars[] = {
+ 0x0930u, /* Devanagari */
+ 0x09B0u, /* Bengali */
+ 0x09F0u, /* Bengali */
+ 0x0A30u, /* Gurmukhi */ /* No Reph */
+ 0x0AB0u, /* Gujarati */
+ 0x0B30u, /* Oriya */
+ 0x0BB0u, /* Tamil */ /* No Reph */
+ 0x0C30u, /* Telugu */ /* Reph formed only with ZWJ */
+ 0x0CB0u, /* Kannada */
+ 0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
+
+ 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
+};
+
+static inline bool
+is_ra (hb_codepoint_t u)
+{
+ for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
+ if (u == ra_chars[i])
+ return true;
+ return false;
+}
+
+static inline void
+set_indic_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+ indic_category_t cat = (indic_category_t) (type & 0x7Fu);
+ indic_position_t pos = (indic_position_t) (type >> 8);
+
+
+ /*
+ * Re-assign category
+ */
+
+ /* The following act more like the Bindus. */
+ if (unlikely (hb_in_range (u, 0x0953u, 0x0954u)))
+ cat = OT_SM;
+ /* The following act like consonants. */
+ else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u,
+ 0x1CF5u, 0x1CF6u)))
+ cat = OT_C;
+ /* TODO: The following should only be allowed after a Visarga.
+ * For now, just treat them like regular tone marks. */
+ else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u)))
+ cat = OT_A;
+ /* TODO: The following should only be allowed after some of
+ * the nasalization marks, maybe only for U+1CE9..U+1CF1.
+ * For now, just treat them like tone marks. */
+ else if (unlikely (u == 0x1CEDu))
+ cat = OT_A;
+ /* The following take marks in standalone clusters, similar to Avagraha. */
+ else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u,
+ 0x1CE9u, 0x1CECu,
+ 0x1CEEu, 0x1CF1u)))
+ {
+ cat = OT_Symbol;
+ static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
+ }
+ else if (unlikely (u == 0x0A51u))
+ {
+ /* https://github.com/harfbuzz/harfbuzz/issues/524 */
+ cat = OT_M;
+ pos = POS_BELOW_C;
+ }
+
+ /* 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 == 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/harfbuzz/harfbuzz/issues/552 */
+
+ else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
+ else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
+ else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u)))
+ cat = OT_PLACEHOLDER;
+ else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
+
+
+ /*
+ * Re-assign position.
+ */
+
+ if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
+ {
+ pos = POS_BASE_C;
+ if (is_ra (u))
+ cat = OT_Ra;
+ }
+ else if (cat == OT_M)
+ {
+ pos = matra_position_indic (u, pos);
+ }
+ else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
+ {
+ pos = POS_SMVD;
+ }
+
+ if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
+
+
+
+ info.indic_category() = cat;
+ info.indic_position() = pos;
+}
+
+
#endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 9d150e0d3c13fe66304d96f4de26543aabbd9eb4..32ad86a5f32735ae29f27ed1af1a9648c2e0e690 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -27,226 +27,12 @@
#include "hb-ot-shape-complex-indic-private.hh"
#include "hb-ot-layout-private.hh"
-/* buffer var allocations */
-#define indic_category() complex_var_u8_0() /* indic_category_t */
-#define indic_position() complex_var_u8_1() /* indic_position_t */
-
/*
* Indic shaper.
*/
-#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
-
-#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
-#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
-#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
-#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
-#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
-#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
-#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
-#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
-#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
-#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
-
-
-#define MATRA_POS_LEFT(u) POS_PRE_M
-#define MATRA_POS_RIGHT(u) ( \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_BENG(u) ? POS_AFTER_POST : \
- IS_GURU(u) ? POS_AFTER_POST : \
- IS_GUJR(u) ? POS_AFTER_POST : \
- IS_ORYA(u) ? POS_AFTER_POST : \
- IS_TAML(u) ? POS_AFTER_POST : \
- IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
- IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
- IS_MLYM(u) ? POS_AFTER_POST : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-#define MATRA_POS_TOP(u) ( /* BENG and MLYM don't have top matras. */ \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
- IS_GUJR(u) ? POS_AFTER_SUB : \
- IS_ORYA(u) ? POS_AFTER_MAIN : \
- IS_TAML(u) ? POS_AFTER_SUB : \
- IS_TELU(u) ? POS_BEFORE_SUB : \
- IS_KNDA(u) ? POS_BEFORE_SUB : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-#define MATRA_POS_BOTTOM(u) ( \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_BENG(u) ? POS_AFTER_SUB : \
- IS_GURU(u) ? POS_AFTER_POST : \
- IS_GUJR(u) ? POS_AFTER_POST : \
- IS_ORYA(u) ? POS_AFTER_SUB : \
- IS_TAML(u) ? POS_AFTER_POST : \
- IS_TELU(u) ? POS_BEFORE_SUB : \
- IS_KNDA(u) ? POS_BEFORE_SUB : \
- IS_MLYM(u) ? POS_AFTER_POST : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-
-static inline indic_position_t
-matra_position (hb_codepoint_t u, indic_position_t side)
-{
- switch ((int) side)
- {
- case POS_PRE_C: return MATRA_POS_LEFT (u);
- case POS_POST_C: return MATRA_POS_RIGHT (u);
- case POS_ABOVE_C: return MATRA_POS_TOP (u);
- case POS_BELOW_C: return MATRA_POS_BOTTOM (u);
- };
- return side;
-}
-
-/* XXX
- * This is a hack for now. We should move this data into the main Indic table.
- * Or completely remove it and just check in the tables.
- */
-static const hb_codepoint_t ra_chars[] = {
- 0x0930u, /* Devanagari */
- 0x09B0u, /* Bengali */
- 0x09F0u, /* Bengali */
- 0x0A30u, /* Gurmukhi */ /* No Reph */
- 0x0AB0u, /* Gujarati */
- 0x0B30u, /* Oriya */
- 0x0BB0u, /* Tamil */ /* No Reph */
- 0x0C30u, /* Telugu */ /* Reph formed only with ZWJ */
- 0x0CB0u, /* Kannada */
- 0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
-
- 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
-};
-
-static inline bool
-is_ra (hb_codepoint_t u)
-{
- for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
- if (u == ra_chars[i])
- return true;
- return false;
-}
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
- /* If it ligated, all bets are off. */
- if (_hb_glyph_info_ligated (&info)) return false;
- return !!(FLAG_UNSAFE (info.indic_category()) & flags);
-}
-
-static inline bool
-is_joiner (const hb_glyph_info_t &info)
-{
- return is_one_of (info, JOINER_FLAGS);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, CONSONANT_FLAGS);
-}
-
-static inline bool
-is_halant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, FLAG (OT_H));
-}
-
-static inline void
-set_indic_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- indic_category_t cat = (indic_category_t) (type & 0x7Fu);
- indic_position_t pos = (indic_position_t) (type >> 8);
-
-
- /*
- * Re-assign category
- */
-
- /* The following act more like the Bindus. */
- if (unlikely (hb_in_range (u, 0x0953u, 0x0954u)))
- cat = OT_SM;
- /* The following act like consonants. */
- else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u,
- 0x1CF5u, 0x1CF6u)))
- cat = OT_C;
- /* TODO: The following should only be allowed after a Visarga.
- * For now, just treat them like regular tone marks. */
- else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u)))
- cat = OT_A;
- /* TODO: The following should only be allowed after some of
- * the nasalization marks, maybe only for U+1CE9..U+1CF1.
- * For now, just treat them like tone marks. */
- else if (unlikely (u == 0x1CEDu))
- cat = OT_A;
- /* The following take marks in standalone clusters, similar to Avagraha. */
- else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u,
- 0x1CE9u, 0x1CECu,
- 0x1CEEu, 0x1CF1u)))
- {
- cat = OT_Symbol;
- static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
- }
- else if (unlikely (u == 0x0A51u))
- {
- /* https://github.com/harfbuzz/harfbuzz/issues/524 */
- cat = OT_M;
- pos = POS_BELOW_C;
- }
-
- /* 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 == 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/harfbuzz/harfbuzz/issues/552 */
-
- else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
- else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
- else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u)))
- cat = OT_PLACEHOLDER;
- else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
- /*
- * Re-assign position.
- */
-
- if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
- {
- pos = POS_BASE_C;
- if (is_ra (u))
- cat = OT_Ra;
- }
- else if (cat == OT_M)
- {
- pos = matra_position (u, pos);
- }
- else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
- {
- pos = POS_SMVD;
- }
-
- if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
-
-
-
- info.indic_category() = cat;
- info.indic_position() = pos;
-}
-
-/*
- * Things above this line should ideally be moved to the Indic table itself.
- */
-
-
/*
* Indic configurations. Note that we do not want to keep every single script-specific
* behavior in these tables necessarily. This should mainly be used for per-script
diff --git a/src/hb-ot-shape-complex-khmer-private.hh b/src/hb-ot-shape-complex-khmer-private.hh
new file mode 100644
index 0000000000000000000000000000000000000000..f90ef967440605a062231f4e4a0def8f74d70a19
--- /dev/null
+++ b/src/hb-ot-shape-complex-khmer-private.hh
@@ -0,0 +1,124 @@
+/*
+ * 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_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
+#define HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
+
+#include "hb-private.hh"
+
+#include "hb-ot-shape-complex-indic-private.hh"
+
+
+/* buffer var allocations */
+#define khmer_category() indic_category() /* khmer_category_t */
+#define khmer_position() indic_position() /* khmer_position_t */
+
+
+typedef indic_category_t khmer_category_t;
+typedef indic_position_t khmer_position_t;
+
+
+static inline khmer_position_t
+matra_position_khmer (khmer_position_t side)
+{
+ switch ((int) side)
+ {
+ case POS_PRE_C:
+ return POS_PRE_M;
+
+ case POS_POST_C:
+ case POS_ABOVE_C:
+ case POS_BELOW_C:
+ return POS_AFTER_POST;
+
+ default:
+ return side;
+ };
+}
+
+static inline bool
+is_consonant_or_vowel (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, CONSONANT_FLAGS | FLAG (OT_V));
+}
+
+static inline bool
+is_coeng (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, FLAG (OT_Coeng));
+}
+
+static inline void
+set_khmer_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+ khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
+ khmer_position_t pos = (khmer_position_t) (type >> 8);
+
+
+ /*
+ * Re-assign category
+ */
+
+ if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
+ else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) ||
+ u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
+ {
+ /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier.
+ * https://github.com/roozbehp/unicode-data/issues/5 */
+ cat = OT_M;
+ pos = POS_ABOVE_C;
+ }
+ else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) cat = OT_PLACEHOLDER;
+ else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
+
+
+ /*
+ * Re-assign position.
+ */
+
+ if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
+ {
+ pos = POS_BASE_C;
+ if (u == 0x179Au)
+ cat = OT_Ra;
+ }
+ else if (cat == OT_M)
+ {
+ pos = matra_position_khmer (pos);
+ }
+ else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) | FLAG (OT_A) | FLAG (OT_Symbol))))
+ {
+ pos = POS_SMVD;
+ }
+
+ info.khmer_category() = cat;
+ info.khmer_position() = pos;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH */
diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc
index 2db4f6097d81a0730253536f634b200a0f80fc41..304879d8fbbe7d0420faf8dd006ad6acc5afa00c 100644
--- a/src/hb-ot-shape-complex-khmer.cc
+++ b/src/hb-ot-shape-complex-khmer.cc
@@ -24,119 +24,9 @@
* Google Author(s): Behdad Esfahbod
*/
-#include "hb-ot-shape-complex-indic-private.hh"
+#include "hb-ot-shape-complex-khmer-private.hh"
#include "hb-ot-layout-private.hh"
-/* buffer var allocations */
-#define khmer_category() complex_var_u8_0() /* khmer_category_t */
-#define khmer_position() complex_var_u8_1() /* khmer_position_t */
-
-
-/*
- * Khmer shaper.
- */
-
-typedef indic_category_t khmer_category_t;
-typedef indic_position_t khmer_position_t;
-
-
-static inline khmer_position_t
-matra_position (khmer_position_t side)
-{
- switch ((int) side)
- {
- case POS_PRE_C:
- return POS_PRE_M;
-
- case POS_POST_C:
- case POS_ABOVE_C:
- case POS_BELOW_C:
- return POS_AFTER_POST;
-
- default:
- return side;
- };
-}
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
- /* If it ligated, all bets are off. */
- if (_hb_glyph_info_ligated (&info)) return false;
- return !!(FLAG_UNSAFE (info.khmer_category()) & flags);
-}
-
-static inline bool
-is_joiner (const hb_glyph_info_t &info)
-{
- return is_one_of (info, JOINER_FLAGS);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, CONSONANT_FLAGS | FLAG (OT_V));
-}
-
-static inline bool
-is_coeng (const hb_glyph_info_t &info)
-{
- return is_one_of (info, FLAG (OT_Coeng));
-}
-
-static inline void
-set_khmer_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
- khmer_position_t pos = (khmer_position_t) (type >> 8);
-
-
- /*
- * Re-assign category
- */
-
- if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
- else if (unlikely (hb_in_range (u, 0x17CDu, 0x17D1u) ||
- u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
- {
- /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier.
- * https://github.com/roozbehp/unicode-data/issues/5 */
- cat = OT_M;
- pos = POS_ABOVE_C;
- }
- else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) cat = OT_PLACEHOLDER;
- else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
- /*
- * Re-assign position.
- */
-
- if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
- {
- pos = POS_BASE_C;
- if (u == 0x179Au)
- cat = OT_Ra;
- }
- else if (cat == OT_M)
- {
- pos = matra_position (pos);
- }
- else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) | FLAG (OT_A) | FLAG (OT_Symbol))))
- {
- pos = POS_SMVD;
- }
-
- info.khmer_category() = cat;
- info.khmer_position() = pos;
-}
-
-/*
- * Things above this line should ideally be moved to the Indic table itself.
- */
-
/*
* Khmer shaper.
@@ -404,7 +294,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
/* Mark all subsequent consonants as below. */
for (unsigned int i = base + 1; i < end; i++)
- if (is_consonant (info[i]))
+ if (is_consonant_or_vowel (info[i]))
info[i].khmer_position() = POS_BELOW_C;
/* Mark final consonants. A final consonant is one appearing after a matra,
@@ -412,7 +302,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
for (unsigned int i = base + 1; i < end; i++)
if (info[i].khmer_category() == OT_M) {
for (unsigned int j = i + 1; j < end; j++)
- if (is_consonant (info[j])) {
+ if (is_consonant_or_vowel (info[j])) {
info[j].khmer_position() = POS_FINAL_C;
break;
}
@@ -455,7 +345,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
{
unsigned int last = base;
for (unsigned int i = base + 1; i < end; i++)
- if (is_consonant (info[i]))
+ if (is_consonant_or_vowel (info[i]))
{
for (unsigned int j = last + 1; j < i; j++)
if (info[j].khmer_position() < POS_SMVD)
diff --git a/src/hb-ot-shape-complex-myanmar-private.hh b/src/hb-ot-shape-complex-myanmar-private.hh
new file mode 100644
index 0000000000000000000000000000000000000000..04f81bd12275abefbaf796add3642b78502fef29
--- /dev/null
+++ b/src/hb-ot-shape-complex-myanmar-private.hh
@@ -0,0 +1,171 @@
+/*
+ * 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_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
+#define HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
+
+#include "hb-private.hh"
+
+#include "hb-ot-shape-complex-indic-private.hh"
+
+
+/* buffer var allocations */
+#define myanmar_category() indic_category() /* myanmar_category_t */
+#define myanmar_position() indic_position() /* myanmar_position_t */
+
+
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum myanmar_category_t {
+ OT_As = 18, /* Asat */
+ OT_D0 = 20, /* Digit zero */
+ OT_DB = OT_N, /* Dot below */
+ OT_GB = OT_PLACEHOLDER,
+ OT_MH = 21, /* Various consonant medial types */
+ OT_MR = 22, /* Various consonant medial types */
+ OT_MW = 23, /* Various consonant medial types */
+ OT_MY = 24, /* Various consonant medial types */
+ OT_PT = 25, /* Pwo and other tones */
+ OT_VAbv = 26,
+ OT_VBlw = 27,
+ OT_VPre = 28,
+ OT_VPst = 29,
+ OT_VS = 30, /* Variation selectors */
+ OT_P = 31, /* Punctuation */
+ OT_D = 32, /* Digits except zero */
+};
+
+
+static inline void
+set_myanmar_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+ indic_category_t cat = (indic_category_t) (type & 0x7Fu);
+ indic_position_t pos = (indic_position_t) (type >> 8);
+
+ /* Myanmar
+ * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze
+ */
+ if (unlikely (hb_in_range (u, 0xFE00u, 0xFE0Fu)))
+ cat = (indic_category_t) OT_VS;
+
+ switch (u)
+ {
+ case 0x104Eu:
+ cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
+ break;
+
+ case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
+ case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
+ case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
+ case 0x25FEu:
+ cat = (indic_category_t) OT_GB;
+ break;
+
+ case 0x1004u: case 0x101Bu: case 0x105Au:
+ cat = (indic_category_t) OT_Ra;
+ break;
+
+ case 0x1032u: case 0x1036u:
+ cat = (indic_category_t) OT_A;
+ break;
+
+ case 0x1039u:
+ cat = (indic_category_t) OT_H;
+ break;
+
+ case 0x103Au:
+ cat = (indic_category_t) OT_As;
+ break;
+
+ case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
+ case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
+ case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
+ case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
+ case 0x1097u: case 0x1098u: case 0x1099u:
+ cat = (indic_category_t) OT_D;
+ break;
+
+ case 0x1040u:
+ cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
+ break;
+
+ case 0x103Eu: case 0x1060u:
+ cat = (indic_category_t) OT_MH;
+ break;
+
+ case 0x103Cu:
+ cat = (indic_category_t) OT_MR;
+ break;
+
+ case 0x103Du: case 0x1082u:
+ cat = (indic_category_t) OT_MW;
+ break;
+
+ case 0x103Bu: case 0x105Eu: case 0x105Fu:
+ cat = (indic_category_t) OT_MY;
+ break;
+
+ case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
+ case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
+ cat = (indic_category_t) OT_PT;
+ break;
+
+ case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
+ case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
+ case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
+ cat = (indic_category_t) OT_SM;
+ break;
+
+ case 0x104Au: case 0x104Bu:
+ cat = (indic_category_t) OT_P;
+ break;
+
+ case 0xAA74u: case 0xAA75u: case 0xAA76u:
+ /* https://github.com/roozbehp/unicode-data/issues/3 */
+ cat = (indic_category_t) OT_C;
+ break;
+ }
+
+ if (cat == OT_M)
+ {
+ switch ((int) pos)
+ {
+ case POS_PRE_C: cat = (indic_category_t) OT_VPre;
+ pos = POS_PRE_M; break;
+ case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break;
+ case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break;
+ case POS_POST_C: cat = (indic_category_t) OT_VPst; break;
+ }
+ }
+
+ info.myanmar_category() = (myanmar_category_t) cat;
+ info.myanmar_position() = pos;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH */
diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc
index 31bb976b1bbd62f88869d819b68a440c6b7c2911..3c57bc1ff66cf8a502aa38926d5e5d324161668e 100644
--- a/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/hb-ot-shape-complex-myanmar.cc
@@ -24,11 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#include "hb-ot-shape-complex-indic-private.hh"
-
-/* buffer var allocations */
-#define myanmar_category() complex_var_u8_0() /* myanmar_category_t */
-#define myanmar_position() complex_var_u8_1() /* myanmar_position_t */
+#include "hb-ot-shape-complex-myanmar-private.hh"
/*
@@ -127,153 +123,6 @@ enum syllable_type_t {
#include "hb-ot-shape-complex-myanmar-machine.hh"
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum myanmar_category_t {
- OT_As = 18, /* Asat */
- OT_D0 = 20, /* Digit zero */
- OT_DB = OT_N, /* Dot below */
- OT_GB = OT_PLACEHOLDER,
- OT_MH = 21, /* Various consonant medial types */
- OT_MR = 22, /* Various consonant medial types */
- OT_MW = 23, /* Various consonant medial types */
- OT_MY = 24, /* Various consonant medial types */
- OT_PT = 25, /* Pwo and other tones */
- OT_VAbv = 26,
- OT_VBlw = 27,
- OT_VPre = 28,
- OT_VPst = 29,
- OT_VS = 30, /* Variation selectors */
- OT_P = 31, /* Punctuation */
- OT_D = 32, /* Digits except zero */
-};
-
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
- /* If it ligated, all bets are off. */
- if (_hb_glyph_info_ligated (&info)) return false;
- return !!(FLAG_UNSAFE (info.myanmar_category()) & flags);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, CONSONANT_FLAGS);
-}
-
-
-static inline void
-set_myanmar_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- indic_category_t cat = (indic_category_t) (type & 0x7Fu);
- indic_position_t pos = (indic_position_t) (type >> 8);
-
- /* Myanmar
- * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze
- */
- if (unlikely (hb_in_range (u, 0xFE00u, 0xFE0Fu)))
- cat = (indic_category_t) OT_VS;
-
- switch (u)
- {
- case 0x104Eu:
- cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
- break;
-
- case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
- case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
- case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
- case 0x25FEu:
- cat = (indic_category_t) OT_GB;
- break;
-
- case 0x1004u: case 0x101Bu: case 0x105Au:
- cat = (indic_category_t) OT_Ra;
- break;
-
- case 0x1032u: case 0x1036u:
- cat = (indic_category_t) OT_A;
- break;
-
- case 0x1039u:
- cat = (indic_category_t) OT_H;
- break;
-
- case 0x103Au:
- cat = (indic_category_t) OT_As;
- break;
-
- case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
- case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
- case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
- case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
- case 0x1097u: case 0x1098u: case 0x1099u:
- cat = (indic_category_t) OT_D;
- break;
-
- case 0x1040u:
- cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
- break;
-
- case 0x103Eu: case 0x1060u:
- cat = (indic_category_t) OT_MH;
- break;
-
- case 0x103Cu:
- cat = (indic_category_t) OT_MR;
- break;
-
- case 0x103Du: case 0x1082u:
- cat = (indic_category_t) OT_MW;
- break;
-
- case 0x103Bu: case 0x105Eu: case 0x105Fu:
- cat = (indic_category_t) OT_MY;
- break;
-
- case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
- case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
- cat = (indic_category_t) OT_PT;
- break;
-
- case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
- case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
- case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
- cat = (indic_category_t) OT_SM;
- break;
-
- case 0x104Au: case 0x104Bu:
- cat = (indic_category_t) OT_P;
- break;
-
- case 0xAA74u: case 0xAA75u: case 0xAA76u:
- /* https://github.com/roozbehp/unicode-data/issues/3 */
- cat = (indic_category_t) OT_C;
- break;
- }
-
- if (cat == OT_M)
- {
- switch ((int) pos)
- {
- case POS_PRE_C: cat = (indic_category_t) OT_VPre;
- pos = POS_PRE_M; break;
- case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break;
- case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break;
- case POS_POST_C: cat = (indic_category_t) OT_VPst; break;
- }
- }
-
- info.myanmar_category() = (myanmar_category_t) cat;
- info.myanmar_position() = pos;
-}
-
-
-
static void
setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
diff --git a/src/hb-ot-shape-complex-use-private.hh b/src/hb-ot-shape-complex-use-private.hh
index 3e763ae3936c224c5cec1be448aeb3526f4602d4..f7ded133d6b0d308237359a2cfc005f432e68644 100644
--- a/src/hb-ot-shape-complex-use-private.hh
+++ b/src/hb-ot-shape-complex-use-private.hh
@@ -92,6 +92,6 @@ enum use_category_t {
};
HB_INTERNAL USE_TABLE_ELEMENT_TYPE
-hb_use_get_categories (hb_codepoint_t u);
+hb_use_get_category (hb_codepoint_t u);
#endif /* HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH */
diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc
index a67ef061122b4571027a81cb9fa1db613fa73c3c..6823392f4b4657176eb59792314dcad45367ecc7 100644
--- a/src/hb-ot-shape-complex-use-table.cc
+++ b/src/hb-ot-shape-complex-use-table.cc
@@ -690,7 +690,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
}; /* Table items: 5424; occupancy: 73% */
USE_TABLE_ELEMENT_TYPE
-hb_use_get_categories (hb_codepoint_t u)
+hb_use_get_category (hb_codepoint_t u)
{
switch (u >> 12)
{
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index 62acd697bdd294e42633d8516f0c668631c03e9a..ee7653b51ce6eea477b5a5d9e96222169eae5ba4 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -262,7 +262,7 @@ setup_masks_use (const hb_ot_shape_plan_t *plan,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- info[i].use_category() = hb_use_get_categories (info[i].codepoint);
+ info[i].use_category() = hb_use_get_category (info[i].codepoint);
}
static void
@@ -505,7 +505,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_glyph_info_t dottedcircle = {0};
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle.codepoint))
return;
- dottedcircle.use_category() = hb_use_get_categories (0x25CC);
+ dottedcircle.use_category() = hb_use_get_category (0x25CC);
buffer->clear_output ();
diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index d71d41224be7e0baed8771eb0bddab8dc026ed74..7282b07991ef03e45be9b8b6de590f963ed4fe46 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -121,6 +121,33 @@ struct hb_set_t
*codepoint = INVALID;
return false;
+ found:
+ *codepoint = i * ELT_BITS + j;
+ return true;
+ }
+ inline bool previous (hb_codepoint_t *codepoint) const
+ {
+ unsigned int m = (*codepoint - 1) & MASK;
+ if (m == MASK)
+ {
+ *codepoint = INVALID;
+ return false;
+ }
+ unsigned int i = m / ELT_BITS;
+ unsigned int j = m & ELT_MASK;
+
+ for (; (int) j >= 0; j--)
+ if (v[i] & (elt_t (1) << j))
+ goto found;
+ for (i--; (int) i >= 0; i--)
+ if (v[i])
+ for (j = ELT_BITS - 1; (int) j >= 0; j--)
+ if (v[i] & (elt_t (1) << j))
+ goto found;
+
+ *codepoint = INVALID;
+ return false;
+
found:
*codepoint = i * ELT_BITS + j;
return true;
@@ -471,12 +498,12 @@ struct hb_set_t
page_map_t map = {get_major (*codepoint), 0};
unsigned int i;
page_map.bfind (map, &i);
- if (i < page_map.len)
+ if (i < page_map.len && page_map[i].major == map.major)
{
if (pages[page_map[i].index].next (codepoint))
{
*codepoint += page_map[i].major * page_t::PAGE_BITS;
- return true;
+ return true;
}
i++;
}
@@ -492,6 +519,37 @@ struct hb_set_t
*codepoint = INVALID;
return false;
}
+ inline bool previous (hb_codepoint_t *codepoint) const
+ {
+ if (unlikely (*codepoint == INVALID)) {
+ *codepoint = get_max ();
+ return *codepoint != INVALID;
+ }
+
+ page_map_t map = {get_major (*codepoint), 0};
+ unsigned int i;
+ page_map.bfind (map, &i);
+ if (i < page_map.len && page_map[i].major == map.major)
+ {
+ if (pages[page_map[i].index].previous (codepoint))
+ {
+ *codepoint += page_map[i].major * page_t::PAGE_BITS;
+ return true;
+ }
+ }
+ i--;
+ for (; (int) i >= 0; i--)
+ {
+ hb_codepoint_t m = pages[page_map[i].index].get_max ();
+ if (m != INVALID)
+ {
+ *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+ return true;
+ }
+ }
+ *codepoint = INVALID;
+ return false;
+ }
inline bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
{
hb_codepoint_t i;
@@ -503,12 +561,31 @@ struct hb_set_t
return false;
}
+ /* TODO Speed up. */
*last = *first = i;
while (next (&i) && i == *last + 1)
(*last)++;
return true;
}
+ inline bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+ {
+ hb_codepoint_t i;
+
+ i = *first;
+ if (!previous (&i))
+ {
+ *last = *first = INVALID;
+ return false;
+ }
+
+ /* TODO Speed up. */
+ *last = *first = i;
+ while (previous (&i) && i == *first - 1)
+ (*first)--;
+
+ return true;
+ }
inline unsigned int get_population (void) const
{
diff --git a/src/hb-set.cc b/src/hb-set.cc
index 0b4f871e852fda9bb9ff18bcf69c8725db9045b7..07cf9d09b55bc08dcb20bd9e3a7e432358bbcb10 100644
--- a/src/hb-set.cc
+++ b/src/hb-set.cc
@@ -50,6 +50,13 @@ hb_set_create (void)
return set;
}
+static const hb_set_t _hb_set_nil = {
+ HB_OBJECT_HEADER_STATIC,
+ true, /* in_error */
+
+ {0} /* elts */
+};
+
/**
* hb_set_get_empty:
*
@@ -60,13 +67,6 @@ hb_set_create (void)
hb_set_t *
hb_set_get_empty (void)
{
- static const hb_set_t _hb_set_nil = {
- HB_OBJECT_HEADER_STATIC,
- true, /* in_error */
-
- {0} /* elts */
- };
-
return const_cast (&_hb_set_nil);
}
@@ -437,7 +437,9 @@ hb_set_get_max (const hb_set_t *set)
* @set: a set.
* @codepoint: (inout):
*
- *
+ * Gets the next number in @set that is greater than current value of @codepoint.
+ *
+ * Set @codepoint to %HB_SET_VALUE_INVALID to get started.
*
* Return value: whether there was a next value.
*
@@ -450,6 +452,26 @@ hb_set_next (const hb_set_t *set,
return set->next (codepoint);
}
+/**
+ * hb_set_previous:
+ * @set: a set.
+ * @codepoint: (inout):
+ *
+ * Gets the previous number in @set that is slower than current value of @codepoint.
+ *
+ * Set @codepoint to %HB_SET_VALUE_INVALID to get started.
+ *
+ * Return value: whether there was a previous value.
+ *
+ * Since: 1.8.0
+ **/
+hb_bool_t
+hb_set_previous (const hb_set_t *set,
+ hb_codepoint_t *codepoint)
+{
+ return set->previous (codepoint);
+}
+
/**
* hb_set_next_range:
* @set: a set.
@@ -459,6 +481,8 @@ hb_set_next (const hb_set_t *set,
* Gets the next consecutive range of numbers in @set that
* are greater than current value of @last.
*
+ * Set @last to %HB_SET_VALUE_INVALID to get started.
+ *
* Return value: whether there was a next range.
*
* Since: 0.9.7
@@ -470,3 +494,26 @@ hb_set_next_range (const hb_set_t *set,
{
return set->next_range (first, last);
}
+
+/**
+ * hb_set_previous_range:
+ * @set: a set.
+ * @first: (inout): input current first and output first codepoint in the range.
+ * @last: (out): output last codepoint in the range.
+ *
+ * Gets the previous consecutive range of numbers in @set that
+ * are greater than current value of @last.
+ *
+ * Set @first to %HB_SET_VALUE_INVALID to get started.
+ *
+ * Return value: whether there was a previous range.
+ *
+ * Since: 1.8.0
+ **/
+hb_bool_t
+hb_set_previous_range (const hb_set_t *set,
+ hb_codepoint_t *first,
+ hb_codepoint_t *last)
+{
+ return set->previous_range (first, last);
+}
diff --git a/src/hb-set.h b/src/hb-set.h
index 2ce406073ce473a913eeb12f66ea59ce6c2718e0..b0f82f82208c78aea83344c1c999808db21a3ab1 100644
--- a/src/hb-set.h
+++ b/src/hb-set.h
@@ -129,25 +129,36 @@ hb_set_symmetric_difference (hb_set_t *set,
HB_EXTERN unsigned int
hb_set_get_population (const hb_set_t *set);
-/* Returns -1 if set empty. */
+/* Returns HB_SET_VALUE_INVALID if set empty. */
HB_EXTERN hb_codepoint_t
hb_set_get_min (const hb_set_t *set);
-/* Returns -1 if set empty. */
+/* Returns HB_SET_VALUE_INVALID if set empty. */
HB_EXTERN hb_codepoint_t
hb_set_get_max (const hb_set_t *set);
-/* Pass -1 in to get started. */
+/* Pass HB_SET_VALUE_INVALID in to get started. */
HB_EXTERN hb_bool_t
hb_set_next (const hb_set_t *set,
hb_codepoint_t *codepoint);
-/* Pass -1 for first and last to get started. */
+/* Pass HB_SET_VALUE_INVALID in to get started. */
+HB_EXTERN hb_bool_t
+hb_set_previous (const hb_set_t *set,
+ hb_codepoint_t *codepoint);
+
+/* Pass HB_SET_VALUE_INVALID for first and last to get started. */
HB_EXTERN hb_bool_t
hb_set_next_range (const hb_set_t *set,
hb_codepoint_t *first,
hb_codepoint_t *last);
+/* Pass HB_SET_VALUE_INVALID for first and last to get started. */
+HB_EXTERN hb_bool_t
+hb_set_previous_range (const hb_set_t *set,
+ hb_codepoint_t *first,
+ hb_codepoint_t *last);
+
HB_END_DECLS
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index 28f5f0c5777a2a18121959fce00091f97b58ebe1..36789f9bfb096a6ed3cfdcb1c2186cafe0406943 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -38,14 +38,12 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
{
unsigned int total = 0;
unsigned int count = 0;
- for (unsigned int i = 0; i < glyph_ids.len; i++) {
+ for (unsigned int i = 0; i < glyph_ids.len; i++)
+ {
hb_codepoint_t next_glyph = glyph_ids[i];
unsigned int start_offset, end_offset;
- if (unlikely (!glyf.get_offsets (next_glyph, &start_offset, &end_offset))) {
- *glyf_size = 0;
- *loca_size = sizeof(OT::HBUINT32);
- return false;
- }
+ if (unlikely (!glyf.get_offsets (next_glyph, &start_offset, &end_offset)))
+ end_offset = start_offset = 0;
total += end_offset - start_offset;
count++;
@@ -84,29 +82,21 @@ _write_glyf_and_loca_prime (const OT::glyf::accelerator_t &glyf,
{
char *glyf_prime_data_next = glyf_prime_data;
- hb_codepoint_t new_glyph_id = 0;
-
- unsigned int current_offset = 0;
- unsigned int end_offset = 0;
- for (unsigned int i = 0; i < glyph_ids.len; i++) {
- unsigned int start_offset;
- if (unlikely (!glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset))) {
- return false;
- }
+ for (unsigned int i = 0; i < glyph_ids.len; i++)
+ {
+ unsigned int start_offset, end_offset;
+ if (unlikely (!glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset)))
+ end_offset = start_offset = 0;
int length = end_offset - start_offset;
memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
- _write_loca_entry (i, current_offset, use_short_loca, loca_prime_data);
+ _write_loca_entry (i, glyf_prime_data_next - glyf_prime_data, use_short_loca, loca_prime_data);
glyf_prime_data_next += length;
- current_offset += length;
- new_glyph_id++;
}
- // Add the last loca entry which doesn't correspond to a specific glyph
- // but identifies the end of the last glyphs data.
- _write_loca_entry (new_glyph_id, current_offset, use_short_loca, loca_prime_data);
+ _write_loca_entry (glyph_ids.len, glyf_prime_data_next - glyf_prime_data, use_short_loca, loca_prime_data);
return true;
}
@@ -134,8 +124,8 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
return false;
}
- char *glyf_prime_data = (char *) calloc (glyf_prime_size, 1);
- char *loca_prime_data = (char *) calloc (loca_prime_size, 1);
+ char *glyf_prime_data = (char *) malloc (glyf_prime_size);
+ char *loca_prime_data = (char *) malloc (loca_prime_size);
if (unlikely (!_write_glyf_and_loca_prime (glyf, glyf_data, glyphs_to_retain,
*use_short_loca,
glyf_prime_size, glyf_prime_data,
diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d41cff6019a5f59e992c4f8336888c0a68996d12
--- /dev/null
+++ b/src/hb-subset-input.cc
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2018 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
+ */
+
+#include "hb-object-private.hh"
+#include "hb-subset-private.hh"
+#include "hb-set-private.hh"
+
+/**
+ * hb_subset_input_create_or_fail:
+ *
+ * Return value: New subset input.
+ *
+ * Since: 1.8.0
+ **/
+hb_subset_input_t *
+hb_subset_input_create_or_fail (void)
+{
+ hb_subset_input_t *input = hb_object_create();
+
+ if (unlikely (!input))
+ return nullptr;
+
+ input->unicodes = hb_set_create ();
+ input->glyphs = hb_set_create ();
+
+ return input;
+}
+
+/**
+ * hb_subset_input_reference: (skip)
+ * @subset_input: a subset_input.
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 1.8.0
+ **/
+hb_subset_input_t *
+hb_subset_input_reference (hb_subset_input_t *subset_input)
+{
+ return hb_object_reference (subset_input);
+}
+
+/**
+ * hb_subset_input_destroy:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
+void
+hb_subset_input_destroy(hb_subset_input_t *subset_input)
+{
+ if (!hb_object_destroy (subset_input)) return;
+
+ hb_set_destroy (subset_input->unicodes);
+ hb_set_destroy (subset_input->glyphs);
+
+ free (subset_input);
+}
+
+/**
+ * hb_subset_input_unicode_set:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
+HB_EXTERN hb_set_t *
+hb_subset_input_unicode_set (hb_subset_input_t *subset_input)
+{
+ return subset_input->unicodes;
+}
+
+/**
+ * hb_subset_input_glyph_set:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
+HB_EXTERN hb_set_t *
+hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
+{
+ return subset_input->glyphs;
+}
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 286f7e15853e3e21b7e2e22e54eaad973d04e70e..6f4b003b3ea7bb875d27c0468f4cf212817b5876 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -155,7 +155,7 @@ hb_subset_plan_create (hb_face_t *face,
plan->gids_to_retain.init();
plan->gids_to_retain_sorted.init();
- _populate_codepoints (input->codepoints, plan->codepoints);
+ _populate_codepoints (input->unicodes, plan->codepoints);
_populate_gids_to_retain (face,
plan->codepoints,
plan->gids_to_retain,
diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh
index 9689da808c5449a740a46dae32db528343f63f7b..4ef1b9540575ca69fc6f0e40e36b595192ecd258 100644
--- a/src/hb-subset-private.hh
+++ b/src/hb-subset-private.hh
@@ -38,7 +38,16 @@ struct hb_subset_input_t {
hb_object_header_t header;
ASSERT_POD ();
- hb_set_t *codepoints;
+ hb_set_t *unicodes;
+ hb_set_t *glyphs;
+
+ /* TODO
+ *
+ * features
+ * lookups
+ * nameIDs
+ * ...
+ */
};
#endif /* HB_SUBSET_PRIVATE_HH */
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 3851977e1013c31ce15f26272e85d4343aafef97..e7f2d912c730a57db28106552e3331bfa83cb08f 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -21,14 +21,12 @@
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
- * Google Author(s): Garret Rieger, Rod Sheeter
+ * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
*/
#include "hb-object-private.hh"
#include "hb-open-type-private.hh"
-#include "hb-private.hh"
-
#include "hb-subset-glyf.hh"
#include "hb-subset-private.hh"
#include "hb-subset-plan.hh"
@@ -56,7 +54,7 @@ struct hb_subset_profile_t {
*
* Return value: New profile with default settings.
*
- * Since: 1.7.5
+ * Since: 1.8.0
**/
hb_subset_profile_t *
hb_subset_profile_create ()
@@ -67,7 +65,7 @@ hb_subset_profile_create ()
/**
* hb_subset_profile_destroy:
*
- * Since: 1.7.5
+ * Since: 1.8.0
**/
void
hb_subset_profile_destroy (hb_subset_profile_t *profile)
@@ -77,48 +75,12 @@ hb_subset_profile_destroy (hb_subset_profile_t *profile)
free (profile);
}
-/**
- * hb_subset_input_create:
- *
- * Return value: New subset input.
- *
- * Since: 1.7.5
- **/
-hb_subset_input_t *
-hb_subset_input_create (hb_set_t *codepoints)
-{
- if (unlikely (!codepoints))
- codepoints = hb_set_get_empty();
-
- hb_subset_input_t *input = hb_object_create();
- input->codepoints = hb_set_reference(codepoints);
- return input;
-}
-
-/**
- * hb_subset_input_destroy:
- *
- * Since: 1.7.5
- **/
-void
-hb_subset_input_destroy(hb_subset_input_t *subset_input)
-{
- if (!hb_object_destroy (subset_input)) return;
-
- hb_set_destroy (subset_input->codepoints);
- free (subset_input);
-}
-
template
static hb_blob_t *
_subset (hb_subset_plan_t *plan, hb_face_t *source)
{
OT::Sanitizer sanitizer;
hb_blob_t *source_blob = sanitizer.sanitize (source->reference_table (TableType::tableTag));
- if (unlikely(!source_blob)) {
- DEBUG_MSG(SUBSET, nullptr, "Failed to reference table for tag %d", TableType::tableTag);
- return nullptr;
- }
const TableType *table = OT::Sanitizer::lock_instance (source_blob);
hb_blob_t *result = table->subset(plan, source);
diff --git a/src/hb-subset.h b/src/hb-subset.h
index 3eb41de848b2a23a6a25923e7556b5b36e73ea77..de7759b22f9fb4f06ba0cfe206b4e5db709671a6 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -47,17 +47,27 @@ hb_subset_profile_destroy (hb_subset_profile_t *profile);
/*
* hb_subset_input_t
+ *
* Things that change based on the input. Characters to keep, etc.
*/
typedef struct hb_subset_input_t hb_subset_input_t;
HB_EXTERN hb_subset_input_t *
-hb_subset_input_create (hb_set_t *codepoints);
+hb_subset_input_create_or_fail (void);
+
+HB_EXTERN hb_subset_input_t *
+hb_subset_input_reference (hb_subset_input_t *subset_input);
HB_EXTERN void
hb_subset_input_destroy (hb_subset_input_t *subset_input);
+HB_EXTERN hb_set_t *
+hb_subset_input_unicode_set (hb_subset_input_t *subset_input);
+
+HB_EXTERN hb_set_t *
+hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
+
/* hb_subset() */
diff --git a/test/api/test-set.c b/test/api/test-set.c
index bbea2cf5a39fe8c775f4d8031aefea63cc63937c..60e11d98185e70896298abf543ce1145d8187af3 100644
--- a/test/api/test-set.c
+++ b/test/api/test-set.c
@@ -32,25 +32,33 @@
static void
test_empty (hb_set_t *s)
{
- hb_codepoint_t next = HB_SET_VALUE_INVALID;
+ hb_codepoint_t next;
g_assert_cmpint (hb_set_get_population (s), ==, 0);
g_assert_cmpint (hb_set_get_min (s), ==, HB_SET_VALUE_INVALID);
g_assert_cmpint (hb_set_get_max (s), ==, HB_SET_VALUE_INVALID);
g_assert (!hb_set_has (s, 13));
+ next = 53043;
g_assert (!hb_set_next (s, &next));
g_assert_cmpint (next, ==, HB_SET_VALUE_INVALID);
+ next = 07734;
+ g_assert (!hb_set_previous (s, &next));
+ g_assert_cmpint (next, ==, HB_SET_VALUE_INVALID);
g_assert (hb_set_is_empty (s));
}
static void
test_not_empty (hb_set_t *s)
{
- hb_codepoint_t next = HB_SET_VALUE_INVALID;
+ hb_codepoint_t next;
g_assert_cmpint (hb_set_get_population (s), !=, 0);
g_assert_cmpint (hb_set_get_min (s), !=, HB_SET_VALUE_INVALID);
g_assert_cmpint (hb_set_get_max (s), !=, HB_SET_VALUE_INVALID);
+ next = HB_SET_VALUE_INVALID;
g_assert (hb_set_next (s, &next));
g_assert_cmpint (next, !=, HB_SET_VALUE_INVALID);
+ next = HB_SET_VALUE_INVALID;
+ g_assert (hb_set_previous (s, &next));
+ g_assert_cmpint (next, !=, HB_SET_VALUE_INVALID);
}
static void
@@ -271,6 +279,27 @@ test_set_iter (void)
g_assert (!hb_set_next (s, &next));
g_assert_cmpint (next, ==, HB_SET_VALUE_INVALID);
+ next = HB_SET_VALUE_INVALID;
+ g_assert (hb_set_previous (s, &next));
+ g_assert_cmpint (next, ==, 20005);
+ g_assert (hb_set_previous (s, &next));
+ g_assert_cmpint (next, ==, 1200);
+ g_assert (hb_set_previous (s, &next));
+ g_assert_cmpint (next, ==, 1100);
+ g_assert (hb_set_previous (s, &next));
+ g_assert_cmpint (next, ==, 15);
+ g_assert (hb_set_previous (s, &next));
+ g_assert (hb_set_previous (s, &next));
+ g_assert_cmpint (next, ==, 13);
+ g_assert (hb_set_previous (s, &next));
+ g_assert (hb_set_previous (s, &next));
+ g_assert (hb_set_previous (s, &next));
+ g_assert_cmpint (next, ==, 10);
+ g_assert (hb_set_previous (s, &next));
+ g_assert_cmpint (next, ==, 6);
+ g_assert (!hb_set_previous (s, &next));
+ g_assert_cmpint (next, ==, HB_SET_VALUE_INVALID);
+
first = last = HB_SET_VALUE_INVALID;
g_assert (hb_set_next_range (s, &first, &last));
g_assert_cmpint (first, ==, 6);
@@ -291,6 +320,26 @@ test_set_iter (void)
g_assert_cmpint (first, ==, HB_SET_VALUE_INVALID);
g_assert_cmpint (last, ==, HB_SET_VALUE_INVALID);
+ first = last = HB_SET_VALUE_INVALID;
+ g_assert (hb_set_previous_range (s, &first, &last));
+ g_assert_cmpint (first, ==, 20005);
+ g_assert_cmpint (last, ==, 20005);
+ g_assert (hb_set_previous_range (s, &first, &last));
+ g_assert_cmpint (first, ==, 1200);
+ g_assert_cmpint (last, ==, 1200);
+ g_assert (hb_set_previous_range (s, &first, &last));
+ g_assert_cmpint (first, ==, 1100);
+ g_assert_cmpint (last, ==, 1100);
+ g_assert (hb_set_previous_range (s, &first, &last));
+ g_assert_cmpint (first, ==, 10);
+ g_assert_cmpint (last, ==, 15);
+ g_assert (hb_set_previous_range (s, &first, &last));
+ g_assert_cmpint (first, ==, 6);
+ g_assert_cmpint (last, ==, 6);
+ g_assert (!hb_set_previous_range (s, &first, &last));
+ g_assert_cmpint (first, ==, HB_SET_VALUE_INVALID);
+ g_assert_cmpint (last, ==, HB_SET_VALUE_INVALID);
+
hb_set_destroy (s);
}
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index a3505a8143d3f00f9511b50263031ff7a0d13870..ea657affe32bd52b18664d40725f4685775387b8 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -37,13 +37,13 @@
struct subset_consumer_t
{
subset_consumer_t (option_parser_t *parser)
- : failed (false), options (parser), font (nullptr), codepoints (nullptr) {}
+ : failed (false), options (parser), font (nullptr), input (nullptr) {}
void init (hb_buffer_t *buffer_,
const font_options_t *font_opts)
{
font = hb_font_reference (font_opts->get_font ());
- codepoints = hb_set_create();
+ input = hb_subset_input_create_or_fail ();
}
void consume_line (const char *text,
@@ -51,14 +51,13 @@ struct subset_consumer_t
const char *text_before,
const char *text_after)
{
- // text appears to be a g_string when set by --unicodes
- // TODO(Q1) are gunichar and hbcodepoint_t interchangeable?
// TODO(Q1) does this only get called with at least 1 codepoint?
+ hb_set_t *codepoints = hb_subset_input_unicode_set (input);
gchar *c = (gchar *)text;
do {
gunichar cp = g_utf8_get_char(c);
- hb_codepoint_t hb_cp = cp; // TODO(Q1) is this safe?
- hb_set_add(codepoints, hb_cp);
+ hb_codepoint_t hb_cp = cp;
+ hb_set_add (codepoints, hb_cp);
} while ((c = g_utf8_find_next_char(c, text + text_len)) != nullptr);
}
@@ -90,12 +89,10 @@ struct subset_consumer_t
void finish (const font_options_t *font_opts)
{
- // TODO(Q1) check for errors from creates and such
hb_subset_profile_t *subset_profile = hb_subset_profile_create();
- hb_subset_input_t *subset_input = hb_subset_input_create (codepoints);
hb_face_t *face = hb_font_get_face (font);
- hb_face_t *new_face = hb_subset(face, subset_profile, subset_input);
+ hb_face_t *new_face = hb_subset(face, subset_profile, input);
hb_blob_t *result = hb_face_reference_blob (new_face);
failed = !hb_blob_get_length (result);
@@ -103,8 +100,7 @@ struct subset_consumer_t
write_file (options.output_file, result);
hb_subset_profile_destroy (subset_profile);
- hb_subset_input_destroy (subset_input);
- hb_set_destroy (codepoints);
+ hb_subset_input_destroy (input);
hb_blob_destroy (result);
hb_face_destroy (new_face);
hb_font_destroy (font);
@@ -116,7 +112,7 @@ struct subset_consumer_t
private:
output_options_t options;
hb_font_t *font;
- hb_set_t *codepoints;
+ hb_subset_input_t *input;
};
int