aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2016-04-20 17:08:40 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-04-20 17:08:40 +0000
commit9a9975d24066e395a1de360a8afacfa4e8a8969e (patch)
tree9e8a513169ee8f4fd304586aae21e3073a8445fa
parent8d1e57ae2523769b9ff7e9d1344a256880cb5202 (diff)
parente9f6b1c7f914c87661cecd99f954204a4415e0d4 (diff)
downloadharfbuzz_ng-nougat-mr1.8-release.tar.gz
Update harfbuzz to 1.2.6 from 1.2.1android-cts_7.1_r1android-cts-7.1_r9android-cts-7.1_r8android-cts-7.1_r7android-cts-7.1_r6android-cts-7.1_r5android-cts-7.1_r4android-cts-7.1_r3android-cts-7.1_r29android-cts-7.1_r28android-cts-7.1_r27android-cts-7.1_r26android-cts-7.1_r25android-cts-7.1_r24android-cts-7.1_r23android-cts-7.1_r22android-cts-7.1_r21android-cts-7.1_r20android-cts-7.1_r2android-cts-7.1_r19android-cts-7.1_r18android-cts-7.1_r17android-cts-7.1_r16android-cts-7.1_r15android-cts-7.1_r14android-cts-7.1_r13android-cts-7.1_r12android-cts-7.1_r11android-cts-7.1_r10android-cts-7.1_r1android-7.1.2_r9android-7.1.2_r8android-7.1.2_r6android-7.1.2_r5android-7.1.2_r4android-7.1.2_r39android-7.1.2_r38android-7.1.2_r37android-7.1.2_r36android-7.1.2_r33android-7.1.2_r32android-7.1.2_r30android-7.1.2_r3android-7.1.2_r29android-7.1.2_r28android-7.1.2_r27android-7.1.2_r25android-7.1.2_r24android-7.1.2_r23android-7.1.2_r2android-7.1.2_r19android-7.1.2_r18android-7.1.2_r17android-7.1.2_r16android-7.1.2_r15android-7.1.2_r14android-7.1.2_r13android-7.1.2_r12android-7.1.2_r11android-7.1.2_r10android-7.1.2_r1android-7.1.1_r9android-7.1.1_r8android-7.1.1_r7android-7.1.1_r61android-7.1.1_r60android-7.1.1_r6android-7.1.1_r59android-7.1.1_r58android-7.1.1_r57android-7.1.1_r56android-7.1.1_r55android-7.1.1_r54android-7.1.1_r53android-7.1.1_r52android-7.1.1_r51android-7.1.1_r50android-7.1.1_r49android-7.1.1_r48android-7.1.1_r47android-7.1.1_r46android-7.1.1_r45android-7.1.1_r44android-7.1.1_r43android-7.1.1_r42android-7.1.1_r41android-7.1.1_r40android-7.1.1_r4android-7.1.1_r39android-7.1.1_r38android-7.1.1_r35android-7.1.1_r33android-7.1.1_r32android-7.1.1_r31android-7.1.1_r3android-7.1.1_r28android-7.1.1_r27android-7.1.1_r26android-7.1.1_r25android-7.1.1_r24android-7.1.1_r23android-7.1.1_r22android-7.1.1_r21android-7.1.1_r20android-7.1.1_r2android-7.1.1_r17android-7.1.1_r16android-7.1.1_r15android-7.1.1_r14android-7.1.1_r13android-7.1.1_r12android-7.1.1_r11android-7.1.1_r10android-7.1.1_r1android-7.1.0_r7android-7.1.0_r6android-7.1.0_r5android-7.1.0_r4android-7.1.0_r3android-7.1.0_r2android-7.1.0_r1nougat-mr2.3-releasenougat-mr2.2-releasenougat-mr2.1-releasenougat-mr2-security-releasenougat-mr2-releasenougat-mr2-pixel-releasenougat-mr2-devnougat-mr1.8-releasenougat-mr1.7-releasenougat-mr1.6-releasenougat-mr1.5-releasenougat-mr1.4-releasenougat-mr1.3-releasenougat-mr1.2-releasenougat-mr1.1-releasenougat-mr1-volantis-releasenougat-mr1-security-releasenougat-mr1-releasenougat-mr1-flounder-releasenougat-mr1-devnougat-mr1-cts-releasenougat-dr1-release
am: e9f6b1c * commit 'e9f6b1c7f914c87661cecd99f954204a4415e0d4': (47 commits) 1.2.6 Blacklist another set of timesi.ttf and timesbi.ttf Fix when no feature is given 1.2.5 Add test for 6dd80faf0dcb3e8a8915c3a25da44e2a67cb0cd8 [coretext] Clarify comment Fix FixedVersion::to_int() Hide justification behind HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION Use standard types instead Windows favourites ones Limit GetJustifiedGlyphs only to scripts with custom justification character Add justification support Basic opentype features support Refactor and remove dupe getglyphs call Better glyph offset support Don't fail when language is not set Make DirectWrite backend to work with different font sizes 1.2.4 Synthesize GDEF glyph class for any glyph that does not have one in GDEF [build] Use tar-ustar instead of tar-pax Minor comment ... Change-Id: I58c6da539823ad94e5da3f87a92cde02ad3f71dc
-rw-r--r--NEWS88
-rw-r--r--README.version4
-rw-r--r--TODO16
-rw-r--r--configure.ac37
-rw-r--r--src/Makefile.am8
-rw-r--r--src/hb-buffer-private.hh65
-rw-r--r--src/hb-buffer.cc72
-rw-r--r--src/hb-coretext.cc8
-rw-r--r--src/hb-deprecated.h10
-rw-r--r--src/hb-directwrite.cc461
-rw-r--r--src/hb-fallback-shape.cc4
-rw-r--r--src/hb-font-private.hh26
-rw-r--r--src/hb-font.cc220
-rw-r--r--src/hb-font.h55
-rw-r--r--src/hb-ft.cc38
-rw-r--r--src/hb-icu.cc1
-rw-r--r--src/hb-open-type-private.hh11
-rw-r--r--src/hb-ot-cmap-table.hh125
-rw-r--r--src/hb-ot-font.cc103
-rw-r--r--src/hb-ot-glyf-table.hh8
-rw-r--r--src/hb-ot-hmtx-table.hh6
-rw-r--r--src/hb-ot-layout-gpos-table.hh28
-rw-r--r--src/hb-ot-layout-gsub-table.hh22
-rw-r--r--src/hb-ot-layout.cc29
-rw-r--r--src/hb-ot-map.cc5
-rw-r--r--src/hb-ot-shape-complex-indic.cc12
-rw-r--r--src/hb-ot-shape-complex-myanmar.cc2
-rw-r--r--src/hb-ot-shape-complex-thai.cc1
-rw-r--r--src/hb-ot-shape-complex-use.cc2
-rw-r--r--src/hb-ot-shape-fallback.cc6
-rw-r--r--src/hb-ot-shape-normalize.cc18
-rw-r--r--src/hb-ot-shape.cc35
-rw-r--r--src/hb-private.hh9
-rw-r--r--src/hb-unicode-private.hh2
-rw-r--r--src/hb-version.h4
-rw-r--r--test/api/test-shape.c2
-rw-r--r--test/shaping/Makefile.am1
-rw-r--r--test/shaping/fonts/sha1sum/07f054357ff8638bac3711b422a1e31180bba863.ttfbin0 -> 848 bytes
-rw-r--r--test/shaping/fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttfbin0 -> 16736 bytes
-rwxr-xr-xtest/shaping/run-tests.sh7
-rw-r--r--test/shaping/tests/cursive-positioning.tests3
-rw-r--r--test/shaping/tests/mark-filtering-sets.tests5
42 files changed, 1047 insertions, 512 deletions
diff --git a/NEWS b/NEWS
index b1b63b2c5..721d5282a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,91 @@
+Overview of changes leading to 1.2.6
+Friday, April 8, 2016
+====================================
+
+- Blacklist GDEF table of another set of Times New Roman (Bold) Italic.
+- DirectWrite backend improvements. Note: DirectWrite backend is
+ exclusively for our internal testing and should NOT be used in any
+ production system whatsoever.
+
+
+Overview of changes leading to 1.2.5
+Monday, April 4, 2016
+====================================
+
+- Fix GDEF mark-filtering-set, which was broken in 1.2.3.
+
+
+Overview of changes leading to 1.2.4
+Thursday, March 17, 2016
+====================================
+
+- Synthesize GDEF glyph class for any glyph that does not have one in GDEF.
+ I really hope we don't discover broken fonts that shape badly with this
+ change.
+- Misc build and other minor fixes.
+- API changes:
+ - Added HB_NDEBUG. It's fine for production systems to define this to
+ disable high-overhead debugging checks. However, I also reduced the
+ overhead of those checks, so it's a non-issue right now. You can
+ forget it. Just not defining anything at all is fine.
+
+
+Overview of changes leading to 1.2.3
+Thursday, February 25, 2016
+====================================
+
+- Blacklist GDEF table of certain versions of Times New Roman (Bold) Italic,
+ due to bug in glyph class of ASCII double-quote character. This should
+ address "regression" introduced in 1.2.0 when we switched mark zeroing
+ in most shapers from BY_UNICODE_LATE to BY_GDEF_LATE.
+ This fourth release in a week should finally stablize things...
+
+- hb-ot-font's get_glyph() implementation saw some optimizations. Though,
+ might be really hard to measure in real-world situations.
+
+- Also, two rather small API changes:
+
+We now disable some time-consuming internal bookkeeping if built with NDEBUG
+defined. This is a first time that we use NDEBUG to disable debug code. If
+there exist production systems that do NOT want to enable NDEBUG, please let
+me know and I'll add HB_NDEBUG.
+
+Added get_nominal_glyph() and get_variation_glyph() instead of get_glyph()
+
+New API:
+- hb_font_get_nominal_glyph_func_t
+- hb_font_get_variation_glyph_func_t
+- hb_font_funcs_set_nominal_glyph_func()
+- hb_font_funcs_set_variation_glyph_func()
+- hb_font_get_nominal_glyph()
+- hb_font_get_variation_glyph()
+
+Deprecated API:
+- hb_font_get_glyph_func_t
+- hb_font_funcs_set_glyph_func()
+
+Clients that implement their own font-funcs are encouraged to replace
+their get_glyph() implementation with a get_nominal_glyph() and
+get_variation_glyph() pair. The variation version can assume that
+variation_selector argument is not zero. Old (deprecated) functions
+will continue working indefinitely using internal gymnastics; it is
+just more efficient to use the new functions.
+
+
+Overview of changes leading to 1.2.2
+Wednesday, February 24, 2016
+====================================
+
+- Fix regression with mark positioning with fonts that have
+ non-zero mark advances. This was introduced in 1.2.0 while
+ trying to make mark and cursive attachments to work together.
+ I have partially reverted that, so this version is much more
+ like what we had before. All clients who updated to 1.2.0
+ should update to this version.
+
+
Overview of changes leading to 1.2.1
-Friday, February 23, 2016
+Tuesday, February 23, 2016
====================================
- CoreText: Fix bug with wrong scale if font scale was changed later.
diff --git a/README.version b/README.version
index 65ac14603..6f84cc923 100644
--- a/README.version
+++ b/README.version
@@ -1,3 +1,3 @@
-URL: http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-1.2.1.tar.bz2
-Version: 1.2.1
+URL: http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-1.2.6.tar.bz2
+Version: 1.2.6
BugComponent: 25699
diff --git a/TODO b/TODO
index e1aa39c4c..4f37f605b 100644
--- a/TODO
+++ b/TODO
@@ -9,26 +9,14 @@ General fixes:
- mask propagation? (when ligation, "or" the masks).
-- Warn at compile time (and runtime with HB_DEBUG?) if no Unicode / font
- funcs found / set.
-- Do proper rounding when scaling from font space? May be a non-issue.
-
-- Misc features:
- * init/medi/fina/isol for non-cursive scripts
-
-
-API issues to fix before 1.0:
-============================
+API issues:
+===========
- API to accept a list of languages?
- Add init_func to font_funcs. Adjust ft.
-- hb-ft load_flags issues.
-
-- Add pkg-config files for glue codes (harfbuzz-glib, etc)
-
- 'const' for getter APIs? (use mutable internally)
- Remove hb_ot_shape_glyphs_closure()?
diff --git a/configure.ac b/configure.ac
index d12d4b814..44621c9a8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
- [1.2.1],
+ [1.2.6],
[http://bugs.freedesktop.org/enter_bug.cgi?product=harfbuzz],
[harfbuzz],
[http://harfbuzz.org/])
@@ -9,7 +9,7 @@ AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
AC_CONFIG_HEADERS([config.h])
-AM_INIT_AUTOMAKE([1.11.1 gnits tar-pax dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
+AM_INIT_AUTOMAKE([1.11.1 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
AM_CONDITIONAL(AUTOMAKE_OLDER_THAN_1_13, test $am__api_version = 1.11 -o $am__api_version = 1.12)
AM_SILENT_RULES([yes])
@@ -197,17 +197,6 @@ m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [
AM_CONDITIONAL([HAVE_INTROSPECTION], false)
])
-dnl ===========================================================================
-
-have_ucdn=true
-if $have_glib; then
- have_ucdn=false
-fi
-if $have_ucdn; then
- AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
-fi
-AM_CONDITIONAL(HAVE_UCDN, $have_ucdn)
-
dnl ==========================================================================
AC_ARG_WITH(cairo,
@@ -256,11 +245,11 @@ AM_CONDITIONAL(HAVE_FONTCONFIG, $have_fontconfig)
dnl ==========================================================================
AC_ARG_WITH(icu,
- [AS_HELP_STRING([--with-icu=@<:@yes/no/auto@:>@],
+ [AS_HELP_STRING([--with-icu=@<:@yes/no/builtin/auto@:>@],
[Use ICU @<:@default=auto@:>@])],,
[with_icu=auto])
have_icu=false
-if test "x$with_icu" = "xyes" -o "x$with_icu" = "xauto"; then
+if test "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" -o "x$with_icu" = "xauto"; then
PKG_CHECK_MODULES(ICU, icu-uc, have_icu=true, :)
dnl Fallback to icu-config if ICU pkg-config files could not be found
@@ -282,14 +271,30 @@ if test "x$with_icu" = "xyes" -o "x$with_icu" = "xauto"; then
fi
fi
fi
-if test "x$with_icu" = "xyes" -a "x$have_icu" != "xtrue"; then
+if test \( "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" \) -a "x$have_icu" != "xtrue"; then
AC_MSG_ERROR([icu support requested but icu-uc not found])
fi
+
if $have_icu; then
CXXFLAGS="$CXXFLAGS `$PKG_CONFIG --variable=CXXFLAGS icu-uc`"
AC_DEFINE(HAVE_ICU, 1, [Have ICU library])
+ if test "x$with_icu" = "xbuiltin"; then
+ AC_DEFINE(HAVE_ICU_BUILTIN, 1, [Use hb-icu Unicode callbacks])
+ fi
fi
AM_CONDITIONAL(HAVE_ICU, $have_icu)
+AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin")
+
+dnl ===========================================================================
+
+have_ucdn=true
+if $have_glib || $have_icu && test "x$with_icu" = "xbuiltin"; then
+ have_ucdn=false
+fi
+if $have_ucdn; then
+ AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
+fi
+AM_CONDITIONAL(HAVE_UCDN, $have_ucdn)
dnl ==========================================================================
diff --git a/src/Makefile.am b/src/Makefile.am
index bb085ad00..8cfe4ac7c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -130,6 +130,7 @@ pkgconfig_DATA = harfbuzz.pc
EXTRA_DIST += harfbuzz.pc.in
FUZZING_CPPFLAGS= \
+ -DHB_NDEBUG \
-DHB_MAX_NESTING_LEVEL=3 \
-DHB_SANITIZE_MAX_EDITS=3 \
-DHB_BUFFER_MAX_EXPANSION_FACTOR=3 \
@@ -146,6 +147,12 @@ EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
CLEANFILES += libharfbuzz-fuzzing.la
if HAVE_ICU
+if HAVE_ICU_BUILTIN
+HBCFLAGS += $(ICU_CFLAGS)
+HBLIBS += $(ICU_LIBS)
+HBSOURCES += $(HB_ICU_sources)
+HBHEADERS += $(HB_ICU_headers)
+else
lib_LTLIBRARIES += libharfbuzz-icu.la
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
libharfbuzz_icu_la_CPPFLAGS = $(ICU_CFLAGS)
@@ -154,6 +161,7 @@ libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
pkginclude_HEADERS += $(HB_ICU_headers)
pkgconfig_DATA += harfbuzz-icu.pc
endif
+endif
EXTRA_DIST += harfbuzz-icu.pc.in
if HAVE_GOBJECT
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index c8eec3c17..ed592f448 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -112,10 +112,6 @@ struct hb_buffer_t {
unsigned int serial;
- /* These reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
- uint8_t allocated_var_bytes[8];
- const char *allocated_var_owner[8];
-
/* Text before / after the main buffer contents.
* Always in Unicode, and ordered outward.
* Index 0 is for "pre-context", 1 for "post-context". */
@@ -123,11 +119,52 @@ struct hb_buffer_t {
hb_codepoint_t context[2][CONTEXT_LENGTH];
unsigned int context_len[2];
- /* Debugging */
+ /* Debugging API */
hb_buffer_message_func_t message_func;
void *message_data;
hb_destroy_func_t message_destroy;
+ /* Internal debugging. */
+ /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
+#ifndef HB_NDEBUG
+ uint8_t allocated_var_bits;
+#endif
+ inline void allocate_var (unsigned int start, unsigned int count)
+ {
+#ifndef HB_NDEBUG
+ unsigned int end = start + count;
+ assert (end <= 8);
+ unsigned int bits = (1<<end) - (1<<start);
+ assert (0 == (allocated_var_bits & bits));
+ allocated_var_bits |= bits;
+#endif
+ }
+ inline void deallocate_var (unsigned int start, unsigned int count)
+ {
+#ifndef HB_NDEBUG
+ unsigned int end = start + count;
+ assert (end <= 8);
+ unsigned int bits = (1<<end) - (1<<start);
+ assert (bits == (allocated_var_bits & bits));
+ allocated_var_bits &= ~bits;
+#endif
+ }
+ inline void assert_var (unsigned int start, unsigned int count)
+ {
+#ifndef HB_NDEBUG
+ unsigned int end = start + count;
+ assert (end <= 8);
+ unsigned int bits = (1<<end) - (1<<start);
+ assert (bits == (allocated_var_bits & bits));
+#endif
+ }
+ inline void deallocate_var_all (void)
+ {
+#ifndef HB_NDEBUG
+ allocated_var_bits = 0;
+#endif
+ }
+
/* Methods */
@@ -140,11 +177,6 @@ struct hb_buffer_t {
{ return len - idx; }
inline unsigned int next_serial (void) { return serial++; }
- HB_INTERNAL void allocate_var (unsigned int byte_i, unsigned int count, const char *owner);
- HB_INTERNAL void deallocate_var (unsigned int byte_i, unsigned int count, const char *owner);
- HB_INTERNAL void assert_var (unsigned int byte_i, unsigned int count, const char *owner);
- HB_INTERNAL void deallocate_var_all (void);
-
HB_INTERNAL void add (hb_codepoint_t codepoint,
unsigned int cluster);
HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
@@ -253,15 +285,12 @@ struct hb_buffer_t {
};
-#define HB_BUFFER_XALLOCATE_VAR(b, func, var, owner) \
+#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
- sizeof (b->info[0].var), owner)
-#define HB_BUFFER_ALLOCATE_VAR(b, var) \
- HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var (), #var)
-#define HB_BUFFER_DEALLOCATE_VAR(b, var) \
- HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var (), #var)
-#define HB_BUFFER_ASSERT_VAR(b, var) \
- HB_BUFFER_XALLOCATE_VAR (b, assert_var, var (), #var)
+ sizeof (b->info[0].var))
+#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ())
+#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
+#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ())
#endif /* HB_BUFFER_PRIVATE_HH */
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 5f320bd7e..406db9c84 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -242,11 +242,11 @@ hb_buffer_t::clear (void)
out_info = info;
serial = 0;
- memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
- memset (allocated_var_owner, 0, sizeof allocated_var_owner);
memset (context, 0, sizeof context);
memset (context_len, 0, sizeof context_len);
+
+ deallocate_var_all ();
}
void
@@ -661,74 +661,6 @@ hb_buffer_t::guess_segment_properties (void)
}
-static inline void
-dump_var_allocation (const hb_buffer_t *buffer)
-{
- char buf[80];
- for (unsigned int i = 0; i < 8; i++)
- buf[i] = '0' + buffer->allocated_var_bytes[7 - i];
- buf[8] = '\0';
- DEBUG_MSG (BUFFER, buffer,
- "Current var allocation: %s",
- buf);
-}
-
-void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner)
-{
- assert (byte_i < 8 && byte_i + count <= 8);
-
- if (DEBUG_ENABLED (BUFFER))
- dump_var_allocation (this);
- DEBUG_MSG (BUFFER, this,
- "Allocating var bytes %d..%d for %s",
- byte_i, byte_i + count - 1, owner);
-
- for (unsigned int i = byte_i; i < byte_i + count; i++) {
- assert (!allocated_var_bytes[i]);
- allocated_var_bytes[i]++;
- allocated_var_owner[i] = owner;
- }
-}
-
-void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner)
-{
- if (DEBUG_ENABLED (BUFFER))
- dump_var_allocation (this);
-
- DEBUG_MSG (BUFFER, this,
- "Deallocating var bytes %d..%d for %s",
- byte_i, byte_i + count - 1, owner);
-
- assert (byte_i < 8 && byte_i + count <= 8);
- for (unsigned int i = byte_i; i < byte_i + count; i++) {
- assert (allocated_var_bytes[i]);
- assert (0 == strcmp (allocated_var_owner[i], owner));
- allocated_var_bytes[i]--;
- }
-}
-
-void hb_buffer_t::assert_var (unsigned int byte_i, unsigned int count, const char *owner)
-{
- if (DEBUG_ENABLED (BUFFER))
- dump_var_allocation (this);
-
- DEBUG_MSG (BUFFER, this,
- "Asserting var bytes %d..%d for %s",
- byte_i, byte_i + count - 1, owner);
-
- assert (byte_i < 8 && byte_i + count <= 8);
- for (unsigned int i = byte_i; i < byte_i + count; i++) {
- assert (allocated_var_bytes[i]);
- assert (0 == strcmp (allocated_var_owner[i], owner));
- }
-}
-
-void hb_buffer_t::deallocate_var_all (void)
-{
- memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes));
- memset (allocated_var_owner, 0, sizeof (allocated_var_owner));
-}
-
/* Public API */
/**
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 90c6653d0..e64d2651a 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -904,13 +904,11 @@ resize_and_retry:
* backend.
*
* However, even that wouldn't work if we were passed in the CGFont to
- * begin with.
- *
- * We might switch to checking PS name against "LastResort". That would
- * be safe for all fonts except for those named "Last Resort". Might be
- * better than what we have right now.
+ * construct a hb_face to begin with.
*
* See: http://github.com/behdad/harfbuzz/pull/36
+ *
+ * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
*/
bool matched = false;
for (unsigned int i = 0; i < range_records.len; i++)
diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h
index 30ae4b1ca..0398dfae6 100644
--- a/src/hb-deprecated.h
+++ b/src/hb-deprecated.h
@@ -44,6 +44,16 @@ HB_BEGIN_DECLS
#define HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_FLAG_DEFAULT
#define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_BUFFER_SERIALIZE_FLAG_DEFAULT
+typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data);
+
+HB_EXTERN void
+hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
#endif
HB_END_DECLS
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index af0fd3da0..96d1870a0 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -1,5 +1,5 @@
/*
- * Copyright © 2015 Ebrahim Byagowi
+ * Copyright © 2015-2016 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -25,7 +25,11 @@
#define HB_SHAPER directwrite
#include "hb-shaper-impl-private.hh"
-#include <dwrite.h>
+#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
+ #include <DWrite.h>
+#else
+ #include <DWrite_1.h>
+#endif
#include "hb-directwrite.h"
@@ -176,7 +180,8 @@ _hb_rename_font(hb_blob_t *blob, wchar_t *new_name)
hb_directwrite_shaper_face_data_t *
_hb_directwrite_shaper_face_data_create(hb_face_t *face)
{
- hb_directwrite_shaper_face_data_t *data = (hb_directwrite_shaper_face_data_t *)calloc(1, sizeof (hb_directwrite_shaper_face_data_t));
+ hb_directwrite_shaper_face_data_t *data =
+ (hb_directwrite_shaper_face_data_t *) calloc (1, sizeof (hb_directwrite_shaper_face_data_t));
if (unlikely (!data))
return NULL;
@@ -244,26 +249,30 @@ _hb_directwrite_shaper_font_data_create (hb_font_t *font)
{
if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return NULL;
- hb_directwrite_shaper_font_data_t *data = (hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t));
+ hb_directwrite_shaper_font_data_t *data =
+ (hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t));
if (unlikely (!data))
return NULL;
data->hdc = GetDC (NULL);
- if (unlikely (!populate_log_font (&data->log_font, font))) {
+ if (unlikely (!populate_log_font (&data->log_font, font)))
+ {
DEBUG_MSG (DIRECTWRITE, font, "Font populate_log_font() failed");
_hb_directwrite_shaper_font_data_destroy (data);
return NULL;
}
data->hfont = CreateFontIndirectW (&data->log_font);
- if (unlikely (!data->hfont)) {
+ if (unlikely (!data->hfont))
+ {
DEBUG_MSG (DIRECTWRITE, font, "Font CreateFontIndirectW() failed");
_hb_directwrite_shaper_font_data_destroy (data);
return NULL;
}
- if (!SelectObject (data->hdc, data->hfont)) {
+ if (!SelectObject (data->hdc, data->hfont))
+ {
DEBUG_MSG (DIRECTWRITE, font, "Font SelectObject() failed");
_hb_directwrite_shaper_font_data_destroy (data);
return NULL;
@@ -333,16 +342,16 @@ public:
// results.
struct Run
{
- UINT32 mTextStart; // starting text position of this run
- UINT32 mTextLength; // number of contiguous code units covered
- UINT32 mGlyphStart; // starting glyph in the glyphs array
- UINT32 mGlyphCount; // number of glyphs associated with this run of
+ uint32_t mTextStart; // starting text position of this run
+ uint32_t mTextLength; // number of contiguous code units covered
+ uint32_t mGlyphStart; // starting glyph in the glyphs array
+ uint32_t mGlyphCount; // number of glyphs associated with this run of
// text
DWRITE_SCRIPT_ANALYSIS mScript;
- UINT8 mBidiLevel;
+ uint8_t mBidiLevel;
bool mIsSideways;
- inline bool ContainsTextPosition(UINT32 aTextPosition) const
+ inline bool ContainsTextPosition(uint32_t aTextPosition) const
{
return aTextPosition >= mTextStart
&& aTextPosition < mTextStart + mTextLength;
@@ -353,7 +362,7 @@ public:
public:
TextAnalysis(const wchar_t* text,
- UINT32 textLength,
+ uint32_t textLength,
const wchar_t* localeName,
DWRITE_READING_DIRECTION readingDirection)
: mText(text)
@@ -367,7 +376,7 @@ public:
for (Run *run = mRunHead.nextRun; run;) {
Run *origRun = run;
run = run->nextRun;
- delete origRun;
+ free (origRun);
}
}
@@ -388,10 +397,7 @@ public:
mCurrentRun = &mRunHead;
// Call each of the analyzers in sequence, recording their results.
- if (SUCCEEDED(hr = textAnalyzer->AnalyzeScript(this,
- 0,
- mTextLength,
- this))) {
+ if (SUCCEEDED (hr = textAnalyzer->AnalyzeScript (this, 0, mTextLength, this))) {
*runHead = &mRunHead;
}
@@ -400,9 +406,9 @@ public:
// IDWriteTextAnalysisSource implementation
- IFACEMETHODIMP GetTextAtPosition(UINT32 textPosition,
- OUT WCHAR const** textString,
- OUT UINT32* textLength)
+ IFACEMETHODIMP GetTextAtPosition(uint32_t textPosition,
+ OUT wchar_t const** textString,
+ OUT uint32_t* textLength)
{
if (textPosition >= mTextLength) {
// No text at this position, valid query though.
@@ -416,9 +422,9 @@ public:
return S_OK;
}
- IFACEMETHODIMP GetTextBeforePosition(UINT32 textPosition,
- OUT WCHAR const** textString,
- OUT UINT32* textLength)
+ IFACEMETHODIMP GetTextBeforePosition(uint32_t textPosition,
+ OUT wchar_t const** textString,
+ OUT uint32_t* textLength)
{
if (textPosition == 0 || textPosition > mTextLength) {
// Either there is no text before here (== 0), or this
@@ -436,15 +442,15 @@ public:
IFACEMETHODIMP_(DWRITE_READING_DIRECTION)
GetParagraphReadingDirection() { return mReadingDirection; }
- IFACEMETHODIMP GetLocaleName(UINT32 textPosition,
- UINT32* textLength,
- WCHAR const** localeName) {
+ IFACEMETHODIMP GetLocaleName(uint32_t textPosition,
+ uint32_t* textLength,
+ wchar_t const** localeName) {
return S_OK;
}
IFACEMETHODIMP
- GetNumberSubstitution(UINT32 textPosition,
- OUT UINT32* textLength,
+ GetNumberSubstitution(uint32_t textPosition,
+ OUT uint32_t* textLength,
OUT IDWriteNumberSubstitution** numberSubstitution)
{
// We do not support number substitution.
@@ -457,8 +463,8 @@ public:
// IDWriteTextAnalysisSink implementation
IFACEMETHODIMP
- SetScriptAnalysis(UINT32 textPosition,
- UINT32 textLength,
+ SetScriptAnalysis(uint32_t textPosition,
+ uint32_t textLength,
DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis)
{
SetCurrentRun(textPosition);
@@ -472,22 +478,22 @@ public:
}
IFACEMETHODIMP
- SetLineBreakpoints(UINT32 textPosition,
- UINT32 textLength,
+ SetLineBreakpoints(uint32_t textPosition,
+ uint32_t textLength,
const DWRITE_LINE_BREAKPOINT* lineBreakpoints) { return S_OK; }
- IFACEMETHODIMP SetBidiLevel(UINT32 textPosition,
- UINT32 textLength,
- UINT8 explicitLevel,
- UINT8 resolvedLevel) { return S_OK; }
+ IFACEMETHODIMP SetBidiLevel(uint32_t textPosition,
+ uint32_t textLength,
+ uint8_t explicitLevel,
+ uint8_t resolvedLevel) { return S_OK; }
IFACEMETHODIMP
- SetNumberSubstitution(UINT32 textPosition,
- UINT32 textLength,
+ SetNumberSubstitution(uint32_t textPosition,
+ uint32_t textLength,
IDWriteNumberSubstitution* numberSubstitution) { return S_OK; }
protected:
- Run *FetchNextRun(IN OUT UINT32* textLength)
+ Run *FetchNextRun(IN OUT uint32_t* textLength)
{
// Used by the sink setters, this returns a reference to the next run.
// Position and length are adjusted to now point after the current run
@@ -509,7 +515,7 @@ protected:
return origRun;
}
- void SetCurrentRun(UINT32 textPosition)
+ void SetCurrentRun(uint32_t textPosition)
{
// Move the current run to the given position.
// Since the analyzers generally return results in a forward manner,
@@ -530,7 +536,7 @@ protected:
// of our runs");
}
- void SplitCurrentRun(UINT32 splitPosition)
+ void SplitCurrentRun(uint32_t splitPosition)
{
if (!mCurrentRun) {
//NS_ASSERTION(false, "SplitCurrentRun called without current run.");
@@ -543,7 +549,7 @@ protected:
// or before it. Usually the first.
return;
}
- Run *newRun = new Run;
+ Run *newRun = (Run*) malloc (sizeof (Run));
*newRun = *mCurrentRun;
@@ -552,7 +558,7 @@ protected:
mCurrentRun->nextRun = newRun;
// Adjust runs' text positions and lengths.
- UINT32 splitPoint = splitPosition - mCurrentRun->mTextStart;
+ uint32_t splitPoint = splitPosition - mCurrentRun->mTextStart;
newRun->mTextStart += splitPoint;
newRun->mTextLength -= splitPoint;
mCurrentRun->mTextLength = splitPoint;
@@ -563,9 +569,9 @@ protected:
// Input
// (weak references are fine here, since this class is a transient
// stack-based helper that doesn't need to copy data)
- UINT32 mTextLength;
- const WCHAR* mText;
- const WCHAR* mLocaleName;
+ uint32_t mTextLength;
+ const wchar_t* mText;
+ const wchar_t* mLocaleName;
DWRITE_READING_DIRECTION mReadingDirection;
// Current processing state.
@@ -575,6 +581,10 @@ protected:
Run mRunHead;
};
+static inline uint16_t hb_uint16_swap (const uint16_t v)
+{ return (v >> 8) | (v << 8); }
+static inline uint32_t hb_uint32_swap (const uint32_t v)
+{ return (hb_uint16_swap(v) << 16) | hb_uint16_swap(v >> 16); }
/*
* shaper
@@ -592,20 +602,30 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
// factory probably should be cached
+#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
IDWriteFactory* dwriteFactory;
- DWriteCreateFactory(
+#else
+ IDWriteFactory1* dwriteFactory;
+#endif
+ DWriteCreateFactory (
DWRITE_FACTORY_TYPE_SHARED,
- __uuidof(IDWriteFactory),
- reinterpret_cast<IUnknown**>(&dwriteFactory)
- );
+ __uuidof (IDWriteFactory),
+ (IUnknown**) &dwriteFactory
+ );
IDWriteGdiInterop *gdiInterop;
dwriteFactory->GetGdiInterop (&gdiInterop);
IDWriteFontFace* fontFace;
gdiInterop->CreateFontFaceFromHdc (font_data->hdc, &fontFace);
+#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
IDWriteTextAnalyzer* analyzer;
- dwriteFactory->CreateTextAnalyzer (&analyzer);
+ dwriteFactory->CreateTextAnalyzer(&analyzer);
+#else
+ IDWriteTextAnalyzer* analyzer0;
+ dwriteFactory->CreateTextAnalyzer (&analyzer0);
+ IDWriteTextAnalyzer1* analyzer = (IDWriteTextAnalyzer1*) analyzer0;
+#endif
unsigned int scratch_size;
hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
@@ -620,7 +640,7 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
#define utf16_index() var1.u32
- ALLOCATE_ARRAY(WCHAR, pchars, buffer->len * 2);
+ ALLOCATE_ARRAY(wchar_t, textString, buffer->len * 2);
unsigned int chars_len = 0;
for (unsigned int i = 0; i < buffer->len; i++)
@@ -628,17 +648,17 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
hb_codepoint_t c = buffer->info[i].codepoint;
buffer->info[i].utf16_index() = chars_len;
if (likely(c <= 0xFFFFu))
- pchars[chars_len++] = c;
+ textString[chars_len++] = c;
else if (unlikely(c > 0x10FFFFu))
- pchars[chars_len++] = 0xFFFDu;
+ textString[chars_len++] = 0xFFFDu;
else {
- pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
- pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
+ textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
+ textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
}
}
ALLOCATE_ARRAY(WORD, log_clusters, chars_len);
- if (num_features)
+ // if (num_features)
{
/* Need log_clusters to assign features. */
chars_len = 0;
@@ -664,164 +684,287 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan,
* but we never attempt to shape a word longer than 64K characters
* in a single gfxShapedWord, so we cannot exceed that limit.
*/
- UINT32 length = buffer->len;
+ uint32_t textLength = buffer->len;
- TextAnalysis analysis(pchars, length, NULL, readingDirection);
+ TextAnalysis analysis(textString, textLength, NULL, readingDirection);
TextAnalysis::Run *runHead;
hr = analysis.GenerateResults(analyzer, &runHead);
- if (FAILED(hr)) {
- //NS_WARNING("Analyzer failed to generate results.");
+#define FAIL(...) \
+ HB_STMT_START { \
+ DEBUG_MSG (DIRECTWRITE, NULL, __VA_ARGS__); \
+ return false; \
+ } HB_STMT_END;
+
+ if (FAILED (hr))
+ {
+ FAIL ("Analyzer failed to generate results.");
return false;
}
- UINT32 maxGlyphs = 3 * length / 2 + 16;
+ uint32_t maxGlyphCount = 3 * textLength / 2 + 16;
+ uint32_t glyphCount;
+ bool isRightToLeft = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
+
+ const wchar_t localeName[20] = {0};
+ if (buffer->props.language != NULL)
+ {
+ mbstowcs ((wchar_t*) localeName,
+ hb_language_to_string (buffer->props.language), 20);
+ }
+
+ DWRITE_TYPOGRAPHIC_FEATURES singleFeatures;
+ singleFeatures.featureCount = num_features;
+ if (num_features)
+ {
+ DWRITE_FONT_FEATURE* dwfeatureArray = (DWRITE_FONT_FEATURE*)
+ malloc (sizeof (DWRITE_FONT_FEATURE) * num_features);
+ for (unsigned int i = 0; i < num_features; ++i)
+ {
+ dwfeatureArray[i].nameTag = (DWRITE_FONT_FEATURE_TAG)
+ hb_uint32_swap (features[i].tag);
+ dwfeatureArray[i].parameter = features[i].value;
+ }
+ singleFeatures.features = dwfeatureArray;
+ }
+ const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures =
+ (const DWRITE_TYPOGRAPHIC_FEATURES*) &singleFeatures;
+ const uint32_t featureRangeLengths[] = { textLength };
-#define INITIAL_GLYPH_SIZE 400
- UINT16* clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
- UINT16* glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
+retry_getglyphs:
+ uint16_t* clusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
+ uint16_t* glyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*)
- malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES));
+ malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_TEXT_PROPERTIES));
DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
- malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
-
- UINT32 actualGlyphs;
-
- bool backward = HB_DIRECTION_IS_BACKWARD(buffer->props.direction);
-
- wchar_t lang[4];
- mbstowcs(lang, hb_language_to_string(buffer->props.language), 4);
- hr = analyzer->GetGlyphs(pchars, length,
- fontFace, FALSE,
- buffer->props.direction,
- &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0,
- maxGlyphs, clusters, textProperties,
- glyphs, glyphProperties, &actualGlyphs);
-
- if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
- free(clusters);
- free(glyphs);
- free(textProperties);
- free(glyphProperties);
-
- clusters = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
- glyphs = (UINT16*)malloc(INITIAL_GLYPH_SIZE * sizeof(UINT16));
- textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*)
- malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_TEXT_PROPERTIES));
- glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*)
- malloc(INITIAL_GLYPH_SIZE * sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
-
- hr = analyzer->GetGlyphs(pchars, length,
- fontFace, FALSE,
- buffer->props.direction,
- &runHead->mScript, (const wchar_t*)lang, NULL, NULL, NULL, 0,
- maxGlyphs, clusters, textProperties,
- glyphs, glyphProperties, &actualGlyphs);
- }
- if (FAILED(hr)) {
- //NS_WARNING("Analyzer failed to get glyphs.");
+ malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES));
+
+ hr = analyzer->GetGlyphs (textString, textLength, fontFace, FALSE,
+ isRightToLeft, &runHead->mScript, localeName, NULL, &dwFeatures,
+ featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices,
+ glyphProperties, &glyphCount);
+
+ if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)))
+ {
+ free (clusterMap);
+ free (glyphIndices);
+ free (textProperties);
+ free (glyphProperties);
+
+ maxGlyphCount *= 2;
+
+ goto retry_getglyphs;
+ }
+ if (FAILED (hr))
+ {
+ FAIL ("Analyzer failed to get glyphs.");
return false;
}
- FLOAT advances[400];
- DWRITE_GLYPH_OFFSET offsets[400];
-
+ float* glyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float));
+ DWRITE_GLYPH_OFFSET* glyphOffsets = (DWRITE_GLYPH_OFFSET*)
+ malloc(maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET));
/* The -2 in the following is to compensate for possible
* alignment needed after the WORD array. sizeof(WORD) == 2. */
- unsigned int glyphs_size = (scratch_size * sizeof (int)-2)
- / (sizeof (WORD) +
- 4 + // sizeof (SCRIPT_GLYPHPROP) +
- sizeof (int) +
- 8 + // sizeof (GOFFSET) +
- sizeof (uint32_t));
- ALLOCATE_ARRAY(uint32_t, vis_clusters, glyphs_size);
+ unsigned int glyphs_size = (scratch_size * sizeof(int) - 2)
+ / (sizeof(WORD) +
+ sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES) +
+ sizeof(int) +
+ sizeof(DWRITE_GLYPH_OFFSET) +
+ sizeof(uint32_t));
+ ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
#undef ALLOCATE_ARRAY
- hr = analyzer->GetGlyphPlacements(pchars,
- clusters,
- textProperties,
- length,
- glyphs,
- glyphProperties,
- actualGlyphs,
- fontFace,
- face->get_upem(),
- FALSE,
- FALSE,
- &runHead->mScript,
- NULL,
- NULL,
- NULL,
- 0,
- advances,
- offsets);
-
- if (FAILED(hr)) {
- //NS_WARNING("Analyzer failed to get glyph placements.");
+ int fontEmSize = font->face->get_upem();
+ if (fontEmSize < 0)
+ fontEmSize = -fontEmSize;
+
+ if (fontEmSize < 0)
+ fontEmSize = -fontEmSize;
+ double x_mult = (double) font->x_scale / fontEmSize;
+ double y_mult = (double) font->y_scale / fontEmSize;
+
+ hr = analyzer->GetGlyphPlacements (textString,
+ clusterMap, textProperties, textLength, glyphIndices,
+ glyphProperties, glyphCount, fontFace, fontEmSize,
+ FALSE, isRightToLeft, &runHead->mScript, localeName,
+ &dwFeatures, featureRangeLengths, 1,
+ glyphAdvances, glyphOffsets);
+
+ if (FAILED (hr))
+ {
+ FAIL ("Analyzer failed to get glyph placements.");
return false;
}
- unsigned int glyphs_len = actualGlyphs;
+#ifdef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION
+
+ DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities =
+ (DWRITE_JUSTIFICATION_OPPORTUNITY*)
+ malloc (maxGlyphCount * sizeof (DWRITE_JUSTIFICATION_OPPORTUNITY));
+ hr = analyzer->GetJustificationOpportunities (fontFace, fontEmSize,
+ runHead->mScript, textLength, glyphCount, textString, clusterMap,
+ glyphProperties, justificationOpportunities);
+
+ if (FAILED (hr))
+ {
+ FAIL ("Analyzer failed to get justification opportunities.");
+ return false;
+ }
+
+ // TODO: get lineWith from somewhere
+ float lineWidth = 60000;
+
+ float* justifiedGlyphAdvances =
+ (float*) malloc (maxGlyphCount * sizeof (float));
+ DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
+ malloc (glyphCount * sizeof (DWRITE_GLYPH_OFFSET));
+ hr = analyzer->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities,
+ glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets);
+
+ if (FAILED (hr))
+ {
+ FAIL ("Analyzer failed to get justified glyph advances.");
+ return false;
+ }
+
+ DWRITE_SCRIPT_PROPERTIES scriptProperties;
+ hr = analyzer->GetScriptProperties (runHead->mScript, &scriptProperties);
+ if (FAILED (hr))
+ {
+ FAIL ("Analyzer failed to get script properties.");
+ return false;
+ }
+ uint32_t justificationCharacter = scriptProperties.justificationCharacter;
+
+ // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
+ if (justificationCharacter != 32)
+ {
+retry_getjustifiedglyphs:
+ uint16_t* modifiedClusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
+ uint16_t* modifiedGlyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t));
+ float* modifiedGlyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float));
+ DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*)
+ malloc (maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET));
+ uint32_t actualGlyphsCount;
+ hr = analyzer->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript,
+ textLength, glyphCount, maxGlyphCount, clusterMap, glyphIndices,
+ glyphAdvances, justifiedGlyphAdvances, justifiedGlyphOffsets,
+ glyphProperties, &actualGlyphsCount, modifiedClusterMap, modifiedGlyphIndices,
+ modifiedGlyphAdvances, modifiedGlyphOffsets);
+
+ if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))
+ {
+ maxGlyphCount = actualGlyphsCount;
+ free (modifiedClusterMap);
+ free (modifiedGlyphIndices);
+ free (modifiedGlyphAdvances);
+ free (modifiedGlyphOffsets);
+
+ maxGlyphCount = actualGlyphsCount;
+
+ goto retry_getjustifiedglyphs;
+ }
+ if (FAILED (hr))
+ {
+ FAIL ("Analyzer failed to get justified glyphs.");
+ return false;
+ }
+
+ free (clusterMap);
+ free (glyphIndices);
+ free (glyphAdvances);
+ free (glyphOffsets);
+
+ glyphCount = actualGlyphsCount;
+ clusterMap = modifiedClusterMap;
+ glyphIndices = modifiedGlyphIndices;
+ glyphAdvances = modifiedGlyphAdvances;
+ glyphOffsets = modifiedGlyphOffsets;
+
+ free(justifiedGlyphAdvances);
+ free(justifiedGlyphOffsets);
+ }
+ else
+ {
+ free(glyphAdvances);
+ free(glyphOffsets);
+
+ glyphAdvances = justifiedGlyphAdvances;
+ glyphOffsets = justifiedGlyphOffsets;
+ }
+
+ free(justificationOpportunities);
+
+#endif
/* Ok, we've got everything we need, now compose output buffer,
* very, *very*, carefully! */
/* Calculate visual-clusters. That's what we ship. */
- for (unsigned int i = 0; i < glyphs_len; i++)
+ for (unsigned int i = 0; i < glyphCount; i++)
vis_clusters[i] = -1;
- for (unsigned int i = 0; i < buffer->len; i++) {
- uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
- //*p = MIN (*p, buffer->info[i].cluster);
+ for (unsigned int i = 0; i < buffer->len; i++)
+ {
+ uint32_t *p =
+ &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
+ *p = MIN (*p, buffer->info[i].cluster);
}
- for (unsigned int i = 1; i < glyphs_len; i++)
+ for (unsigned int i = 1; i < glyphCount; i++)
if (vis_clusters[i] == -1)
vis_clusters[i] = vis_clusters[i - 1];
#undef utf16_index
- //if (unlikely (!buffer->ensure (glyphs_len)))
- // FAIL ("Buffer in error");
+ if (unlikely (!buffer->ensure (glyphCount)))
+ FAIL ("Buffer in error");
#undef FAIL
/* Set glyph infos */
buffer->len = 0;
- for (unsigned int i = 0; i < glyphs_len; i++)
+ for (unsigned int i = 0; i < glyphCount; i++)
{
hb_glyph_info_t *info = &buffer->info[buffer->len++];
- info->codepoint = glyphs[i];
+ info->codepoint = glyphIndices[i];
info->cluster = vis_clusters[i];
/* The rest is crap. Let's store position info there for now. */
- info->mask = advances[i];
- info->var1.u32 = offsets[i].ascenderOffset;
- info->var2.u32 = -offsets[i].advanceOffset;
+ info->mask = glyphAdvances[i];
+ info->var1.i32 = glyphOffsets[i].advanceOffset;
+ info->var2.i32 = glyphOffsets[i].ascenderOffset;
}
- free(clusters);
- free(glyphs);
- free(textProperties);
- free(glyphProperties);
-
/* Set glyph positions */
buffer->clear_positions ();
- for (unsigned int i = 0; i < glyphs_len; i++)
+ for (unsigned int i = 0; i < glyphCount; i++)
{
hb_glyph_info_t *info = &buffer->info[i];
hb_glyph_position_t *pos = &buffer->pos[i];
/* TODO vertical */
- pos->x_advance = info->mask;
- pos->x_offset = backward ? -info->var1.u32 : info->var1.u32;
- pos->y_offset = info->var2.u32;
+ pos->x_advance = x_mult * (int32_t) info->mask;
+ pos->x_offset =
+ x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32);
+ pos->y_offset = y_mult * info->var2.i32;
}
- if (backward)
+ if (isRightToLeft)
hb_buffer_reverse (buffer);
+ free (clusterMap);
+ free (glyphIndices);
+ free (textProperties);
+ free (glyphProperties);
+ free (glyphAdvances);
+ free (glyphOffsets);
+
+ if (num_features)
+ free (singleFeatures.features);
+
/* Wow, done! */
return true;
}
diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc
index b5ebfc046..e2ad24001 100644
--- a/src/hb-fallback-shape.cc
+++ b/src/hb-fallback-shape.cc
@@ -106,7 +106,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
*/
hb_codepoint_t space;
- bool has_space = (bool) font->get_glyph (' ', 0, &space);
+ bool has_space = (bool) font->get_nominal_glyph (' ', &space);
buffer->clear_positions ();
@@ -123,7 +123,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
pos[i].y_advance = 0;
continue;
}
- font->get_glyph (info[i].codepoint, 0, &info[i].codepoint);
+ font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint);
font->get_glyph_advance_for_direction (info[i].codepoint,
direction,
&pos[i].x_advance,
diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 9138c236d..8da40a992 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -44,7 +44,8 @@
#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
- HB_FONT_FUNC_IMPLEMENT (glyph) \
+ HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
+ HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
@@ -180,16 +181,25 @@ struct hb_font_t {
inline bool has_glyph (hb_codepoint_t unicode)
{
hb_codepoint_t glyph;
- return get_glyph (unicode, 0, &glyph);
+ return get_nominal_glyph (unicode, &glyph);
}
- inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph)
+ inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
+ hb_codepoint_t *glyph)
{
*glyph = 0;
- return klass->get.f.glyph (this, user_data,
- unicode, variation_selector, glyph,
- klass->user_data.glyph);
+ return klass->get.f.nominal_glyph (this, user_data,
+ unicode, glyph,
+ klass->user_data.nominal_glyph);
+ }
+
+ inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph)
+ {
+ *glyph = 0;
+ return klass->get.f.variation_glyph (this, user_data,
+ unicode, variation_selector, glyph,
+ klass->user_data.variation_glyph);
}
inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
@@ -487,7 +497,7 @@ struct hb_font_t {
hb_codepoint_t unichar;
if (0 == strncmp (s, "uni", 3) &&
hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
- get_glyph (unichar, 0, glyph))
+ get_nominal_glyph (unichar, glyph))
return true;
}
diff --git a/src/hb-font.cc b/src/hb-font.cc
index c038b1087..6a4823ab5 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -93,27 +93,48 @@ hb_font_get_font_v_extents_parent (hb_font_t *font,
}
static hb_bool_t
-hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
- void *font_data HB_UNUSED,
- hb_codepoint_t unicode,
- hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph,
- void *user_data HB_UNUSED)
+hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
{
*glyph = 0;
return false;
}
static hb_bool_t
-hb_font_get_glyph_parent (hb_font_t *font,
- void *font_data HB_UNUSED,
- hb_codepoint_t unicode,
- hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph,
- void *user_data HB_UNUSED)
+hb_font_get_nominal_glyph_parent (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
{
- return font->parent->get_glyph (unicode, variation_selector, glyph);
+ return font->parent->get_nominal_glyph (unicode, glyph);
}
+static hb_bool_t
+hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
+{
+ *glyph = 0;
+ return false;
+}
+static hb_bool_t
+hb_font_get_variation_glyph_parent (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
+{
+ return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
+}
+
+
static hb_position_t
hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
@@ -622,7 +643,50 @@ hb_font_get_glyph (hb_font_t *font,
hb_codepoint_t unicode, hb_codepoint_t variation_selector,
hb_codepoint_t *glyph)
{
- return font->get_glyph (unicode, variation_selector, glyph);
+ if (unlikely (variation_selector))
+ return font->get_variation_glyph (unicode, variation_selector, glyph);
+ return font->get_nominal_glyph (unicode, glyph);
+}
+
+/**
+ * hb_font_get_nominal_glyph:
+ * @font: a font.
+ * @unicode:
+ * @glyph: (out):
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 1.2.3
+ **/
+hb_bool_t
+hb_font_get_nominal_glyph (hb_font_t *font,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph)
+{
+ return font->get_nominal_glyph (unicode, glyph);
+}
+
+/**
+ * hb_font_get_variation_glyph:
+ * @font: a font.
+ * @unicode:
+ * @variation_selector:
+ * @glyph: (out):
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 1.2.3
+ **/
+hb_bool_t
+hb_font_get_variation_glyph (hb_font_t *font,
+ hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph)
+{
+ return font->get_variation_glyph (unicode, variation_selector, glyph);
}
/**
@@ -1472,3 +1536,131 @@ hb_font_get_ppem (hb_font_t *font,
if (x_ppem) *x_ppem = font->x_ppem;
if (y_ppem) *y_ppem = font->y_ppem;
}
+
+
+#ifndef HB_DISABLE_DEPRECATED
+
+/*
+ * Deprecated get_glyph_func():
+ */
+
+struct hb_trampoline_closure_t
+{
+ void *user_data;
+ hb_destroy_func_t destroy;
+ unsigned int ref_count;
+};
+
+template <typename FuncType>
+struct hb_trampoline_t
+{
+ hb_trampoline_closure_t closure; /* Must be first. */
+ FuncType func;
+};
+
+template <typename FuncType>
+static hb_trampoline_t<FuncType> *
+trampoline_create (FuncType func,
+ void *user_data,
+ hb_destroy_func_t destroy)
+{
+ typedef hb_trampoline_t<FuncType> trampoline_t;
+
+ trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
+
+ if (unlikely (!trampoline))
+ return NULL;
+
+ trampoline->closure.user_data = user_data;
+ trampoline->closure.destroy = destroy;
+ trampoline->closure.ref_count = 1;
+ trampoline->func = func;
+
+ return trampoline;
+}
+
+static void
+trampoline_reference (hb_trampoline_closure_t *closure)
+{
+ closure->ref_count++;
+}
+
+static void
+trampoline_destroy (void *user_data)
+{
+ hb_trampoline_closure_t *closure = (hb_trampoline_closure_t *) user_data;
+
+ if (--closure->ref_count)
+ return;
+
+ if (closure->destroy)
+ closure->destroy (closure->user_data);
+ free (closure);
+}
+
+typedef hb_trampoline_t<hb_font_get_glyph_func_t> hb_font_get_glyph_trampoline_t;
+
+static hb_bool_t
+hb_font_get_nominal_glyph_trampoline (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data)
+{
+ hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
+ return trampoline->func (font, font_data, unicode, 0, glyph, trampoline->closure.user_data);
+}
+
+static hb_bool_t
+hb_font_get_variation_glyph_trampoline (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data)
+{
+ hb_font_get_glyph_trampoline_t *trampoline = (hb_font_get_glyph_trampoline_t *) user_data;
+ return trampoline->func (font, font_data, unicode, variation_selector, glyph, trampoline->closure.user_data);
+}
+
+/**
+ * hb_font_funcs_set_glyph_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ * Deprecated. Use hb_font_funcs_set_nominal_glyph_func() and
+ * hb_font_funcs_set_variation_glyph_func() instead.
+ *
+ * Since: 0.9.2
+ * Deprecated: 1.2.3
+ **/
+void
+hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_func_t func,
+ void *user_data, hb_destroy_func_t destroy)
+{
+ hb_font_get_glyph_trampoline_t *trampoline;
+
+ trampoline = trampoline_create (func, user_data, destroy);
+ if (unlikely (!trampoline))
+ {
+ if (destroy)
+ destroy (user_data);
+ return;
+ }
+
+ hb_font_funcs_set_nominal_glyph_func (ffuncs,
+ hb_font_get_nominal_glyph_trampoline,
+ trampoline,
+ trampoline_destroy);
+
+ trampoline_reference (&trampoline->closure);
+ hb_font_funcs_set_variation_glyph_func (ffuncs,
+ hb_font_get_variation_glyph_trampoline,
+ trampoline,
+ trampoline_destroy);
+}
+
+#endif /* HB_DISABLE_DEPRECATED */
diff --git a/src/hb-font.h b/src/hb-font.h
index 82d056c01..2b6ab5088 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -116,10 +116,14 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
-typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
- hb_codepoint_t unicode, hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph,
- void *user_data);
+typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data);
+typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data);
typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
@@ -197,7 +201,7 @@ hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs,
void *user_data, hb_destroy_func_t destroy);
/**
- * hb_font_funcs_set_glyph_func:
+ * hb_font_funcs_set_nominal_glyph_func:
* @ffuncs: font functions.
* @func: (closure user_data) (destroy destroy) (scope notified):
* @user_data:
@@ -205,12 +209,28 @@ hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs,
*
*
*
- * Since: 0.9.2
+ * Since: 1.2.3
+ **/
+HB_EXTERN void
+hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_nominal_glyph_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_variation_glyph_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 1.2.3
**/
HB_EXTERN void
-hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_func_t func,
- void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_variation_glyph_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
/**
* hb_font_funcs_set_glyph_h_advance_func:
@@ -382,9 +402,13 @@ hb_font_get_v_extents (hb_font_t *font,
hb_font_extents_t *extents);
HB_EXTERN hb_bool_t
-hb_font_get_glyph (hb_font_t *font,
- hb_codepoint_t unicode, hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph);
+hb_font_get_nominal_glyph (hb_font_t *font,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph);
+HB_EXTERN hb_bool_t
+hb_font_get_variation_glyph (hb_font_t *font,
+ hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph);
HB_EXTERN hb_position_t
hb_font_get_glyph_h_advance (hb_font_t *font,
@@ -431,6 +455,13 @@ hb_font_get_glyph_from_name (hb_font_t *font,
/* high-level funcs, with fallback */
+/* Calls either hb_font_get_nominal_glyph() if variation_selector is 0,
+ * otherwise callse hb_font_get_variation_glyph(). */
+HB_EXTERN hb_bool_t
+hb_font_get_glyph (hb_font_t *font,
+ hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph);
+
HB_EXTERN void
hb_font_get_extents_for_direction (hb_font_t *font,
hb_direction_t direction,
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index eed1787da..2cad8c264 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -155,21 +155,32 @@ hb_ft_font_get_face (hb_font_t *font)
static hb_bool_t
-hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
- void *font_data,
- hb_codepoint_t unicode,
- hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph,
- void *user_data HB_UNUSED)
-
+hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
- unsigned int g;
+ unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
+
+ if (unlikely (!g))
+ return false;
+
+ *glyph = g;
+ return true;
+}
- if (likely (!variation_selector))
- g = FT_Get_Char_Index (ft_font->ft_face, unicode);
- else
- g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
+static hb_bool_t
+hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
+{
+ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
if (unlikely (!g))
return false;
@@ -408,7 +419,8 @@ retry:
hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, NULL, NULL);
//hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, NULL, NULL);
- hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL);
+ hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, NULL, NULL);
+ hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, NULL, NULL);
hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL);
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL);
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL);
diff --git a/src/hb-icu.cc b/src/hb-icu.cc
index 24cec9d72..ee54721fd 100644
--- a/src/hb-icu.cc
+++ b/src/hb-icu.cc
@@ -36,6 +36,7 @@
#include <unicode/uchar.h>
#include <unicode/unorm.h>
#include <unicode/ustring.h>
+#include <unicode/utf16.h>
#include <unicode/uversion.h>
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 6a5200087..80ad68774 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -662,6 +662,15 @@ typedef SHORT FWORD;
/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
typedef USHORT UFWORD;
+/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
+struct F2DOT14 : SHORT
+{
+ //inline float to_float (void) const { return ???; }
+ //inline void set_float (float f) { v.set (f * ???); }
+ public:
+ DEFINE_SIZE_STATIC (2);
+};
+
/* Date represented in number of seconds since 12:00 midnight, January 1,
* 1904. The value is represented as a signed 64-bit integer. */
struct LONGDATETIME
@@ -742,7 +751,7 @@ struct CheckSum : ULONG
template <typename FixedType=USHORT>
struct FixedVersion
{
- inline uint32_t to_int (void) const { return (major << sizeof(FixedType)) + minor; }
+ inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
inline bool sanitize (hb_sanitize_context_t *c) const
{
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index c9161f0ef..d7a94a1ef 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -69,61 +69,78 @@ struct CmapSubtableFormat0
struct CmapSubtableFormat4
{
- inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+ struct accelerator_t
{
- unsigned int segCount;
- const USHORT *endCount;
- const USHORT *startCount;
- const USHORT *idDelta;
- const USHORT *idRangeOffset;
- const USHORT *glyphIdArray;
- unsigned int glyphIdArrayLength;
+ inline void init (const CmapSubtableFormat4 *subtable)
+ {
+ segCount = subtable->segCountX2 / 2;
+ endCount = subtable->values;
+ startCount = endCount + segCount + 1;
+ idDelta = startCount + segCount;
+ idRangeOffset = idDelta + segCount;
+ glyphIdArray = idRangeOffset + segCount;
+ glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
+ }
- segCount = this->segCountX2 / 2;
- endCount = this->values;
- startCount = endCount + segCount + 1;
- idDelta = startCount + segCount;
- idRangeOffset = idDelta + segCount;
- glyphIdArray = idRangeOffset + segCount;
- glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2;
-
- /* Custom two-array bsearch. */
- int min = 0, max = (int) segCount - 1;
- unsigned int i;
- while (min <= max)
+ static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
{
- int mid = (min + max) / 2;
- if (codepoint < startCount[mid])
- max = mid - 1;
- else if (codepoint > endCount[mid])
- min = mid + 1;
+ const accelerator_t *thiz = (const accelerator_t *) obj;
+
+ /* Custom two-array bsearch. */
+ int min = 0, max = (int) thiz->segCount - 1;
+ const USHORT *startCount = thiz->startCount;
+ const USHORT *endCount = thiz->endCount;
+ unsigned int i;
+ while (min <= max)
+ {
+ int mid = (min + max) / 2;
+ if (codepoint < startCount[mid])
+ max = mid - 1;
+ else if (codepoint > endCount[mid])
+ min = mid + 1;
+ else
+ {
+ i = mid;
+ goto found;
+ }
+ }
+ return false;
+
+ found:
+ hb_codepoint_t gid;
+ unsigned int rangeOffset = thiz->idRangeOffset[i];
+ if (rangeOffset == 0)
+ gid = codepoint + thiz->idDelta[i];
else
{
- i = mid;
- goto found;
+ /* Somebody has been smoking... */
+ unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
+ if (unlikely (index >= thiz->glyphIdArrayLength))
+ return false;
+ gid = thiz->glyphIdArray[index];
+ if (unlikely (!gid))
+ return false;
+ gid += thiz->idDelta[i];
}
- }
- return false;
-
- found:
- hb_codepoint_t gid;
- unsigned int rangeOffset = idRangeOffset[i];
- if (rangeOffset == 0)
- gid = codepoint + idDelta[i];
- else
- {
- /* Somebody has been smoking... */
- unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount;
- if (unlikely (index >= glyphIdArrayLength))
- return false;
- gid = glyphIdArray[index];
- if (unlikely (!gid))
- return false;
- gid += idDelta[i];
+
+ *glyph = gid & 0xFFFFu;
+ return true;
}
- *glyph = gid & 0xFFFFu;
- return true;
+ const USHORT *endCount;
+ const USHORT *startCount;
+ const USHORT *idDelta;
+ const USHORT *idRangeOffset;
+ const USHORT *glyphIdArray;
+ unsigned int segCount;
+ unsigned int glyphIdArrayLength;
+ };
+
+ inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+ {
+ accelerator_t accel;
+ accel.init (this);
+ return accel.get_glyph_func (&accel, codepoint, glyph);
}
inline bool sanitize (hb_sanitize_context_t *c) const
@@ -388,7 +405,7 @@ struct CmapSubtableFormat14
}
protected:
- USHORT format; /* Format number is set to 0. */
+ USHORT format; /* Format number is set to 14. */
ULONG lengthZ; /* Byte length of this subtable. */
SortedArrayOf<VariationSelectorRecord, ULONG>
record; /* Variation selector records; sorted
@@ -416,16 +433,6 @@ struct CmapSubtable
}
}
- inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
- hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph) const
- {
- switch (u.format) {
- case 14: return u.format14.get_glyph_variant(codepoint, variation_selector, glyph);
- default: return GLYPH_VARIANT_NOT_FOUND;
- }
- }
-
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -442,7 +449,7 @@ struct CmapSubtable
}
}
- protected:
+ public:
union {
USHORT format; /* Format identifier */
CmapSubtableFormat0 format0;
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index e7b57b88a..61c703655 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -201,10 +201,26 @@ struct hb_ot_face_glyf_accelerator_t
}
};
+typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
+ hb_codepoint_t codepoint,
+ hb_codepoint_t *glyph);
+
+template <typename Type>
+static inline bool get_glyph_from (const void *obj,
+ hb_codepoint_t codepoint,
+ hb_codepoint_t *glyph)
+{
+ const Type *typed_obj = (const Type *) obj;
+ return typed_obj->get_glyph (codepoint, glyph);
+}
+
struct hb_ot_face_cmap_accelerator_t
{
- const OT::CmapSubtable *table;
- const OT::CmapSubtable *uvs_table;
+ hb_cmap_get_glyph_func_t get_glyph_func;
+ const void *get_glyph_data;
+ OT::CmapSubtableFormat4::accelerator_t format4_accel;
+
+ const OT::CmapSubtableFormat14 *uvs_table;
hb_blob_t *blob;
inline void init (hb_face_t *face)
@@ -212,7 +228,7 @@ struct hb_ot_face_cmap_accelerator_t
this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap));
const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob);
const OT::CmapSubtable *subtable = NULL;
- const OT::CmapSubtable *subtable_uvs = NULL;
+ const OT::CmapSubtableFormat14 *subtable_uvs = NULL;
/* 32-bit subtables. */
if (!subtable) subtable = cmap->find_subtable (3, 10);
@@ -229,12 +245,30 @@ struct hb_ot_face_cmap_accelerator_t
if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
/* UVS subtable. */
- if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5);
+ if (!subtable_uvs)
+ {
+ const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
+ if (st && st->u.format == 14)
+ subtable_uvs = &st->u.format14;
+ }
/* Meh. */
- if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable);
+ if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14);
- this->table = subtable;
this->uvs_table = subtable_uvs;
+
+ this->get_glyph_data = subtable;
+ switch (subtable->u.format) {
+ /* Accelerate format 4 and format 12. */
+ default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>; break;
+ case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>; break;
+ case 4:
+ {
+ this->format4_accel.init (&subtable->u.format4);
+ this->get_glyph_data = &this->format4_accel;
+ this->get_glyph_func = this->format4_accel.get_glyph_func;
+ }
+ break;
+ }
}
inline void fini (void)
@@ -242,23 +276,26 @@ struct hb_ot_face_cmap_accelerator_t
hb_blob_destroy (this->blob);
}
- inline bool get_glyph (hb_codepoint_t unicode,
- hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph) const
+ inline bool get_nominal_glyph (hb_codepoint_t unicode,
+ hb_codepoint_t *glyph) const
+ {
+ return this->get_glyph_func (this->get_glyph_data, unicode, glyph);
+ }
+
+ inline bool get_variation_glyph (hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph) const
{
- if (unlikely (variation_selector))
+ switch (this->uvs_table->get_glyph_variant (unicode,
+ variation_selector,
+ glyph))
{
- switch (this->uvs_table->get_glyph_variant (unicode,
- variation_selector,
- glyph))
- {
- case OT::GLYPH_VARIANT_NOT_FOUND: return false;
- case OT::GLYPH_VARIANT_FOUND: return true;
- case OT::GLYPH_VARIANT_USE_DEFAULT: break;
- }
+ case OT::GLYPH_VARIANT_NOT_FOUND: return false;
+ case OT::GLYPH_VARIANT_FOUND: return true;
+ case OT::GLYPH_VARIANT_USE_DEFAULT: break;
}
- return this->table->get_glyph (unicode, glyph);
+ return get_nominal_glyph (unicode, glyph);
}
};
@@ -301,16 +338,27 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font)
static hb_bool_t
-hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
- void *font_data,
- hb_codepoint_t unicode,
- hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph,
- void *user_data HB_UNUSED)
+hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
+
+{
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ return ot_font->cmap.get_nominal_glyph (unicode, glyph);
+}
+static hb_bool_t
+hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
- return ot_font->cmap.get_glyph (unicode, variation_selector, glyph);
+ return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
}
static hb_position_t
@@ -397,7 +445,8 @@ retry:
hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL);
hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL);
- hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL);
+ hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, NULL, NULL);
+ hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, NULL, NULL);
hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL);
hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL);
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL);
diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 9e5af6d10..dc7aa8469 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -90,10 +90,10 @@ struct glyfGlyphHeader
* greater than or equal to zero,
* this is a simple glyph; if negative,
* this is a composite glyph. */
- SHORT xMin; /* Minimum x for coordinate data. */
- SHORT yMin; /* Minimum y for coordinate data. */
- SHORT xMax; /* Maximum x for coordinate data. */
- SHORT yMax; /* Maximum y for coordinate data. */
+ FWORD xMin; /* Minimum x for coordinate data. */
+ FWORD yMin; /* Minimum y for coordinate data. */
+ FWORD xMax; /* Maximum x for coordinate data. */
+ FWORD yMax; /* Maximum y for coordinate data. */
DEFINE_SIZE_STATIC (10);
};
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index 49056e676..a9606b3d2 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -44,8 +44,8 @@ namespace OT {
struct LongMetric
{
- USHORT advance; /* Advance width/height. */
- SHORT lsb; /* Leading (left/top) side bearing. */
+ UFWORD advance; /* Advance width/height. */
+ FWORD lsb; /* Leading (left/top) side bearing. */
public:
DEFINE_SIZE_STATIC (4);
};
@@ -74,7 +74,7 @@ struct _mtx
* be in the array, but that entry is
* required. The last entry applies to
* all subsequent glyphs. */
- SHORT leadingBearingX[VAR]; /* Here the advance is assumed
+ FWORD leadingBearingX[VAR]; /* Here the advance is assumed
* to be the same as the advance
* for the last entry above. The
* number of entries in this array is
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 59dddcf73..bbe390cf7 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -437,22 +437,6 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
o.attach_type() = ATTACH_TYPE_MARK;
o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
- {
- unsigned int i = buffer->idx;
- unsigned int j = glyph_pos;
- hb_glyph_position_t *pos = buffer->pos;
- assert (j < i);
- if (HB_DIRECTION_IS_FORWARD (c->direction))
- for (unsigned int k = j; k < i; k++) {
- pos[i].x_offset -= pos[k].x_advance;
- pos[i].y_offset -= pos[k].y_advance;
- }
- else
- for (unsigned int k = j + 1; k < i + 1; k++) {
- pos[i].x_offset += pos[k].x_advance;
- pos[i].y_offset += pos[k].y_advance;
- }
- }
buffer->idx++;
return_trace (true);
@@ -1593,6 +1577,18 @@ propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direc
{
pos[i].x_offset += pos[j].x_offset;
pos[i].y_offset += pos[j].y_offset;
+
+ assert (j < i);
+ if (HB_DIRECTION_IS_FORWARD (direction))
+ for (unsigned int k = j; k < i; k++) {
+ pos[i].x_offset -= pos[k].x_advance;
+ pos[i].y_offset -= pos[k].y_advance;
+ }
+ else
+ for (unsigned int k = j + 1; k < i + 1; k++) {
+ pos[i].x_offset += pos[k].x_advance;
+ pos[i].y_offset += pos[k].y_advance;
+ }
}
}
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 38c2c6405..7de56cf2a 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -1288,10 +1288,28 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
{
- _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
- _hb_glyph_info_clear_lig_props (&buffer->info[i]);
+ unsigned int props = gdef.get_glyph_props (info[i].codepoint);
+ if (!props)
+ {
+ /* Never mark default-ignorables as marks.
+ * They won't get in the way of lookups anyway,
+ * but having them as mark will cause them to be skipped
+ * over if the lookup-flag says so, but at least for the
+ * Mongolian variation selectors, looks like Uniscribe
+ * marks them as non-mark. Some Mongolian fonts without
+ * GDEF rely on this. Another notable character that
+ * this applies to is COMBINING GRAPHEME JOINER. */
+ props = (_hb_glyph_info_get_general_category (&info[i]) !=
+ HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
+ _hb_glyph_info_is_default_ignorable (&info[i])) ?
+ HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
+ HB_OT_LAYOUT_GLYPH_PROPS_MARK;
+ }
+ _hb_glyph_info_set_glyph_props (&info[i], props);
+ _hb_glyph_info_clear_lig_props (&info[i]);
buffer->info[i].syllable() = 0;
}
}
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index adf232bf1..5628ac34e 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -60,6 +60,35 @@ _hb_ot_layout_create (hb_face_t *face)
layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
+ {
+ /*
+ * The ugly business of blacklisting individual fonts' tables happen here!
+ * See this thread for why we finally had to bend in and do this:
+ * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
+ */
+ unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob);
+ unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob);
+ unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob);
+ if (0
+ || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len) /* Windows 7 timesi.ttf */
+ || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len) /* Windows 7 timesbi.ttf */
+ || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len) /* Windows ??? timesi.ttf */
+ || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len) /* Windows ??? timesbi.ttf */
+ || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len) /* OS X 10.11.3 Times New Roman Italic.ttf */
+ || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len) /* OS X 10.11.3 Times New Roman Bold Italic.ttf */
+ )
+ {
+ /* In certain versions of Times New Roman Italic and Bold Italic,
+ * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
+ * glyph class 3 (mark) in GDEF. Nuke the GDEF to avoid zero-width
+ * double-quote. See:
+ * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
+ */
+ if (3 == layout->gdef->get_glyph_class (5))
+ layout->gdef = &OT::Null(OT::GDEF);
+ }
+ }
+
layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 7bdeddbe1..7822cef8b 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -204,11 +204,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
for (unsigned int table_index = 0; table_index < 2; table_index++)
{
if (required_feature_tag[table_index] == info->tag)
- {
required_feature_stage[table_index] = info->stage[table_index];
- found = true;
- continue;
- }
+
found |= hb_ot_layout_language_find_feature (face,
table_tags[table_index],
script_index[table_index],
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 21256dec5..1e151a778 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -493,12 +493,12 @@ struct indic_shape_plan_t
hb_codepoint_t glyph = virama_glyph;
if (unlikely (virama_glyph == (hb_codepoint_t) -1))
{
- if (!config->virama || !font->get_glyph (config->virama, 0, &glyph))
+ if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
glyph = 0;
/* Technically speaking, the spec says we should apply 'locl' to virama too.
* Maybe one day... */
- /* Our get_glyph() function needs a font, so we can't get the virama glyph
+ /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
* during shape planning... Instead, overwrite it here. It's safe. Don't worry! */
(const_cast<indic_shape_plan_t *> (this))->virama_glyph = glyph;
}
@@ -742,10 +742,6 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
switch (indic_plan->config->base_pos)
{
- default:
- assert (false);
- HB_FALLTHROUGH;
-
case BASE_POS_LAST:
{
/* -> starting from the end of the syllable, move backwards */
@@ -1219,7 +1215,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t dottedcircle_glyph;
- if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
+ if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
@@ -1803,7 +1799,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
hb_codepoint_t glyph;
if (hb_options ().uniscribe_bug_compatible ||
- (c->font->get_glyph (ab, 0, &glyph) &&
+ (c->font->get_nominal_glyph (ab, &glyph) &&
indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
{
/* Ok, safe to use Uniscribe-style decomposition. */
diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc
index 7b043440e..545765d5f 100644
--- a/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/hb-ot-shape-complex-myanmar.cc
@@ -439,7 +439,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_codepoint_t dottedcircle_glyph;
- if (!font->get_glyph (0x25CCu, 0, &dottedcircle_glyph))
+ if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc
index 58392b6a9..4322b0d1d 100644
--- a/src/hb-ot-shape-complex-thai.cc
+++ b/src/hb-ot-shape-complex-thai.cc
@@ -139,7 +139,6 @@ thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
};
switch (action) {
- default: assert (false); HB_FALLTHROUGH;
case NOP: return u;
case SD: pua_mappings = SD_mappings; break;
case SDL: pua_mappings = SDL_mappings; break;
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index 6fbfe2b5e..d2b6e63bd 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -499,7 +499,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
return;
hb_glyph_info_t dottedcircle = {0};
- if (!font->get_glyph (0x25CCu, 0, &dottedcircle.codepoint))
+ if (!font->get_nominal_glyph (0x25CCu, &dottedcircle.codepoint))
return;
dottedcircle.use_category() = hb_use_get_categories (0x25CC);
diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc
index c9cf737f4..ea8312b22 100644
--- a/src/hb-ot-shape-fallback.cc
+++ b/src/hb-ot-shape-fallback.cc
@@ -526,7 +526,7 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
case t::SPACE_FIGURE:
for (char u = '0'; u <= '9'; u++)
- if (font->get_glyph (u, 0, &glyph))
+ if (font->get_nominal_glyph (u, &glyph))
{
pos[i].x_advance = font->get_glyph_h_advance (glyph);
break;
@@ -534,9 +534,9 @@ _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
break;
case t::SPACE_PUNCTUATION:
- if (font->get_glyph ('.', 0, &glyph))
+ if (font->get_nominal_glyph ('.', &glyph))
pos[i].x_advance = font->get_glyph_h_advance (glyph);
- else if (font->get_glyph (',', 0, &glyph))
+ else if (font->get_nominal_glyph (',', &glyph))
pos[i].x_advance = font->get_glyph_h_advance (glyph);
break;
diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 3f00b8ee6..107617e81 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -91,7 +91,7 @@ compose_unicode (const hb_ot_shape_normalize_context_t *c,
static inline void
set_glyph (hb_glyph_info_t &info, hb_font_t *font)
{
- font->get_glyph (info.codepoint, 0, &info.glyph_index());
+ font->get_nominal_glyph (info.codepoint, &info.glyph_index());
}
static inline void
@@ -124,10 +124,10 @@ decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint
hb_font_t * const font = c->font;
if (!c->decompose (c, ab, &a, &b) ||
- (b && !font->get_glyph (b, 0, &b_glyph)))
+ (b && !font->get_nominal_glyph (b, &b_glyph)))
return 0;
- bool has_a = (bool) font->get_glyph (a, 0, &a_glyph);
+ bool has_a = (bool) font->get_nominal_glyph (a, &a_glyph);
if (shortest && has_a) {
/* Output a and b */
output_char (buffer, a, a_glyph);
@@ -166,7 +166,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
hb_codepoint_t u = buffer->cur().codepoint;
hb_codepoint_t glyph;
- if (shortest && c->font->get_glyph (u, 0, &glyph))
+ if (shortest && c->font->get_nominal_glyph (u, &glyph))
{
next_char (buffer, glyph);
return;
@@ -178,7 +178,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
return;
}
- if (!shortest && c->font->get_glyph (u, 0, &glyph))
+ if (!shortest && c->font->get_nominal_glyph (u, &glyph))
{
next_char (buffer, glyph);
return;
@@ -188,7 +188,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
{
hb_codepoint_t space_glyph;
hb_unicode_funcs_t::space_t space_type = buffer->unicode->space_fallback_type (u);
- if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_glyph (0x0020u, 0, &space_glyph))
+ if (space_type != hb_unicode_funcs_t::NOT_SPACE && c->font->get_nominal_glyph (0x0020u, &space_glyph))
{
_hb_glyph_info_set_unicode_space_fallback_type (&buffer->cur(), space_type);
next_char (buffer, space_glyph);
@@ -202,7 +202,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
/* U+2011 is the only sensible character that is a no-break version of another character
* and not a space. The space ones are handled already. Handle this lone one. */
hb_codepoint_t other_glyph;
- if (c->font->get_glyph (0x2010u, 0, &other_glyph))
+ if (c->font->get_nominal_glyph (0x2010u, &other_glyph))
{
next_char (buffer, other_glyph);
return;
@@ -221,7 +221,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, uns
for (; buffer->idx < end - 1 && !buffer->in_error;) {
if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
/* The next two lines are some ugly lines... But work. */
- if (font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
+ if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
{
buffer->replace_glyphs (2, 1, &buffer->cur().codepoint);
}
@@ -388,7 +388,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
buffer->cur().codepoint,
&composed) &&
/* And the font has glyph for the composite. */
- font->get_glyph (composed, 0, &glyph))
+ font->get_nominal_glyph (composed, &glyph))
{
/* Composes. */
buffer->next_glyph (); /* Copy to out-buffer. */
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 42b921c6e..7811cb7f8 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -456,7 +456,7 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
return;
hb_codepoint_t space;
- if (c->font->get_glyph (' ', 0, &space))
+ if (c->font->get_nominal_glyph (' ', &space))
{
/* Replace default-ignorables with a zero-advance space glyph. */
for (/*continue*/; i < count; i++)
@@ -524,32 +524,6 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
}
static inline void
-hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
-{
- unsigned int count = c->buffer->len;
- hb_glyph_info_t *info = c->buffer->info;
- for (unsigned int i = 0; i < count; i++)
- {
- hb_ot_layout_glyph_props_flags_t klass;
-
- /* Never mark default-ignorables as marks.
- * They won't get in the way of lookups anyway,
- * but having them as mark will cause them to be skipped
- * over if the lookup-flag says so, but at least for the
- * Mongolian variation selectors, looks like Uniscribe
- * marks them as non-mark. Some Mongolian fonts without
- * GDEF rely on this. Another notable character that
- * this applies to is COMBINING GRAPHEME JOINER. */
- klass = (_hb_glyph_info_get_general_category (&info[i]) !=
- HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
- _hb_glyph_info_is_default_ignorable (&info[i])) ?
- HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
- HB_OT_LAYOUT_GLYPH_PROPS_MARK;
- _hb_glyph_info_set_glyph_props (&info[i], klass);
- }
-}
-
-static inline void
hb_ot_substitute_default (hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
@@ -580,9 +554,6 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
hb_ot_layout_substitute_start (c->font, buffer);
- if (!hb_ot_layout_has_glyph_classes (c->face))
- hb_synthesize_glyph_classes (c);
-
c->plan->substitute (c->font, buffer);
return;
@@ -848,12 +819,12 @@ add_char (hb_font_t *font,
hb_set_t *glyphs)
{
hb_codepoint_t glyph;
- if (font->get_glyph (u, 0, &glyph))
+ if (font->get_nominal_glyph (u, &glyph))
glyphs->add (glyph);
if (mirror)
{
hb_codepoint_t m = unicode->mirroring (u);
- if (m != u && font->get_glyph (m, 0, &glyph))
+ if (m != u && font->get_nominal_glyph (m, &glyph))
glyphs->add (glyph);
}
}
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 7afb25803..179e4e9f7 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -611,6 +611,15 @@ static inline unsigned char TOLOWER (unsigned char c)
/* Debug */
+/* HB_NDEBUG disables some sanity checks that are very safe to disable and
+ * should be disabled in production systems. If NDEBUG is defined, enable
+ * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
+ * light-weight) to be enabled, then HB_DEBUG can be defined to disable
+ * the costlier checks. */
+#ifdef NDEBUG
+#define HB_NDEBUG
+#endif
+
#ifndef HB_DEBUG
#define HB_DEBUG 0
#endif
diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh
index 44fbe582e..ed45374b7 100644
--- a/src/hb-unicode-private.hh
+++ b/src/hb-unicode-private.hh
@@ -224,7 +224,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
switch (u)
{
/* All GC=Zs chars that can use a fallback. */
- default: return NOT_SPACE; /* Shouldn't happen. */
+ default: return NOT_SPACE; /* U+1680 OGHAM SPACE MARK */
case 0x0020u: return SPACE; /* U+0020 SPACE */
case 0x00A0u: return SPACE; /* U+00A0 NO-BREAK SPACE */
case 0x2000u: return SPACE_EM_2; /* U+2000 EN QUAD */
diff --git a/src/hb-version.h b/src/hb-version.h
index 3456e7d68..c5692d233 100644
--- a/src/hb-version.h
+++ b/src/hb-version.h
@@ -38,9 +38,9 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 1
#define HB_VERSION_MINOR 2
-#define HB_VERSION_MICRO 1
+#define HB_VERSION_MICRO 6
-#define HB_VERSION_STRING "1.2.1"
+#define HB_VERSION_STRING "1.2.6"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \
diff --git a/test/api/test-shape.c b/test/api/test-shape.c
index eb244072a..c274f0f7e 100644
--- a/test/api/test-shape.c
+++ b/test/api/test-shape.c
@@ -101,7 +101,7 @@ test_shape (void)
ffuncs = hb_font_funcs_create ();
hb_font_funcs_set_glyph_h_advance_func (ffuncs, glyph_h_advance_func, NULL, NULL);
- hb_font_funcs_set_glyph_func (ffuncs, glyph_func, NULL, NULL);
+ hb_font_funcs_set_glyph_func (ffuncs, glyph_func, malloc (10), free);
hb_font_funcs_set_glyph_h_kerning_func (ffuncs, glyph_h_kerning_func, NULL, NULL);
hb_font_set_funcs (font, ffuncs, NULL, NULL);
hb_font_funcs_destroy (ffuncs);
diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am
index e70dff7f9..6320b02db 100644
--- a/test/shaping/Makefile.am
+++ b/test/shaping/Makefile.am
@@ -54,6 +54,7 @@ TESTS = \
tests/indic-old-spec.tests \
tests/indic-pref-blocking.tests \
tests/ligature-id.tests \
+ tests/mark-filtering-sets.tests \
tests/mongolian-variation-selector.tests \
tests/spaces.tests \
tests/simple.tests \
diff --git a/test/shaping/fonts/sha1sum/07f054357ff8638bac3711b422a1e31180bba863.ttf b/test/shaping/fonts/sha1sum/07f054357ff8638bac3711b422a1e31180bba863.ttf
new file mode 100644
index 000000000..fcd4f3232
--- /dev/null
+++ b/test/shaping/fonts/sha1sum/07f054357ff8638bac3711b422a1e31180bba863.ttf
Binary files differ
diff --git a/test/shaping/fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf b/test/shaping/fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf
new file mode 100644
index 000000000..1dbadde41
--- /dev/null
+++ b/test/shaping/fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf
Binary files differ
diff --git a/test/shaping/run-tests.sh b/test/shaping/run-tests.sh
index 668bb8c9c..021c6f8ac 100755
--- a/test/shaping/run-tests.sh
+++ b/test/shaping/run-tests.sh
@@ -18,10 +18,13 @@ if test $# = 0; then
set /dev/stdin
fi
-IFS=:
for f in "$@"; do
$reference || echo "Running tests in $f"
- while read fontfile options unicodes glyphs_expected; do
+ while IFS=: read fontfile options unicodes glyphs_expected; do
+ if echo "$fontfile" | grep -q '^#'; then
+ $reference || echo "Skipping $fontfile:$unicodes"
+ continue
+ fi
$reference || echo "Testing $fontfile:$unicodes"
glyphs=`$srcdir/hb-unicode-encode "$unicodes" | $hb_shape $options "$srcdir/$fontfile"`
if test $? != 0; then
diff --git a/test/shaping/tests/cursive-positioning.tests b/test/shaping/tests/cursive-positioning.tests
index 503554f43..ce63bd1f2 100644
--- a/test/shaping/tests/cursive-positioning.tests
+++ b/test/shaping/tests/cursive-positioning.tests
@@ -1,3 +1,4 @@
fonts/sha1sum/c4e48b0886ef460f532fb49f00047ec92c432ec0.ttf::U+0643,U+0645,U+0645,U+062B,U+0644:[gid8=4+738|gid5=3@441,1197+0|gid6=3@0,432+405|gid9=2@0,477+452|gid9=1@0,977+452|gid10=0@20,1577+207]
fonts/sha1sum/298c9e1d955f10f6f72c6915c3c6ff9bf9695cec.ttf::U+0643,U+0645,U+0645,U+062B,U+0644:[gid8=4+738|gid5=3@441,1197+0|gid6=3@0,432+405|gid9=2@0,477+500|gid9=1@0,577+452|gid10=0@20,1177+207]
-fonts/sha1sum/706c5d7b625f207bc0d874c67237aad6f1e9cd6f.ttf::U+0B1F,U+0B4D,U+0B1A,U+0B4D,U+0B1A:[ttaorya=0+1307|casubscriptorya=0@-242,104+-231|casubscriptnarroworya=0@20,104+507]
+#fonts/sha1sum/706c5d7b625f207bc0d874c67237aad6f1e9cd6f.ttf::U+0B1F,U+0B4D,U+0B1A,U+0B4D,U+0B1A:[ttaorya=0+1307|casubscriptorya=0@-242,104+-231|casubscriptnarroworya=0@20,104+507]
+fonts/sha1sum/07f054357ff8638bac3711b422a1e31180bba863.ttf:--font-funcs=ot --no-glyph-names:U+0606,U+06E1:[2=0@40,502+0|1=0+1000]
diff --git a/test/shaping/tests/mark-filtering-sets.tests b/test/shaping/tests/mark-filtering-sets.tests
new file mode 100644
index 000000000..7b5c91004
--- /dev/null
+++ b/test/shaping/tests/mark-filtering-sets.tests
@@ -0,0 +1,5 @@
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+062A,U+0629:[glyph837=3@299,1170+0|uni06C1.1=3+502|glyph837=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+0646,U+0629:[glyph837=3@299,1170+0|uni06C1.1=3+502|glyph836=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+0626,U+0629:[glyph837=3@299,1170+0|uni06C1.1=3+502|glyph847=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+062B,U+0629:[glyph837=3@299,1520+0|uni06C1.1=3+502|glyph838=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]
+fonts/sha1sum/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf::U+062A,U+062E,U+0679,U+0629:[glyph837=3@299,1520+0|uni06C1.1=3+502|glyph842=2@149,690+0|uni0628.8=2+532|glyph836=1@-51,1259+0|glyph514=1+196|glyph837=0@655,1751+0|glyph112=0@0,-358+905]