summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbashi@google.com <bashi@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-30 11:34:19 +0000
committerbashi@google.com <bashi@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-30 11:34:19 +0000
commit681d5ae61568fa5e5149027edad6a616bbfd081d (patch)
tree6d1824f16ecb26faf30740d1030e2c27aea9d497
parentfb70ecf10de0dbc5065b677dc9235633afcbef38 (diff)
downloadchromium_src-681d5ae61568fa5e5149027edad6a616bbfd081d.zip
chromium_src-681d5ae61568fa5e5149027edad6a616bbfd081d.tar.gz
chromium_src-681d5ae61568fa5e5149027edad6a616bbfd081d.tar.bz2
Update harfbuzz-ng to 1a5a91dc0d8bf4b72a2f22dc6300b06ad7000b79.
Preparing for using HarfBuzz-ng as a secondary text shaper on mac. CoreText doesn't support OpenType features so we need additional text shaper to support -webkit-font-feature-settings property. I don't think this version is ready for transition on Linux because I could see considerable performance regressions when I run cycler tests. BUG=68551 TEST=None. This CL doesn't change build process for now. Review URL: https://chromiumcodereview.appspot.com/9223010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119661 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--third_party/harfbuzz-ng/COPYING16
-rw-r--r--third_party/harfbuzz-ng/README8
-rw-r--r--third_party/harfbuzz-ng/README.chromium5
-rw-r--r--third_party/harfbuzz-ng/harfbuzz.gyp83
-rw-r--r--third_party/harfbuzz-ng/src/Makefile.am147
-rwxr-xr-xthird_party/harfbuzz-ng/src/check-c-linkage-decls.sh18
-rwxr-xr-xthird_party/harfbuzz-ng/src/check-header-guards.sh20
-rwxr-xr-xthird_party/harfbuzz-ng/src/check-internal-symbols.sh28
-rwxr-xr-xthird_party/harfbuzz-ng/src/check-libstdc++.sh27
-rwxr-xr-xthird_party/harfbuzz-ng/src/gen-arabic-joining-table.py83
-rw-r--r--third_party/harfbuzz-ng/src/hb-blob.c362
-rw-r--r--third_party/harfbuzz-ng/src/hb-blob.cc324
-rw-r--r--third_party/harfbuzz-ng/src/hb-blob.h42
-rw-r--r--third_party/harfbuzz-ng/src/hb-buffer-private.hh150
-rw-r--r--third_party/harfbuzz-ng/src/hb-buffer.cc829
-rw-r--r--third_party/harfbuzz-ng/src/hb-buffer.h83
-rw-r--r--third_party/harfbuzz-ng/src/hb-common.cc372
-rw-r--r--third_party/harfbuzz-ng/src/hb-common.h294
-rw-r--r--third_party/harfbuzz-ng/src/hb-fallback-shape-private.hh (renamed from third_party/harfbuzz-ng/src/hb-language.h)26
-rw-r--r--third_party/harfbuzz-ng/src/hb-fallback-shape.cc62
-rw-r--r--third_party/harfbuzz-ng/src/hb-font-private.h97
-rw-r--r--third_party/harfbuzz-ng/src/hb-font-private.hh163
-rw-r--r--third_party/harfbuzz-ng/src/hb-font.cc857
-rw-r--r--third_party/harfbuzz-ng/src/hb-font.h351
-rw-r--r--third_party/harfbuzz-ng/src/hb-ft.c262
-rw-r--r--third_party/harfbuzz-ng/src/hb-ft.cc439
-rw-r--r--third_party/harfbuzz-ng/src/hb-ft.h16
-rw-r--r--third_party/harfbuzz-ng/src/hb-glib.c64
-rw-r--r--third_party/harfbuzz-ng/src/hb-glib.cc349
-rw-r--r--third_party/harfbuzz-ng/src/hb-glib.h12
-rw-r--r--third_party/harfbuzz-ng/src/hb-gobject-enums.cc259
-rw-r--r--third_party/harfbuzz-ng/src/hb-gobject-enums.cc.tmpl74
-rw-r--r--third_party/harfbuzz-ng/src/hb-gobject-structs.cc63
-rw-r--r--third_party/harfbuzz-ng/src/hb-gobject.h (renamed from third_party/harfbuzz-ng/src/hb-unicode-private.h)54
-rw-r--r--third_party/harfbuzz-ng/src/hb-graphite.cc310
-rw-r--r--third_party/harfbuzz-ng/src/hb-graphite2.cc348
-rw-r--r--third_party/harfbuzz-ng/src/hb-graphite2.h (renamed from third_party/harfbuzz-ng/src/hb-graphite.h)25
-rw-r--r--third_party/harfbuzz-ng/src/hb-icu.c260
-rw-r--r--third_party/harfbuzz-ng/src/hb-icu.cc291
-rw-r--r--third_party/harfbuzz-ng/src/hb-icu.h13
-rw-r--r--third_party/harfbuzz-ng/src/hb-language.c120
-rw-r--r--third_party/harfbuzz-ng/src/hb-mutex-private.hh110
-rw-r--r--third_party/harfbuzz-ng/src/hb-object-private.h141
-rw-r--r--third_party/harfbuzz-ng/src/hb-object-private.hh267
-rw-r--r--third_party/harfbuzz-ng/src/hb-open-file-private.hh10
-rw-r--r--third_party/harfbuzz-ng/src/hb-open-type-private.hh175
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-head-table.hh (renamed from third_party/harfbuzz-ng/src/hb-ot-head-private.hh)13
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh92
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh86
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh30
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh (renamed from third_party/harfbuzz-ng/src/hb-ot-layout-gdef-private.hh)62
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh (renamed from third_party/harfbuzz-ng/src/hb-ot-layout-gpos-private.hh)476
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh (renamed from third_party/harfbuzz-ng/src/hb-ot-layout-gsub-private.hh)143
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh207
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout-private.hh70
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout.cc99
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-layout.h21
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-map-private.hh162
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-map.cc192
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh66
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-name-table.hh129
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh (renamed from third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.h)324
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc81
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh304
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.rl119
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh830
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc765
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-misc.cc55
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh175
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc286
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape-private.hh79
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape.cc334
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-shape.h11
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-tag.cc (renamed from third_party/harfbuzz-ng/src/hb-ot-tag.c)375
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot-tag.h9
-rw-r--r--third_party/harfbuzz-ng/src/hb-ot.h2
-rw-r--r--third_party/harfbuzz-ng/src/hb-private.h270
-rw-r--r--third_party/harfbuzz-ng/src/hb-private.hh632
-rw-r--r--third_party/harfbuzz-ng/src/hb-shape.cc136
-rw-r--r--third_party/harfbuzz-ng/src/hb-shape.h23
-rw-r--r--third_party/harfbuzz-ng/src/hb-tt-font.cc242
-rw-r--r--third_party/harfbuzz-ng/src/hb-unicode-private.hh107
-rw-r--r--third_party/harfbuzz-ng/src/hb-unicode.c364
-rw-r--r--third_party/harfbuzz-ng/src/hb-unicode.cc273
-rw-r--r--third_party/harfbuzz-ng/src/hb-unicode.h312
-rw-r--r--third_party/harfbuzz-ng/src/hb-uniscribe.cc463
-rw-r--r--third_party/harfbuzz-ng/src/hb-uniscribe.h (renamed from third_party/harfbuzz-ng/src/hb-blob-private.h)42
-rw-r--r--third_party/harfbuzz-ng/src/hb-version.h (renamed from third_party/harfbuzz-ng/src/hb-common.c)43
-rw-r--r--third_party/harfbuzz-ng/src/hb.h4
-rw-r--r--third_party/harfbuzz-ng/src/main.cc8
-rw-r--r--third_party/harfbuzz-ng/src/test.c94
-rw-r--r--third_party/harfbuzz/harfbuzz.gyp4
92 files changed, 11670 insertions, 5053 deletions
diff --git a/third_party/harfbuzz-ng/COPYING b/third_party/harfbuzz-ng/COPYING
index 3fb9e51..4bb77a0 100644
--- a/third_party/harfbuzz-ng/COPYING
+++ b/third_party/harfbuzz-ng/COPYING
@@ -1,12 +1,14 @@
HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
-Copyright (C) 2010 Google, Inc.
-Copyright (C) 2006 Behdad Esfahbod
-Copyright (C) 2009 Keith Stribley
-Copyright (C) 2009 Martin Hosken and SIL International
-Copyright (C) 2007 Chris Wilson
-Copyright (C) 2004,2007,2008,2009,2010 Red Hat, Inc.
-Copyright (C) 1998-2004 David Turner and Werner Lemberg
+Copyright © 2011 Codethink Limited
+Copyright © 2010,2011 Google, Inc.
+Copyright © 2006 Behdad Esfahbod
+Copyright © 2009 Keith Stribley
+Copyright © 2009 Martin Hosken and SIL International
+Copyright © 2007 Chris Wilson
+Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
+Copyright © 1998-2004 David Turner and Werner Lemberg
+
For full copyright notices consult the individual files in the package.
diff --git a/third_party/harfbuzz-ng/README b/third_party/harfbuzz-ng/README
index 06aad34..74e739d 100644
--- a/third_party/harfbuzz-ng/README
+++ b/third_party/harfbuzz-ng/README
@@ -1,9 +1,7 @@
This is HarfBuzz, a text shaping library.
-Bug reports on these files should be sent to the HarfBuzz mailing list as
-listed on http://harfbuzz.org/
+For bug reports, mailing list, and other information please visit:
-For license information, see the file COPYING.
+ http://harfbuzz.org/
-Behdad Esfahbod
-18 November 2010
+For license information, see the file COPYING.
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium
index ca393d0..9930732 100644
--- a/third_party/harfbuzz-ng/README.chromium
+++ b/third_party/harfbuzz-ng/README.chromium
@@ -1,7 +1,10 @@
Name: harfbuzz-ng
+Short Name: harfbuzz-ng
URL: http://freedesktop.org/wiki/Software/HarfBuzz
Version: unknown
-Revision: b0d396aa88b3cdf8cea896bfeeba197656e1cdb1
+Date: 20120127
+Revision: 1a5a91dc0d8bf4b72a2f22dc6300b06ad7000b79
+Security Critical: yes
Description:
This is harfbuzz-ng, a new implementation of harfbuzz with a different
diff --git a/third_party/harfbuzz-ng/harfbuzz.gyp b/third_party/harfbuzz-ng/harfbuzz.gyp
index c1ea3e4..ea8e48d 100644
--- a/third_party/harfbuzz-ng/harfbuzz.gyp
+++ b/third_party/harfbuzz-ng/harfbuzz.gyp
@@ -1,4 +1,4 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -8,51 +8,79 @@
],
'targets': [
{
- 'target_name': 'harfbuzz',
+ 'target_name': 'harfbuzz-ng',
'type': 'static_library',
+ 'defines': [
+ 'HAVE_OT',
+ 'HAVE_ICU',
+ ],
'sources': [
- 'src/hb-blob-private.h',
- 'src/hb-blob.c',
+ 'src/hb-blob.cc',
'src/hb-blob.h',
'src/hb-buffer-private.hh',
'src/hb-buffer.cc',
'src/hb-buffer.h',
- 'src/hb-common.c',
+ 'src/hb-common.cc',
'src/hb-common.h',
- 'src/hb-font-private.h',
+ 'src/hb-fallback-shape-private.hh',
+ 'src/hb-fallback-shape.cc',
+ 'src/hb-font-private.hh',
'src/hb-font.cc',
'src/hb-font.h',
- 'src/hb-ft.c',
- 'src/hb-icu.c',
- 'src/hb-language.c',
- 'src/hb-language.h',
- 'src/hb-object-private.h',
+ 'src/hb-glib.cc',
+ 'src/hb-glib.h',
+ 'src/hb-gobject-enums.cc',
+ 'src/hb-gobject-structs.cc',
+ 'src/hb-gobject.h',
+ 'src/hb-icu.cc',
+ 'src/hb-icu.h',
+ 'src/hb-mutex-private.hh',
+ 'src/hb-object-private.hh',
'src/hb-open-file-private.hh',
'src/hb-open-type-private.hh',
- 'src/hb-ot-head-private.hh',
+ 'src/hb-ot-head-table.hh',
+ 'src/hb-ot-hhea-table.hh',
+ 'src/hb-ot-hmtx-table.hh',
'src/hb-ot-layout-common-private.hh',
- 'src/hb-ot-layout-gdef-private.hh',
- 'src/hb-ot-layout-gpos-private.hh',
- 'src/hb-ot-layout-gsub-private.hh',
+ 'src/hb-ot-layout-gdef-table.hh',
+ 'src/hb-ot-layout-gpos-table.hh',
+ 'src/hb-ot-layout-gsub-table.hh',
'src/hb-ot-layout-gsubgpos-private.hh',
'src/hb-ot-layout-private.hh',
'src/hb-ot-layout.cc',
+ 'src/hb-ot-layout.h',
'src/hb-ot-map-private.hh',
'src/hb-ot-map.cc',
- 'src/hb-ot-shape-complex-arabic-table.h',
+ 'src/hb-ot-maxp-table.hh',
+ 'src/hb-ot-name-table.hh',
+ 'src/hb-ot-shape-complex-arabic-table.hh',
'src/hb-ot-shape-complex-arabic.cc',
+ 'src/hb-ot-shape-complex-indic-machine.hh',
+ 'src/hb-ot-shape-complex-indic-table.hh',
+ 'src/hb-ot-shape-complex-indic.cc',
+ 'src/hb-ot-shape-complex-misc.cc',
'src/hb-ot-shape-complex-private.hh',
+ 'src/hb-ot-shape-normalize.cc',
'src/hb-ot-shape-private.hh',
'src/hb-ot-shape.cc',
- 'src/hb-ot-tag.c',
- 'src/hb-private.h',
+ 'src/hb-ot-shape.h',
+ 'src/hb-ot-tag.cc',
+ 'src/hb-ot-tag.h',
+ 'src/hb-ot.h',
+ 'src/hb-private.hh',
'src/hb-shape.cc',
'src/hb-shape.h',
- 'src/hb-unicode-private.h',
- 'src/hb-unicode.c',
+ 'src/hb-tt-font.cc',
+ 'src/hb-unicode-private.hh',
+ 'src/hb-unicode.cc',
'src/hb-unicode.h',
+ 'src/hb-version.h',
'src/hb.h',
],
+ 'sources/': [
+ ['exclude', 'src/hb-glib\\.(cc|h)$'],
+ ['exclude', 'src/hb-gobject.*\\.(cc|h)$'],
+ ],
'include_dirs': [
'src',
],
@@ -62,9 +90,22 @@
],
},
'dependencies': [
- '../../build/linux/system.gyp:freetype2',
'../../third_party/icu/icu.gyp:icuuc',
],
+ 'conditions': [
+ ['use_glib == 1', {
+ 'defines': [
+ 'HAVE_GLIB',
+ ],
+ 'sources/': [
+ ['include', 'src/hb-glib\\.(cc|h)$'],
+ ['include', 'src/hb-gobject.*\\.(cc|h)$'],
+ ],
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ ],
+ }],
+ ],
},
],
}
diff --git a/third_party/harfbuzz-ng/src/Makefile.am b/third_party/harfbuzz-ng/src/Makefile.am
deleted file mode 100644
index 13107b9..0000000
--- a/third_party/harfbuzz-ng/src/Makefile.am
+++ /dev/null
@@ -1,147 +0,0 @@
-# Process this file with automake to produce Makefile.in
-
-NULL =
-EXTRA_DIST =
-
-# The following warning options are useful for debugging: -Wpadded -Wcast-align
-#AM_CXXFLAGS =
-
-lib_LTLIBRARIES = libharfbuzz.la
-
-HBCFLAGS =
-HBLIBS =
-HBSOURCES = \
- hb-blob.c \
- hb-blob-private.h \
- hb-buffer.cc \
- hb-buffer-private.hh \
- hb-common.c \
- hb-font.cc \
- hb-font-private.h \
- hb-object-private.h \
- hb-open-file-private.hh \
- hb-open-type-private.hh \
- hb-language.c \
- hb-ot-head-private.hh \
- hb-private.h \
- hb-shape.cc \
- hb-unicode.c \
- hb-unicode-private.h \
- $(NULL)
-HBHEADERS = \
- hb.h \
- hb-blob.h \
- hb-buffer.h \
- hb-common.h \
- hb-font.h \
- hb-language.h \
- hb-shape.h \
- hb-unicode.h \
- $(NULL)
-
-HBSOURCES += \
- hb-ot-layout.cc \
- hb-ot-layout-common-private.hh \
- hb-ot-layout-gdef-private.hh \
- hb-ot-layout-gpos-private.hh \
- hb-ot-layout-gsubgpos-private.hh \
- hb-ot-layout-gsub-private.hh \
- hb-ot-layout-private.hh \
- hb-ot-map.cc \
- hb-ot-map-private.hh \
- hb-ot-shape.cc \
- hb-ot-shape-complex-arabic.cc \
- hb-ot-shape-complex-arabic-table.h \
- hb-ot-shape-complex-private.hh \
- hb-ot-shape-private.hh \
- hb-ot-tag.c \
- $(NULL)
-HBHEADERS += \
- hb-ot.h \
- hb-ot-layout.h \
- hb-ot-shape.h \
- hb-ot-tag.h \
- $(NULL)
-
-if HAVE_GLIB
-HBCFLAGS += $(GLIB_CFLAGS)
-HBLIBS += $(GLIB_LIBS)
-HBSOURCES += \
- hb-glib.c \
- $(NULL)
-HBHEADERS += \
- hb-glib.h \
- $(NULL)
-endif
-
-if HAVE_ICU
-HBCFLAGS += $(ICU_CFLAGS)
-HBLIBS += $(ICU_LIBS)
-HBSOURCES += \
- hb-icu.c \
- $(NULL)
-HBHEADERS += \
- hb-icu.h \
- $(NULL)
-endif
-
-if HAVE_FREETYPE
-HBCFLAGS += $(FREETYPE_CFLAGS)
-HBLIBS += $(FREETYPE_LIBS)
-HBSOURCES += \
- hb-ft.c \
- $(NULL)
-HBHEADERS += \
- hb-ft.h \
- $(NULL)
-endif
-
-if HAVE_GRAPHITE
-HBCFLAGS += $(GRAPHITE_CFLAGS)
-HBLIBS += $(GRAPHITE_LIBS)
-HBSOURCES += \
- hb-graphite.cc \
- $(NULL)
-HBHEADERS += \
- hb-graphite.h \
- $(NULL)
-endif
-
-CXXLINK = $(LINK)
-libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS)
-libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
-libharfbuzz_la_LIBADD = $(HBLIBS)
-pkginclude_HEADERS = $(HBHEADERS)
-
-
-GENERATORS = \
- gen-arabic-joining-table.py \
- $(NULL)
-
-EXTRA_DIST += $(GENERATORS)
-
-noinst_PROGRAMS = main test
-
-main_SOURCES = main.cc
-main_CPPFLAGS = $(HBCFLAGS)
-main_LDADD = libharfbuzz.la $(HBLIBS)
-
-test_SOURCES = test.c
-test_CPPFLAGS = $(HBCFLAGS)
-test_LDADD = libharfbuzz.la $(HBLIBS)
-
-TESTS = \
- check-c-linkage-decls.sh \
- check-header-guards.sh \
- check-internal-symbols.sh \
- $(NULL)
-
-if HAVE_ICU
-else
-if HAVE_GRAPHITE
-else
-TESTS += check-libstdc++.sh
-endif
-endif
-
--include $(top_srcdir)/git.mk
diff --git a/third_party/harfbuzz-ng/src/check-c-linkage-decls.sh b/third_party/harfbuzz-ng/src/check-c-linkage-decls.sh
deleted file mode 100755
index 711d089..0000000
--- a/third_party/harfbuzz-ng/src/check-c-linkage-decls.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-
-LC_ALL=C
-export LC_ALL
-
-test -z "$srcdir" && srcdir=.
-stat=0
-
-cd "$srcdir"
-
-for x in hb-*.c hb-*.cc hb-*.h hb-*.hh ; do
- if ! grep -q HB_BEGIN_DECLS "$x" || ! grep -q HB_END_DECLS "$x"; then
- echo "Ouch, file $x does not HB_BEGIN_DECLS / HB_END_DECLS"
- stat=1
- fi
-done
-
-exit $stat
diff --git a/third_party/harfbuzz-ng/src/check-header-guards.sh b/third_party/harfbuzz-ng/src/check-header-guards.sh
deleted file mode 100755
index c966cd2..0000000
--- a/third_party/harfbuzz-ng/src/check-header-guards.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-LC_ALL=C
-export LC_ALL
-
-test -z "$srcdir" && srcdir=.
-stat=0
-
-cd "$srcdir"
-
-for x in hb-*.h hb-*.hh ; do
- tag=`echo "$x" | tr 'a-z.-' 'A-Z_'`
- lines=`grep "\<$tag\>" "$x" | wc -l`
- if test "x$lines" != x3; then
- echo "Ouch, header file $x does not have correct preprocessor guards"
- stat=1
- fi
-done
-
-exit $stat
diff --git a/third_party/harfbuzz-ng/src/check-internal-symbols.sh b/third_party/harfbuzz-ng/src/check-internal-symbols.sh
deleted file mode 100755
index 124a7b0..0000000
--- a/third_party/harfbuzz-ng/src/check-internal-symbols.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-
-LC_ALL=C
-export LC_ALL
-
-if which nm 2>/dev/null >/dev/null; then
- :
-else
- echo "check-internal-symbols.sh: 'nm' not found; skipping test"
- exit 0
-fi
-
-test -z "$srcdir" && srcdir=.
-test -z "$MAKE" && MAKE=make
-stat=0
-
-so=.libs/libharfbuzz.so
-if test -f "$so"; then
- echo "Checking that we are exposing internal symbols"
- if nm $so | grep ' T ' | grep -v ' T _fini\>\| T _init\>\| T hb_'; then
- echo "Ouch, internal symbols exposed"
- stat=1
- fi
-else
- echo "check-internal-symbols.sh: libharfbuzz.so not found; skipping test"
-fi
-
-exit $stat
diff --git a/third_party/harfbuzz-ng/src/check-libstdc++.sh b/third_party/harfbuzz-ng/src/check-libstdc++.sh
deleted file mode 100755
index c0abcbe4..0000000
--- a/third_party/harfbuzz-ng/src/check-libstdc++.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-LC_ALL=C
-export LC_ALL
-
-if which ldd 2>/dev/null >/dev/null; then
- :
-else
- echo "check-libstdc++.sh: 'ldd' not found; skipping test"
- exit 0
-fi
-
-test -z "$srcdir" && srcdir=.
-stat=0
-
-so=.libs/libharfbuzz.so
-if test -f "$so"; then
- echo "Checking that we are not linking to libstdc++"
- if ldd $so | grep 'libstdc[+][+]'; then
- echo "Ouch, linked to libstdc++"
- stat=1
- fi
-else
- echo "check-libstdc++.sh: libharfbuzz.so not found; skipping test"
-fi
-
-exit $stat
diff --git a/third_party/harfbuzz-ng/src/gen-arabic-joining-table.py b/third_party/harfbuzz-ng/src/gen-arabic-joining-table.py
deleted file mode 100755
index 08e54db..0000000
--- a/third_party/harfbuzz-ng/src/gen-arabic-joining-table.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/python
-
-import sys
-
-header = sys.stdin.readline (), sys.stdin.readline ()
-while sys.stdin.readline ().find ('##################') < 0:
- pass
-
-
-print "/* == Start of generated table == */"
-print "/*"
-print " * The following table is generated by running:"
-print " *"
-print " * ./gen-arabic-joining-table.py < ArabicShaping.txt"
-print " *"
-print " * on the ArabicShaping.txt file with the header:"
-print " *"
-for line in header:
- print " * %s" % (line.strip())
-print " */"
-
-print "static const uint8_t joining_table[] ="
-print "{"
-
-
-min_u = 0x110000
-max_u = 0
-num = 0
-last = -1
-block = ''
-for line in sys.stdin:
-
- if line[0] == '#':
- if line.find (" characters"):
- block = line[2:].strip ()
- continue
-
- fields = [x.strip () for x in line.split (';')]
- if len (fields) == 1:
- continue
-
- u = int (fields[0], 16)
- if u == 0x200C or u == 0x200D:
- continue
- if u < last:
- raise Exception ("Input data character not sorted", u)
- min_u = min (min_u, u)
- max_u = max (max_u, u)
- num += 1
-
- if block:
- print "\n /* %s */\n" % block
- block = ''
-
- if last != -1:
- last += 1
- while last < u:
- print " JOINING_TYPE_X, /* %04X */" % last
- last += 1
- else:
- last = u
-
- if fields[3] in ["ALAPH", "DALATH RISH"]:
- value = "JOINING_GROUP_" + fields[3].replace(' ', '_')
- else:
- value = "JOINING_TYPE_" + fields[2]
- print " %s, /* %s */" % (value, '; '.join(fields))
-
-print
-print " JOINING_TYPE_X /* dummy */"
-print "};"
-print
-
-print "#define JOINING_TABLE_FIRST 0x%04x" % min_u
-print "#define JOINING_TABLE_LAST 0x%04x" % max_u
-print
-
-print "/* == End of generated table == */"
-
-occupancy = num * 100 / (max_u - min_u + 1)
-# Maintain at least 40% occupancy in the table */
-if occupancy < 40:
- raise Exception ("Table too sparse, please investigate: ", occupancy)
diff --git a/third_party/harfbuzz-ng/src/hb-blob.c b/third_party/harfbuzz-ng/src/hb-blob.c
deleted file mode 100644
index 37e7787..0000000
--- a/third_party/harfbuzz-ng/src/hb-blob.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2009 Red Hat, 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.h"
-
-#include "hb-blob-private.h"
-
-#ifdef HAVE_SYS_MMAN_H
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#include <sys/mman.h>
-#endif /* HAVE_SYS_MMAN_H */
-
-#include <stdio.h>
-#include <errno.h>
-
-HB_BEGIN_DECLS
-
-
-#ifndef HB_DEBUG_BLOB
-#define HB_DEBUG_BLOB (HB_DEBUG+0)
-#endif
-
-hb_blob_t _hb_blob_nil = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
-
- 0, /* length */
-
- HB_MUTEX_INIT, /* lock */
-
- 0, /* lock_count */
- HB_MEMORY_MODE_READONLY, /* mode */
-
- NULL, /* data */
-
- NULL, /* destroy */
- NULL /* user_data */
-};
-
-static void
-_hb_blob_destroy_user_data (hb_blob_t *blob)
-{
- if (blob->destroy) {
- blob->destroy (blob->user_data);
- blob->destroy = NULL;
- blob->user_data = NULL;
- }
-}
-
-static void
-_hb_blob_unlock_and_destroy (hb_blob_t *blob)
-{
- hb_blob_unlock (blob);
- hb_blob_destroy (blob);
-}
-
-hb_blob_t *
-hb_blob_create (const char *data,
- unsigned int length,
- hb_memory_mode_t mode,
- hb_destroy_func_t destroy,
- void *user_data)
-{
- hb_blob_t *blob;
-
- if (!length || !HB_OBJECT_DO_CREATE (hb_blob_t, blob)) {
- if (destroy)
- destroy (user_data);
- return &_hb_blob_nil;
- }
-
- hb_mutex_init (blob->lock);
- blob->lock_count = 0;
-
- blob->data = data;
- blob->length = length;
- blob->mode = mode;
-
- blob->destroy = destroy;
- blob->user_data = user_data;
-
- if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
- blob->mode = HB_MEMORY_MODE_READONLY;
- if (!hb_blob_try_writable (blob)) {
- hb_blob_destroy (blob);
- return &_hb_blob_nil;
- }
- }
-
- return blob;
-}
-
-hb_blob_t *
-hb_blob_create_sub_blob (hb_blob_t *parent,
- unsigned int offset,
- unsigned int length)
-{
- hb_blob_t *blob;
- const char *pdata;
-
- if (!length || offset >= parent->length || !HB_OBJECT_DO_CREATE (hb_blob_t, blob))
- return &_hb_blob_nil;
-
- pdata = hb_blob_lock (parent);
-
- blob->data = pdata + offset;
- blob->length = MIN (length, parent->length - offset);
-
- hb_mutex_lock (parent->lock);
- blob->mode = parent->mode;
- hb_mutex_unlock (parent->lock);
-
- blob->destroy = (hb_destroy_func_t) _hb_blob_unlock_and_destroy;
- blob->user_data = hb_blob_reference (parent);
-
- return blob;
-}
-
-hb_blob_t *
-hb_blob_create_empty (void)
-{
- return &_hb_blob_nil;
-}
-
-hb_blob_t *
-hb_blob_reference (hb_blob_t *blob)
-{
- HB_OBJECT_DO_REFERENCE (blob);
-}
-
-unsigned int
-hb_blob_get_reference_count (hb_blob_t *blob)
-{
- HB_OBJECT_DO_GET_REFERENCE_COUNT (blob);
-}
-
-void
-hb_blob_destroy (hb_blob_t *blob)
-{
- HB_OBJECT_DO_DESTROY (blob);
-
- _hb_blob_destroy_user_data (blob);
-
- free (blob);
-}
-
-unsigned int
-hb_blob_get_length (hb_blob_t *blob)
-{
- return blob->length;
-}
-
-const char *
-hb_blob_lock (hb_blob_t *blob)
-{
- if (HB_OBJECT_IS_INERT (blob))
- return NULL;
-
- hb_mutex_lock (blob->lock);
-
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__,
- blob->lock_count, blob->data));
-
- blob->lock_count++;
-
- hb_mutex_unlock (blob->lock);
-
- return blob->data;
-}
-
-void
-hb_blob_unlock (hb_blob_t *blob)
-{
- if (HB_OBJECT_IS_INERT (blob))
- return;
-
- hb_mutex_lock (blob->lock);
-
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__,
- blob->lock_count, blob->data));
-
- assert (blob->lock_count > 0);
- blob->lock_count--;
-
- hb_mutex_unlock (blob->lock);
-}
-
-hb_bool_t
-hb_blob_is_writable (hb_blob_t *blob)
-{
- hb_memory_mode_t mode;
-
- if (HB_OBJECT_IS_INERT (blob))
- return FALSE;
-
- hb_mutex_lock (blob->lock);
-
- mode = blob->mode;
-
- hb_mutex_unlock (blob->lock);
-
- return mode == HB_MEMORY_MODE_WRITABLE;
-}
-
-
-static hb_bool_t
-_try_make_writable_inplace_unix_locked (hb_blob_t *blob)
-{
-#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
- uintptr_t pagesize = -1, mask, length;
- const char *addr;
-
-#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
- pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE);
-#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
- pagesize = (uintptr_t) sysconf (_SC_PAGESIZE);
-#elif defined(HAVE_GETPAGESIZE)
- pagesize = (uintptr_t) getpagesize ();
-#endif
-
- if ((uintptr_t) -1L == pagesize) {
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: failed to get pagesize: %s\n", blob, __FUNCTION__, strerror (errno)));
- return FALSE;
- }
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: pagesize is %lu\n", blob, __FUNCTION__, (unsigned long) pagesize));
-
- mask = ~(pagesize-1);
- addr = (const char *) (((uintptr_t) blob->data) & mask);
- length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr;
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: calling mprotect on [%p..%p] (%lu bytes)\n",
- blob, __FUNCTION__,
- addr, addr+length, (unsigned long) length));
- if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) {
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: %s\n", blob, __FUNCTION__, strerror (errno)));
- return FALSE;
- }
-
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: successfully made [%p..%p] (%lu bytes) writable\n",
- blob, __FUNCTION__,
- addr, addr+length, (unsigned long) length));
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
-static void
-try_writable_inplace_locked (hb_blob_t *blob)
-{
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: making writable\n", blob, __FUNCTION__));
-
- if (_try_make_writable_inplace_unix_locked (blob)) {
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: making writable -> succeeded\n", blob, __FUNCTION__));
- blob->mode = HB_MEMORY_MODE_WRITABLE;
- } else {
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: making writable -> FAILED\n", blob, __FUNCTION__));
- /* Failed to make writable inplace, mark that */
- blob->mode = HB_MEMORY_MODE_READONLY;
- }
-}
-
-hb_bool_t
-hb_blob_try_writable_inplace (hb_blob_t *blob)
-{
- hb_memory_mode_t mode;
-
- if (HB_OBJECT_IS_INERT (blob))
- return FALSE;
-
- hb_mutex_lock (blob->lock);
-
- if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE)
- try_writable_inplace_locked (blob);
-
- mode = blob->mode;
-
- hb_mutex_unlock (blob->lock);
-
- return mode == HB_MEMORY_MODE_WRITABLE;
-}
-
-hb_bool_t
-hb_blob_try_writable (hb_blob_t *blob)
-{
- hb_memory_mode_t mode;
-
- if (HB_OBJECT_IS_INERT (blob))
- return FALSE;
-
- hb_mutex_lock (blob->lock);
-
- if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE)
- try_writable_inplace_locked (blob);
-
- if (blob->mode == HB_MEMORY_MODE_READONLY)
- {
- char *new_data;
-
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__,
- blob->lock_count, blob->data));
-
- if (blob->lock_count)
- goto done;
-
- new_data = malloc (blob->length);
- if (new_data) {
- (void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: dupped successfully -> %p\n", blob, __FUNCTION__, blob->data));
- memcpy (new_data, blob->data, blob->length);
- _hb_blob_destroy_user_data (blob);
- blob->mode = HB_MEMORY_MODE_WRITABLE;
- blob->data = new_data;
- blob->destroy = free;
- blob->user_data = new_data;
- }
- }
-
-done:
- mode = blob->mode;
-
- hb_mutex_unlock (blob->lock);
-
- return mode == HB_MEMORY_MODE_WRITABLE;
-}
-
-
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-blob.cc b/third_party/harfbuzz-ng/src/hb-blob.cc
new file mode 100644
index 0000000..b2b1d9c
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-blob.cc
@@ -0,0 +1,324 @@
+/*
+ * Copyright © 2009 Red Hat, 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ */
+
+#include "hb-private.hh"
+
+#include "hb-blob.h"
+#include "hb-object-private.hh"
+
+#ifdef HAVE_SYS_MMAN_H
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <sys/mman.h>
+#endif /* HAVE_SYS_MMAN_H */
+
+#include <stdio.h>
+#include <errno.h>
+
+
+
+#ifndef HB_DEBUG_BLOB
+#define HB_DEBUG_BLOB (HB_DEBUG+0)
+#endif
+
+
+struct _hb_blob_t {
+ hb_object_header_t header;
+
+ bool immutable;
+
+ const char *data;
+ unsigned int length;
+ hb_memory_mode_t mode;
+
+ void *user_data;
+ hb_destroy_func_t destroy;
+};
+
+static hb_blob_t _hb_blob_nil = {
+ HB_OBJECT_HEADER_STATIC,
+
+ TRUE, /* immutable */
+
+ NULL, /* data */
+ 0, /* length */
+ HB_MEMORY_MODE_READONLY, /* mode */
+
+ NULL, /* user_data */
+ NULL /* destroy */
+};
+
+
+static bool _try_writable (hb_blob_t *blob);
+
+static void
+_hb_blob_destroy_user_data (hb_blob_t *blob)
+{
+ if (blob->destroy) {
+ blob->destroy (blob->user_data);
+ blob->user_data = NULL;
+ blob->destroy = NULL;
+ }
+}
+
+hb_blob_t *
+hb_blob_create (const char *data,
+ unsigned int length,
+ hb_memory_mode_t mode,
+ void *user_data,
+ hb_destroy_func_t destroy)
+{
+ hb_blob_t *blob;
+
+ if (!length || !(blob = hb_object_create<hb_blob_t> ())) {
+ if (destroy)
+ destroy (user_data);
+ return &_hb_blob_nil;
+ }
+
+ blob->data = data;
+ blob->length = length;
+ blob->mode = mode;
+
+ blob->user_data = user_data;
+ blob->destroy = destroy;
+
+ if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
+ blob->mode = HB_MEMORY_MODE_READONLY;
+ if (!_try_writable (blob)) {
+ hb_blob_destroy (blob);
+ return &_hb_blob_nil;
+ }
+ }
+
+ return blob;
+}
+
+hb_blob_t *
+hb_blob_create_sub_blob (hb_blob_t *parent,
+ unsigned int offset,
+ unsigned int length)
+{
+ hb_blob_t *blob;
+
+ if (!length || offset >= parent->length)
+ return &_hb_blob_nil;
+
+ hb_blob_make_immutable (parent);
+
+ blob = hb_blob_create (parent->data + offset,
+ MIN (length, parent->length - offset),
+ parent->mode,
+ hb_blob_reference (parent),
+ (hb_destroy_func_t) hb_blob_destroy);
+
+ return blob;
+}
+
+hb_blob_t *
+hb_blob_get_empty (void)
+{
+ return &_hb_blob_nil;
+}
+
+hb_blob_t *
+hb_blob_reference (hb_blob_t *blob)
+{
+ return hb_object_reference (blob);
+}
+
+void
+hb_blob_destroy (hb_blob_t *blob)
+{
+ if (!hb_object_destroy (blob)) return;
+
+ _hb_blob_destroy_user_data (blob);
+
+ free (blob);
+}
+
+hb_bool_t
+hb_blob_set_user_data (hb_blob_t *blob,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (blob, key, data, destroy, replace);
+}
+
+void *
+hb_blob_get_user_data (hb_blob_t *blob,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (blob, key);
+}
+
+
+void
+hb_blob_make_immutable (hb_blob_t *blob)
+{
+ if (hb_object_is_inert (blob))
+ return;
+
+ blob->immutable = TRUE;
+}
+
+hb_bool_t
+hb_blob_is_immutable (hb_blob_t *blob)
+{
+ return blob->immutable;
+}
+
+
+unsigned int
+hb_blob_get_length (hb_blob_t *blob)
+{
+ return blob->length;
+}
+
+const char *
+hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
+{
+ if (length)
+ *length = blob->length;
+
+ return blob->data;
+}
+
+char *
+hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
+{
+ if (!_try_writable (blob)) {
+ if (length)
+ *length = 0;
+
+ return NULL;
+ }
+
+ if (length)
+ *length = blob->length;
+
+ return const_cast<char *> (blob->data);
+}
+
+
+static hb_bool_t
+_try_make_writable_inplace_unix (hb_blob_t *blob)
+{
+#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
+ uintptr_t pagesize = -1, mask, length;
+ const char *addr;
+
+#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
+ pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE);
+#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
+ pagesize = (uintptr_t) sysconf (_SC_PAGESIZE);
+#elif defined(HAVE_GETPAGESIZE)
+ pagesize = (uintptr_t) getpagesize ();
+#endif
+
+ if ((uintptr_t) -1L == pagesize) {
+ DEBUG_MSG_FUNC (BLOB, blob, "failed to get pagesize: %s", strerror (errno));
+ return FALSE;
+ }
+ DEBUG_MSG_FUNC (BLOB, blob, "pagesize is %lu", (unsigned long) pagesize);
+
+ mask = ~(pagesize-1);
+ addr = (const char *) (((uintptr_t) blob->data) & mask);
+ length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr;
+ DEBUG_MSG_FUNC (BLOB, blob,
+ "calling mprotect on [%p..%p] (%lu bytes)",
+ addr, addr+length, (unsigned long) length);
+ if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) {
+ DEBUG_MSG_FUNC (BLOB, blob, "mprotect failed: %s", strerror (errno));
+ return FALSE;
+ }
+
+ blob->mode = HB_MEMORY_MODE_WRITABLE;
+
+ DEBUG_MSG_FUNC (BLOB, blob,
+ "successfully made [%p..%p] (%lu bytes) writable\n",
+ addr, addr+length, (unsigned long) length);
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+static bool
+_try_writable_inplace (hb_blob_t *blob)
+{
+ DEBUG_MSG_FUNC (BLOB, blob, "making writable inplace\n");
+
+ if (_try_make_writable_inplace_unix (blob))
+ return TRUE;
+
+ DEBUG_MSG_FUNC (BLOB, blob, "making writable -> FAILED\n");
+
+ /* Failed to make writable inplace, mark that */
+ blob->mode = HB_MEMORY_MODE_READONLY;
+ return FALSE;
+}
+
+static bool
+_try_writable (hb_blob_t *blob)
+{
+ if (blob->immutable)
+ return FALSE;
+
+ if (blob->mode == HB_MEMORY_MODE_WRITABLE)
+ return TRUE;
+
+ if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob))
+ return TRUE;
+
+ if (blob->mode == HB_MEMORY_MODE_WRITABLE)
+ return TRUE;
+
+
+ DEBUG_MSG_FUNC (BLOB, blob, "currect data is -> %p\n", blob->data);
+
+ char *new_data;
+
+ new_data = (char *) malloc (blob->length);
+ if (unlikely (!new_data))
+ return FALSE;
+
+ DEBUG_MSG_FUNC (BLOB, blob, "dupped successfully -> %p\n", blob->data);
+
+ memcpy (new_data, blob->data, blob->length);
+ _hb_blob_destroy_user_data (blob);
+ blob->mode = HB_MEMORY_MODE_WRITABLE;
+ blob->data = new_data;
+ blob->user_data = new_data;
+ blob->destroy = free;
+
+ return TRUE;
+}
+
+
diff --git a/third_party/harfbuzz-ng/src/hb-blob.h b/third_party/harfbuzz-ng/src/hb-blob.h
index dbbfc90..50c9ae3 100644
--- a/third_party/harfbuzz-ng/src/hb-blob.h
+++ b/third_party/harfbuzz-ng/src/hb-blob.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -45,8 +45,8 @@ hb_blob_t *
hb_blob_create (const char *data,
unsigned int length,
hb_memory_mode_t mode,
- hb_destroy_func_t destroy,
- void *user_data);
+ void *user_data,
+ hb_destroy_func_t destroy);
hb_blob_t *
hb_blob_create_sub_blob (hb_blob_t *parent,
@@ -54,34 +54,42 @@ hb_blob_create_sub_blob (hb_blob_t *parent,
unsigned int length);
hb_blob_t *
-hb_blob_create_empty (void);
+hb_blob_get_empty (void);
hb_blob_t *
hb_blob_reference (hb_blob_t *blob);
-unsigned int
-hb_blob_get_reference_count (hb_blob_t *blob);
-
void
hb_blob_destroy (hb_blob_t *blob);
-unsigned int
-hb_blob_get_length (hb_blob_t *blob);
+hb_bool_t
+hb_blob_set_user_data (hb_blob_t *blob,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+
+void *
+hb_blob_get_user_data (hb_blob_t *blob,
+ hb_user_data_key_t *key);
-const char *
-hb_blob_lock (hb_blob_t *blob);
void
-hb_blob_unlock (hb_blob_t *blob);
+hb_blob_make_immutable (hb_blob_t *blob);
hb_bool_t
-hb_blob_is_writable (hb_blob_t *blob);
+hb_blob_is_immutable (hb_blob_t *blob);
-hb_bool_t
-hb_blob_try_writable_inplace (hb_blob_t *blob);
-hb_bool_t
-hb_blob_try_writable (hb_blob_t *blob);
+unsigned int
+hb_blob_get_length (hb_blob_t *blob);
+
+const char *
+hb_blob_get_data (hb_blob_t *blob, unsigned int *length);
+
+char *
+hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length);
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-buffer-private.hh b/third_party/harfbuzz-ng/src/hb-buffer-private.hh
index a129165..4292222 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-buffer-private.hh
@@ -1,8 +1,9 @@
/*
- * Copyright (C) 1998-2004 David Turner and Werner Lemberg
- * Copyright (C) 2004,2007,2009,2010 Red Hat, Inc.
+ * Copyright © 1998-2004 David Turner and Werner Lemberg
+ * Copyright © 2004,2007,2009,2010 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
- * This is part of HarfBuzz, a text shaping library.
+ * 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
@@ -23,16 +24,17 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Owen Taylor, Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
#ifndef HB_BUFFER_PRIVATE_HH
#define HB_BUFFER_PRIVATE_HH
-#include "hb-private.h"
+#include "hb-private.hh"
#include "hb-buffer.h"
-#include "hb-unicode-private.h"
+#include "hb-object-private.hh"
+#include "hb-unicode-private.hh"
-HB_BEGIN_DECLS
ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20);
@@ -45,44 +47,8 @@ typedef struct _hb_segment_properties_t {
} hb_segment_properties_t;
-HB_INTERNAL void
-_hb_buffer_swap (hb_buffer_t *buffer);
-
-HB_INTERNAL void
-_hb_buffer_clear_output (hb_buffer_t *buffer);
-
-HB_INTERNAL void
-_hb_buffer_replace_glyphs_be16 (hb_buffer_t *buffer,
- unsigned int num_in,
- unsigned int num_out,
- const uint16_t *glyph_data_be);
-
-HB_INTERNAL void
-_hb_buffer_replace_glyph (hb_buffer_t *buffer,
- hb_codepoint_t glyph_index);
-
-HB_INTERNAL void
-_hb_buffer_next_glyph (hb_buffer_t *buffer);
-
-
-HB_INTERNAL void
-_hb_buffer_reset_masks (hb_buffer_t *buffer,
- hb_mask_t mask);
-
-HB_INTERNAL void
-_hb_buffer_add_masks (hb_buffer_t *buffer,
- hb_mask_t mask);
-
-HB_INTERNAL void
-_hb_buffer_set_masks (hb_buffer_t *buffer,
- hb_mask_t value,
- hb_mask_t mask,
- unsigned int cluster_start,
- unsigned int cluster_end);
-
-
struct _hb_buffer_t {
- hb_reference_count_t ref_count;
+ hb_object_header_t header;
/* Information about how the text in the buffer should be treated */
@@ -91,56 +57,100 @@ struct _hb_buffer_t {
/* Buffer contents */
- unsigned int allocated; /* Length of allocated arrays */
-
- hb_bool_t have_output; /* Whether we have an output buffer going on */
- hb_bool_t have_positions; /* Whether we have positions */
- hb_bool_t in_error; /* Allocation failed */
+ bool in_error; /* Allocation failed */
+ bool have_output; /* Whether we have an output buffer going on */
+ bool have_positions; /* Whether we have positions */
- unsigned int i; /* Cursor into ->info and ->pos arrays */
+ unsigned int idx; /* Cursor into ->info and ->pos arrays */
unsigned int len; /* Length of ->info and ->pos arrays */
- unsigned int out_len; /* Length of ->out array */
+ unsigned int out_len; /* Length of ->out array if have_output */
+ unsigned int allocated; /* Length of allocated arrays */
hb_glyph_info_t *info;
hb_glyph_info_t *out_info;
hb_glyph_position_t *pos;
- /* Other stuff */
-
unsigned int serial;
+ uint8_t allocated_var_bytes[8];
+ const char *allocated_var_owner[8];
/* Methods */
+
+ HB_INTERNAL void reset (void);
+
+ inline unsigned int backtrack_len (void) const
+ { return have_output? out_len : idx; }
inline unsigned int next_serial (void) { return serial++; }
- inline void swap (void) { _hb_buffer_swap (this); }
- inline void clear_output (void) { _hb_buffer_clear_output (this); }
- inline void next_glyph (void) { _hb_buffer_next_glyph (this); }
- inline void replace_glyphs_be16 (unsigned int num_in,
+
+ 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 deallocate_var_all (void);
+
+ HB_INTERNAL void add (hb_codepoint_t codepoint,
+ hb_mask_t mask,
+ unsigned int cluster);
+
+ HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
+ HB_INTERNAL void reverse (void);
+ HB_INTERNAL void reverse_clusters (void);
+ HB_INTERNAL void guess_properties (void);
+
+ HB_INTERNAL void swap_buffers (void);
+ HB_INTERNAL void clear_output (void);
+ HB_INTERNAL void clear_positions (void);
+ HB_INTERNAL void replace_glyphs_be16 (unsigned int num_in,
+ unsigned int num_out,
+ const uint16_t *glyph_data_be);
+ HB_INTERNAL void replace_glyphs (unsigned int num_in,
unsigned int num_out,
- const uint16_t *glyph_data_be)
- { _hb_buffer_replace_glyphs_be16 (this, num_in, num_out, glyph_data_be); }
- inline void replace_glyph (hb_codepoint_t glyph_index)
- { _hb_buffer_replace_glyph (this, glyph_index); }
+ const uint16_t *glyph_data);
+ HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index);
+ /* Makes a copy of the glyph at idx to output and replace glyph_index */
+ HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index);
+ /* Copies glyph at idx to output but doesn't advance idx */
+ HB_INTERNAL void copy_glyph (void);
+ /* Copies glyph at idx to output and advance idx.
+ * If there's no output, just advance idx. */
+ HB_INTERNAL void next_glyph (void);
+ /* Advance idx without copying to output. */
+ inline void skip_glyph (void) { idx++; }
inline void reset_masks (hb_mask_t mask)
{
- for (unsigned int i = 0; i < len; i++)
- info[i].mask = mask;
+ for (unsigned int j = 0; j < len; j++)
+ info[j].mask = mask;
}
inline void add_masks (hb_mask_t mask)
{
- for (unsigned int i = 0; i < len; i++)
- info[i].mask |= mask;
+ for (unsigned int j = 0; j < len; j++)
+ info[j].mask |= mask;
}
- inline void set_masks (hb_mask_t value,
- hb_mask_t mask,
- unsigned int cluster_start,
- unsigned int cluster_end)
- { _hb_buffer_set_masks (this, value, mask, cluster_start, cluster_end); }
+ HB_INTERNAL void set_masks (hb_mask_t value,
+ hb_mask_t mask,
+ unsigned int cluster_start,
+ unsigned int cluster_end);
+ /* Internal methods */
+ HB_INTERNAL bool enlarge (unsigned int size);
+
+ inline bool ensure (unsigned int size)
+ { return likely (size <= allocated) ? TRUE : enlarge (size); }
+
+ HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
+
+ HB_INTERNAL void *get_scratch_buffer (unsigned int *size);
};
-HB_END_DECLS
+#define HB_BUFFER_XALLOCATE_VAR(b, func, var, owner) \
+ 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)
+
+
#endif /* HB_BUFFER_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.cc b/third_party/harfbuzz-ng/src/hb-buffer.cc
index 03e8e1a..e8bdfb1 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer.cc
+++ b/third_party/harfbuzz-ng/src/hb-buffer.cc
@@ -1,8 +1,9 @@
/*
- * Copyright (C) 1998-2004 David Turner and Werner Lemberg
- * Copyright (C) 2004,2007,2009,2010 Red Hat, Inc.
+ * Copyright © 1998-2004 David Turner and Werner Lemberg
+ * Copyright © 2004,2007,2009,2010 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
- * This is part of HarfBuzz, a text shaping library.
+ * 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
@@ -23,19 +24,33 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Owen Taylor, Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
#include "hb-buffer-private.hh"
#include <string.h>
-HB_BEGIN_DECLS
+
+
+#ifndef HB_DEBUG_BUFFER
+#define HB_DEBUG_BUFFER (HB_DEBUG+0)
+#endif
static hb_buffer_t _hb_buffer_nil = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
+ HB_OBJECT_HEADER_STATIC,
- &_hb_unicode_funcs_nil /* unicode */
+ &_hb_unicode_funcs_default,
+ {
+ HB_DIRECTION_INVALID,
+ HB_SCRIPT_INVALID,
+ NULL,
+ },
+
+ TRUE, /* in_error */
+ TRUE, /* have_output */
+ TRUE /* have_positions */
};
/* Here is how the buffer works internally:
@@ -45,392 +60,630 @@ static hb_buffer_t _hb_buffer_nil = {
*
* As an optimization, both info and out_info may point to the
* same piece of memory, which is owned by info. This remains the
- * case as long as out_len doesn't exceed len at any time.
- * In that case, swap() is no-op and the glyph operations operate
+ * case as long as out_len doesn't exceed i at any time.
+ * In that case, swap_buffers() is no-op and the glyph operations operate
* mostly in-place.
*
* As soon as out_info gets longer than info, out_info is moved over
* to an alternate buffer (which we reuse the pos buffer for!), and its
* current contents (out_len entries) are copied to the new place.
- * This should all remain transparent to the user. swap() then
+ * This should all remain transparent to the user. swap_buffers() then
* switches info and out_info.
*/
-static hb_bool_t
-_hb_buffer_enlarge (hb_buffer_t *buffer, unsigned int size)
+
+/* Internal API */
+
+bool
+hb_buffer_t::enlarge (unsigned int size)
{
- if (unlikely (buffer->in_error))
+ if (unlikely (in_error))
return FALSE;
- unsigned int new_allocated = buffer->allocated;
- hb_glyph_position_t *new_pos;
- hb_glyph_info_t *new_info;
- bool separate_out;
+ unsigned int new_allocated = allocated;
+ hb_glyph_position_t *new_pos = NULL;
+ hb_glyph_info_t *new_info = NULL;
+ bool separate_out = out_info != info;
- separate_out = buffer->out_info != buffer->info;
+ if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
+ goto done;
while (size > new_allocated)
- new_allocated += (new_allocated >> 1) + 8;
+ new_allocated += (new_allocated >> 1) + 32;
+
+ ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0]));
+ if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
+ goto done;
- new_pos = (hb_glyph_position_t *) realloc (buffer->pos, new_allocated * sizeof (buffer->pos[0]));
- new_info = (hb_glyph_info_t *) realloc (buffer->info, new_allocated * sizeof (buffer->info[0]));
+ new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
+ new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
+done:
if (unlikely (!new_pos || !new_info))
- buffer->in_error = TRUE;
+ in_error = TRUE;
if (likely (new_pos))
- buffer->pos = new_pos;
+ pos = new_pos;
if (likely (new_info))
- buffer->info = new_info;
+ info = new_info;
- buffer->out_info = separate_out ? (hb_glyph_info_t *) buffer->pos : buffer->info;
- if (likely (!buffer->in_error))
- buffer->allocated = new_allocated;
+ out_info = separate_out ? (hb_glyph_info_t *) pos : info;
+ if (likely (!in_error))
+ allocated = new_allocated;
- return likely (!buffer->in_error);
+ return likely (!in_error);
}
-static inline hb_bool_t
-_hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
+bool
+hb_buffer_t::make_room_for (unsigned int num_in,
+ unsigned int num_out)
{
- return likely (size <= buffer->allocated) ? TRUE : _hb_buffer_enlarge (buffer, size);
-}
-
-static inline hb_bool_t
-_hb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size)
-{
- if (unlikely (!_hb_buffer_ensure (buffer, size))) return FALSE;
+ if (unlikely (!ensure (out_len + num_out))) return FALSE;
- if (buffer->out_info == buffer->info)
+ if (out_info == info &&
+ out_len + num_out > idx + num_in)
{
- assert (buffer->have_output);
+ assert (have_output);
- buffer->out_info = (hb_glyph_info_t *) buffer->pos;
- memcpy (buffer->out_info, buffer->info, buffer->out_len * sizeof (buffer->out_info[0]));
+ out_info = (hb_glyph_info_t *) pos;
+ memcpy (out_info, info, out_len * sizeof (out_info[0]));
}
return TRUE;
}
+void *
+hb_buffer_t::get_scratch_buffer (unsigned int *size)
+{
+ have_output = FALSE;
+ have_positions = FALSE;
+ out_len = 0;
+ *size = allocated * sizeof (pos[0]);
+ return pos;
+}
-/* Public API */
-hb_buffer_t *
-hb_buffer_create (unsigned int pre_alloc_size)
+/* HarfBuzz-Internal API */
+
+void
+hb_buffer_t::reset (void)
{
- hb_buffer_t *buffer;
+ if (unlikely (hb_object_is_inert (this)))
+ return;
- if (!HB_OBJECT_DO_CREATE (hb_buffer_t, buffer))
- return &_hb_buffer_nil;
+ hb_unicode_funcs_destroy (unicode);
+ unicode = _hb_buffer_nil.unicode;
- if (pre_alloc_size)
- _hb_buffer_ensure (buffer, pre_alloc_size);
+ props = _hb_buffer_nil.props;
- buffer->unicode = &_hb_unicode_funcs_nil;
+ in_error = FALSE;
+ have_output = FALSE;
+ have_positions = FALSE;
- return buffer;
-}
+ idx = 0;
+ len = 0;
+ out_len = 0;
-hb_buffer_t *
-hb_buffer_reference (hb_buffer_t *buffer)
-{
- HB_OBJECT_DO_REFERENCE (buffer);
-}
+ serial = 0;
+ memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
+ memset (allocated_var_owner, 0, sizeof allocated_var_owner);
-unsigned int
-hb_buffer_get_reference_count (hb_buffer_t *buffer)
-{
- HB_OBJECT_DO_GET_REFERENCE_COUNT (buffer);
+ out_info = info;
}
void
-hb_buffer_destroy (hb_buffer_t *buffer)
+hb_buffer_t::add (hb_codepoint_t codepoint,
+ hb_mask_t mask,
+ unsigned int cluster)
{
- HB_OBJECT_DO_DESTROY (buffer);
+ hb_glyph_info_t *glyph;
- hb_unicode_funcs_destroy (buffer->unicode);
+ if (unlikely (!ensure (len + 1))) return;
- free (buffer->info);
- free (buffer->pos);
+ glyph = &info[len];
- free (buffer);
-}
+ memset (glyph, 0, sizeof (*glyph));
+ glyph->codepoint = codepoint;
+ glyph->mask = mask;
+ glyph->cluster = cluster;
+ len++;
+}
void
-hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
- hb_unicode_funcs_t *unicode)
+hb_buffer_t::clear_output (void)
{
- if (!unicode)
- unicode = &_hb_unicode_funcs_nil;
+ if (unlikely (hb_object_is_inert (this)))
+ return;
- hb_unicode_funcs_reference (unicode);
- hb_unicode_funcs_destroy (buffer->unicode);
- buffer->unicode = unicode;
+ have_output = TRUE;
+ have_positions = FALSE;
+
+ out_len = 0;
+ out_info = info;
}
-hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
+void
+hb_buffer_t::clear_positions (void)
{
- return buffer->unicode;
+ if (unlikely (hb_object_is_inert (this)))
+ return;
+
+ have_output = FALSE;
+ have_positions = TRUE;
+
+ memset (pos, 0, sizeof (pos[0]) * len);
}
void
-hb_buffer_set_direction (hb_buffer_t *buffer,
- hb_direction_t direction)
-
+hb_buffer_t::swap_buffers (void)
{
- buffer->props.direction = direction;
+ if (unlikely (in_error)) return;
+
+ assert (have_output);
+
+ if (out_info != info)
+ {
+ hb_glyph_info_t *tmp_string;
+ tmp_string = info;
+ info = out_info;
+ out_info = tmp_string;
+ pos = (hb_glyph_position_t *) out_info;
+ }
+
+ unsigned int tmp;
+ tmp = len;
+ len = out_len;
+ out_len = tmp;
+
+ idx = 0;
}
-hb_direction_t
-hb_buffer_get_direction (hb_buffer_t *buffer)
+void
+hb_buffer_t::replace_glyphs_be16 (unsigned int num_in,
+ unsigned int num_out,
+ const uint16_t *glyph_data_be)
{
- return buffer->props.direction;
+ if (!make_room_for (num_in, num_out)) return;
+
+ hb_glyph_info_t orig_info = info[idx];
+ for (unsigned int i = 1; i < num_in; i++)
+ {
+ hb_glyph_info_t *inf = &info[idx + i];
+ orig_info.cluster = MIN (orig_info.cluster, inf->cluster);
+ }
+
+ hb_glyph_info_t *pinfo = &out_info[out_len];
+ for (unsigned int i = 0; i < num_out; i++)
+ {
+ *pinfo = orig_info;
+ pinfo->codepoint = hb_be_uint16 (glyph_data_be[i]);
+ pinfo++;
+ }
+
+ idx += num_in;
+ out_len += num_out;
}
void
-hb_buffer_set_script (hb_buffer_t *buffer,
- hb_script_t script)
+hb_buffer_t::replace_glyphs (unsigned int num_in,
+ unsigned int num_out,
+ const uint16_t *glyph_data)
{
- buffer->props.script = script;
+ if (!make_room_for (num_in, num_out)) return;
+
+ hb_glyph_info_t orig_info = info[idx];
+ for (unsigned int i = 1; i < num_in; i++)
+ {
+ hb_glyph_info_t *inf = &info[idx + i];
+ orig_info.cluster = MIN (orig_info.cluster, inf->cluster);
+ }
+
+ hb_glyph_info_t *pinfo = &out_info[out_len];
+ for (unsigned int i = 0; i < num_out; i++)
+ {
+ *pinfo = orig_info;
+ pinfo->codepoint = glyph_data[i];
+ pinfo++;
+ }
+
+ idx += num_in;
+ out_len += num_out;
}
-hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer)
+void
+hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
{
- return buffer->props.script;
+ if (!make_room_for (0, 1)) return;
+
+ out_info[out_len] = info[idx];
+ out_info[out_len].codepoint = glyph_index;
+
+ out_len++;
}
void
-hb_buffer_set_language (hb_buffer_t *buffer,
- hb_language_t language)
+hb_buffer_t::copy_glyph (void)
{
- buffer->props.language = language;
+ if (!make_room_for (0, 1)) return;
+
+ out_info[out_len] = info[idx];
+
+ out_len++;
}
-hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer)
+void
+hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
{
- return buffer->props.language;
-}
+ if (!make_room_for (1, 1)) return;
+ out_info[out_len] = info[idx];
+ out_info[out_len].codepoint = glyph_index;
+
+ idx++;
+ out_len++;
+}
void
-hb_buffer_clear (hb_buffer_t *buffer)
+hb_buffer_t::next_glyph (void)
{
- buffer->have_output = FALSE;
- buffer->have_positions = FALSE;
- buffer->in_error = FALSE;
- buffer->len = 0;
- buffer->out_len = 0;
- buffer->i = 0;
- buffer->out_info = buffer->info;
- buffer->serial = 0;
+ if (have_output)
+ {
+ if (out_info != info)
+ {
+ if (unlikely (!ensure (out_len + 1))) return;
+ out_info[out_len] = info[idx];
+ }
+ else if (out_len != idx)
+ out_info[out_len] = info[idx];
+
+ out_len++;
+ }
+
+ idx++;
}
-hb_bool_t
-hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
+void
+hb_buffer_t::set_masks (hb_mask_t value,
+ hb_mask_t mask,
+ unsigned int cluster_start,
+ unsigned int cluster_end)
{
- return _hb_buffer_ensure (buffer, size);
+ hb_mask_t not_mask = ~mask;
+ value &= mask;
+
+ if (!mask)
+ return;
+
+ if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ info[i].mask = (info[i].mask & not_mask) | value;
+ return;
+ }
+
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
+ info[i].mask = (info[i].mask & not_mask) | value;
}
void
-hb_buffer_add_glyph (hb_buffer_t *buffer,
- hb_codepoint_t codepoint,
- hb_mask_t mask,
- unsigned int cluster)
+hb_buffer_t::reverse_range (unsigned int start,
+ unsigned int end)
{
- hb_glyph_info_t *glyph;
+ unsigned int i, j;
- if (unlikely (!_hb_buffer_ensure (buffer, buffer->len + 1))) return;
+ if (start == end - 1)
+ return;
- glyph = &buffer->info[buffer->len];
+ for (i = start, j = end - 1; i < j; i++, j--) {
+ hb_glyph_info_t t;
- memset (glyph, 0, sizeof (*glyph));
- glyph->codepoint = codepoint;
- glyph->mask = mask;
- glyph->cluster = cluster;
+ t = info[i];
+ info[i] = info[j];
+ info[j] = t;
+ }
+
+ if (pos) {
+ for (i = start, j = end - 1; i < j; i++, j--) {
+ hb_glyph_position_t t;
- buffer->len++;
+ t = pos[i];
+ pos[i] = pos[j];
+ pos[j] = t;
+ }
+ }
}
void
-hb_buffer_clear_positions (hb_buffer_t *buffer)
+hb_buffer_t::reverse (void)
{
- _hb_buffer_clear_output (buffer);
- buffer->have_output = FALSE;
- buffer->have_positions = TRUE;
+ if (unlikely (!len))
+ return;
- if (unlikely (!buffer->pos))
- {
- buffer->pos = (hb_glyph_position_t *) calloc (buffer->allocated, sizeof (buffer->pos[0]));
+ reverse_range (0, len);
+}
+
+void
+hb_buffer_t::reverse_clusters (void)
+{
+ unsigned int i, start, count, last_cluster;
+
+ if (unlikely (!len))
return;
+
+ reverse ();
+
+ count = len;
+ start = 0;
+ last_cluster = info[0].cluster;
+ for (i = 1; i < count; i++) {
+ if (last_cluster != info[i].cluster) {
+ reverse_range (start, i);
+ start = i;
+ last_cluster = info[i].cluster;
+ }
+ }
+ reverse_range (start, i);
+}
+
+void
+hb_buffer_t::guess_properties (void)
+{
+ /* If script is set to INVALID, guess from buffer contents */
+ if (props.script == HB_SCRIPT_INVALID) {
+ for (unsigned int i = 0; i < len; i++) {
+ hb_script_t script = hb_unicode_script (unicode, info[i].codepoint);
+ if (likely (script != HB_SCRIPT_COMMON &&
+ script != HB_SCRIPT_INHERITED &&
+ script != HB_SCRIPT_UNKNOWN)) {
+ props.script = script;
+ break;
+ }
+ }
}
- memset (buffer->pos, 0, sizeof (buffer->pos[0]) * buffer->len);
+ /* If direction is set to INVALID, guess from script */
+ if (props.direction == HB_DIRECTION_INVALID) {
+ props.direction = hb_script_get_horizontal_direction (props.script);
+ }
+
+ /* If language is not set, use default language from locale */
+ if (props.language == HB_LANGUAGE_INVALID) {
+ /* TODO get_default_for_script? using $LANGUAGE */
+ props.language = hb_language_get_default ();
+ }
}
-/* HarfBuzz-Internal API */
-void
-_hb_buffer_clear_output (hb_buffer_t *buffer)
+static inline void
+dump_var_allocation (const hb_buffer_t *buffer)
{
- buffer->have_output = TRUE;
- buffer->have_positions = FALSE;
- buffer->out_len = 0;
- buffer->out_info = buffer->info;
+ 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_swap (hb_buffer_t *buffer)
+void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner)
{
- unsigned int tmp;
+ assert (byte_i < 8 && byte_i + count <= 8);
- assert (buffer->have_output);
+ if (DEBUG (BUFFER))
+ dump_var_allocation (this);
+ DEBUG_MSG (BUFFER, this,
+ "Allocating var bytes %d..%d for %s",
+ byte_i, byte_i + count - 1, owner);
- if (unlikely (buffer->in_error)) return;
+ 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;
+ }
+}
- if (buffer->out_info != buffer->info)
- {
- hb_glyph_info_t *tmp_string;
- tmp_string = buffer->info;
- buffer->info = buffer->out_info;
- buffer->out_info = tmp_string;
- buffer->pos = (hb_glyph_position_t *) buffer->out_info;
+void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner)
+{
+ if (DEBUG (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::deallocate_var_all (void)
+{
+ memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes));
+ memset (allocated_var_owner, 0, sizeof (allocated_var_owner));
+}
+
+/* Public API */
- tmp = buffer->len;
- buffer->len = buffer->out_len;
- buffer->out_len = tmp;
+hb_buffer_t *
+hb_buffer_create ()
+{
+ hb_buffer_t *buffer;
- buffer->i = 0;
+ if (!(buffer = hb_object_create<hb_buffer_t> ()))
+ return &_hb_buffer_nil;
+
+ buffer->reset ();
+
+ return buffer;
+}
+
+hb_buffer_t *
+hb_buffer_get_empty (void)
+{
+ return &_hb_buffer_nil;
+}
+
+hb_buffer_t *
+hb_buffer_reference (hb_buffer_t *buffer)
+{
+ return hb_object_reference (buffer);
}
void
-_hb_buffer_replace_glyphs_be16 (hb_buffer_t *buffer,
- unsigned int num_in,
- unsigned int num_out,
- const uint16_t *glyph_data_be)
+hb_buffer_destroy (hb_buffer_t *buffer)
{
- if (buffer->out_info != buffer->info ||
- buffer->out_len + num_out > buffer->i + num_in)
- {
- if (unlikely (!_hb_buffer_ensure_separate (buffer, buffer->out_len + num_out)))
- return;
- }
+ if (!hb_object_destroy (buffer)) return;
- hb_glyph_info_t orig_info = buffer->info[buffer->i];
+ hb_unicode_funcs_destroy (buffer->unicode);
- for (unsigned int i = 0; i < num_out; i++)
- {
- hb_glyph_info_t *info = &buffer->out_info[buffer->out_len + i];
- *info = orig_info;
- info->codepoint = hb_be_uint16 (glyph_data_be[i]);
- }
+ free (buffer->info);
+ free (buffer->pos);
+
+ free (buffer);
+}
- buffer->i += num_in;
- buffer->out_len += num_out;
+hb_bool_t
+hb_buffer_set_user_data (hb_buffer_t *buffer,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (buffer, key, data, destroy, replace);
}
+void *
+hb_buffer_get_user_data (hb_buffer_t *buffer,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (buffer, key);
+}
+
+
void
-_hb_buffer_replace_glyph (hb_buffer_t *buffer,
- hb_codepoint_t glyph_index)
+hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
+ hb_unicode_funcs_t *unicode)
{
- hb_glyph_info_t *info;
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
- if (buffer->out_info != buffer->info)
- {
- if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return;
- buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
- }
- else if (buffer->out_len != buffer->i)
- buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
+ if (!unicode)
+ unicode = _hb_buffer_nil.unicode;
- info = &buffer->out_info[buffer->out_len];
- info->codepoint = glyph_index;
+ hb_unicode_funcs_reference (unicode);
+ hb_unicode_funcs_destroy (buffer->unicode);
+ buffer->unicode = unicode;
+}
- buffer->i++;
- buffer->out_len++;
+hb_unicode_funcs_t *
+hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
+{
+ return buffer->unicode;
}
void
-_hb_buffer_next_glyph (hb_buffer_t *buffer)
+hb_buffer_set_direction (hb_buffer_t *buffer,
+ hb_direction_t direction)
+
{
- if (buffer->have_output)
- {
- if (buffer->out_info != buffer->info)
- {
- if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return;
- buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
- }
- else if (buffer->out_len != buffer->i)
- buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
- buffer->out_len++;
- }
+ buffer->props.direction = direction;
+}
- buffer->i++;
+hb_direction_t
+hb_buffer_get_direction (hb_buffer_t *buffer)
+{
+ return buffer->props.direction;
}
void
-_hb_buffer_reset_masks (hb_buffer_t *buffer,
- hb_mask_t mask)
+hb_buffer_set_script (hb_buffer_t *buffer,
+ hb_script_t script)
{
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- buffer->info[i].mask = mask;
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
+ buffer->props.script = script;
+}
+
+hb_script_t
+hb_buffer_get_script (hb_buffer_t *buffer)
+{
+ return buffer->props.script;
}
void
-_hb_buffer_add_masks (hb_buffer_t *buffer,
- hb_mask_t mask)
+hb_buffer_set_language (hb_buffer_t *buffer,
+ hb_language_t language)
{
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- buffer->info[i].mask |= mask;
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
+ buffer->props.language = language;
+}
+
+hb_language_t
+hb_buffer_get_language (hb_buffer_t *buffer)
+{
+ return buffer->props.language;
}
+
void
-_hb_buffer_set_masks (hb_buffer_t *buffer,
- hb_mask_t value,
- hb_mask_t mask,
- unsigned int cluster_start,
- unsigned int cluster_end)
+hb_buffer_reset (hb_buffer_t *buffer)
{
- hb_mask_t not_mask = ~mask;
- value &= mask;
+ buffer->reset ();
+}
- if (!mask)
- return;
+hb_bool_t
+hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
+{
+ return buffer->ensure (size);
+}
- if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
- return;
- }
+hb_bool_t
+hb_buffer_allocation_successful (hb_buffer_t *buffer)
+{
+ return !buffer->in_error;
+}
- /* XXX can't bsearch since .cluster may not be sorted. */
- /* Binary search to find the start position and go from there. */
- unsigned int min = 0, max = buffer->len;
- while (min < max)
- {
- unsigned int mid = min + ((max - min) / 2);
- if (buffer->info[mid].cluster < cluster_start)
- min = mid + 1;
- else
- max = mid;
- }
- unsigned int count = buffer->len;
- for (unsigned int i = min; i < count && buffer->info[i].cluster < cluster_end; i++)
- buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
+void
+hb_buffer_add (hb_buffer_t *buffer,
+ hb_codepoint_t codepoint,
+ hb_mask_t mask,
+ unsigned int cluster)
+{
+ buffer->add (codepoint, mask, cluster);
}
+hb_bool_t
+hb_buffer_set_length (hb_buffer_t *buffer,
+ unsigned int length)
+{
+ if (!buffer->ensure (length))
+ return FALSE;
+
+ /* Wipe the new space */
+ if (length > buffer->len) {
+ memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
+ if (buffer->have_positions)
+ memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
+ }
-/* Public API again */
+ buffer->len = length;
+ return TRUE;
+}
unsigned int
hb_buffer_get_length (hb_buffer_t *buffer)
@@ -440,90 +693,67 @@ hb_buffer_get_length (hb_buffer_t *buffer)
/* Return value valid as long as buffer not modified */
hb_glyph_info_t *
-hb_buffer_get_glyph_infos (hb_buffer_t *buffer)
+hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
+ unsigned int *length)
{
+ if (length)
+ *length = buffer->len;
+
return (hb_glyph_info_t *) buffer->info;
}
/* Return value valid as long as buffer not modified */
hb_glyph_position_t *
-hb_buffer_get_glyph_positions (hb_buffer_t *buffer)
+hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
+ unsigned int *length)
{
if (!buffer->have_positions)
- hb_buffer_clear_positions (buffer);
-
- return (hb_glyph_position_t *) buffer->pos;
-}
-
-
-static void
-reverse_range (hb_buffer_t *buffer,
- unsigned int start,
- unsigned int end)
-{
- unsigned int i, j;
-
- for (i = start, j = end - 1; i < j; i++, j--) {
- hb_glyph_info_t t;
-
- t = buffer->info[i];
- buffer->info[i] = buffer->info[j];
- buffer->info[j] = t;
- }
+ buffer->clear_positions ();
- if (buffer->pos) {
- for (i = 0, j = end - 1; i < j; i++, j--) {
- hb_glyph_position_t t;
+ if (length)
+ *length = buffer->len;
- t = buffer->pos[i];
- buffer->pos[i] = buffer->pos[j];
- buffer->pos[j] = t;
- }
- }
+ return (hb_glyph_position_t *) buffer->pos;
}
void
hb_buffer_reverse (hb_buffer_t *buffer)
{
- if (unlikely (!buffer->len))
- return;
-
- reverse_range (buffer, 0, buffer->len);
+ buffer->reverse ();
}
void
hb_buffer_reverse_clusters (hb_buffer_t *buffer)
{
- unsigned int i, start, count, last_cluster;
-
- if (unlikely (!buffer->len))
- return;
-
- hb_buffer_reverse (buffer);
-
- count = buffer->len;
- start = 0;
- last_cluster = buffer->info[0].cluster;
- for (i = 1; i < count; i++) {
- if (last_cluster != buffer->info[i].cluster) {
- reverse_range (buffer, start, i);
- start = i;
- last_cluster = buffer->info[i].cluster;
- }
- }
- reverse_range (buffer, start, i);
+ buffer->reverse_clusters ();
}
+void
+hb_buffer_guess_properties (hb_buffer_t *buffer)
+{
+ buffer->guess_properties ();
+}
#define ADD_UTF(T) \
HB_STMT_START { \
+ if (text_length == -1) { \
+ text_length = 0; \
+ const T *p = (const T *) text; \
+ while (*p) { \
+ text_length++; \
+ p++; \
+ } \
+ } \
+ if (item_length == -1) \
+ item_length = text_length - item_offset; \
+ buffer->ensure (buffer->len + item_length * sizeof (T) / 4); \
const T *next = (const T *) text + item_offset; \
const T *end = next + item_length; \
while (next < end) { \
hb_codepoint_t u; \
const T *old_next = next; \
next = UTF_NEXT (next, end, u); \
- hb_buffer_add_glyph (buffer, u, 1, old_next - (const T *) text); \
+ hb_buffer_add (buffer, u, 1, old_next - (const T *) text); \
} \
} HB_STMT_END
@@ -543,7 +773,7 @@ hb_utf8_next (const uint8_t *text,
uint8_t c = *text;
unsigned int mask, len;
- /* TODO check for overlong sequences? also: optimize? */
+ /* TODO check for overlong sequences? */
UTF8_COMPUTE (c, mask, len);
if (unlikely (!len || (unsigned int) (end - text) < len)) {
@@ -571,9 +801,9 @@ hb_utf8_next (const uint8_t *text,
void
hb_buffer_add_utf8 (hb_buffer_t *buffer,
const char *text,
- unsigned int text_length HB_UNUSED,
+ int text_length,
unsigned int item_offset,
- unsigned int item_length)
+ int item_length)
{
#define UTF_NEXT(S, E, U) hb_utf8_next (S, E, &(U))
ADD_UTF (uint8_t);
@@ -590,7 +820,7 @@ hb_utf16_next (const uint16_t *text,
if (unlikely (c >= 0xd800 && c < 0xdc00)) {
/* high surrogate */
uint16_t l;
- if (text < end && ((l = *text), unlikely (l >= 0xdc00 && l < 0xe000))) {
+ if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) {
/* low surrogate */
*unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
text++;
@@ -605,9 +835,9 @@ hb_utf16_next (const uint16_t *text,
void
hb_buffer_add_utf16 (hb_buffer_t *buffer,
const uint16_t *text,
- unsigned int text_length HB_UNUSED,
+ int text_length,
unsigned int item_offset,
- unsigned int item_length)
+ int item_length)
{
#define UTF_NEXT(S, E, U) hb_utf16_next (S, E, &(U))
ADD_UTF (uint16_t);
@@ -617,9 +847,9 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer,
void
hb_buffer_add_utf32 (hb_buffer_t *buffer,
const uint32_t *text,
- unsigned int text_length HB_UNUSED,
+ int text_length,
unsigned int item_offset,
- unsigned int item_length)
+ int item_length)
{
#define UTF_NEXT(S, E, U) ((U) = *(S), (S)+1)
ADD_UTF (uint32_t);
@@ -627,4 +857,3 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
}
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.h b/third_party/harfbuzz-ng/src/hb-buffer.h
index 0185415..9582ebe 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer.h
+++ b/third_party/harfbuzz-ng/src/hb-buffer.h
@@ -1,8 +1,9 @@
/*
- * Copyright (C) 1998-2004 David Turner and Werner Lemberg
- * Copyright (C) 2004,2007,2009 Red Hat, Inc.
+ * Copyright © 1998-2004 David Turner and Werner Lemberg
+ * Copyright © 2004,2007,2009 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
- * This is part of HarfBuzz, a text shaping library.
+ * 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
@@ -23,6 +24,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Owen Taylor, Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
#ifndef HB_BUFFER_H
@@ -30,7 +32,6 @@
#include "hb-common.h"
#include "hb-unicode.h"
-#include "hb-language.h"
HB_BEGIN_DECLS
@@ -41,6 +42,8 @@ typedef struct _hb_glyph_info_t {
hb_codepoint_t codepoint;
hb_mask_t mask;
uint32_t cluster;
+
+ /*< private >*/
hb_var_int_t var1;
hb_var_int_t var2;
} hb_glyph_info_t;
@@ -50,22 +53,35 @@ typedef struct _hb_glyph_position_t {
hb_position_t y_advance;
hb_position_t x_offset;
hb_position_t y_offset;
+
+ /*< private >*/
hb_var_int_t var;
} hb_glyph_position_t;
hb_buffer_t *
-hb_buffer_create (unsigned int pre_alloc_size);
+hb_buffer_create (void);
hb_buffer_t *
-hb_buffer_reference (hb_buffer_t *buffer);
+hb_buffer_get_empty (void);
-unsigned int
-hb_buffer_get_reference_count (hb_buffer_t *buffer);
+hb_buffer_t *
+hb_buffer_reference (hb_buffer_t *buffer);
void
hb_buffer_destroy (hb_buffer_t *buffer);
+hb_bool_t
+hb_buffer_set_user_data (hb_buffer_t *buffer,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+void *
+hb_buffer_get_user_data (hb_buffer_t *buffer,
+ hb_user_data_key_t *key);
+
void
hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
@@ -96,15 +112,20 @@ hb_language_t
hb_buffer_get_language (hb_buffer_t *buffer);
+/* Resets the buffer. Afterwards it's as if it was just created,
+ * except that it has a larger buffer allocated perhaps... */
void
-hb_buffer_clear (hb_buffer_t *buffer);
+hb_buffer_reset (hb_buffer_t *buffer);
+
+/* Returns FALSE if allocation failed */
+hb_bool_t
+hb_buffer_pre_allocate (hb_buffer_t *buffer,
+ unsigned int size);
-void
-hb_buffer_clear_positions (hb_buffer_t *buffer);
+/* Returns FALSE if allocation has failed before */
hb_bool_t
-hb_buffer_ensure (hb_buffer_t *buffer,
- unsigned int size);
+hb_buffer_allocation_successful (hb_buffer_t *buffer);
void
hb_buffer_reverse (hb_buffer_t *buffer);
@@ -112,50 +133,60 @@ hb_buffer_reverse (hb_buffer_t *buffer);
void
hb_buffer_reverse_clusters (hb_buffer_t *buffer);
+void
+hb_buffer_guess_properties (hb_buffer_t *buffer);
+
/* Filling the buffer in */
void
-hb_buffer_add_glyph (hb_buffer_t *buffer,
- hb_codepoint_t codepoint,
- hb_mask_t mask,
- unsigned int cluster);
+hb_buffer_add (hb_buffer_t *buffer,
+ hb_codepoint_t codepoint,
+ hb_mask_t mask,
+ unsigned int cluster);
void
hb_buffer_add_utf8 (hb_buffer_t *buffer,
const char *text,
- unsigned int text_length,
+ int text_length,
unsigned int item_offset,
- unsigned int item_length);
+ int item_length);
void
hb_buffer_add_utf16 (hb_buffer_t *buffer,
const uint16_t *text,
- unsigned int text_length,
+ int text_length,
unsigned int item_offset,
- unsigned int item_length);
+ int item_length);
void
hb_buffer_add_utf32 (hb_buffer_t *buffer,
const uint32_t *text,
- unsigned int text_length,
+ int text_length,
unsigned int item_offset,
- unsigned int item_length);
+ int item_length);
-/* Getting glyphs out of the buffer */
+/* Clears any new items added at the end */
+hb_bool_t
+hb_buffer_set_length (hb_buffer_t *buffer,
+ unsigned int length);
/* Return value valid as long as buffer not modified */
unsigned int
hb_buffer_get_length (hb_buffer_t *buffer);
+/* Getting glyphs out of the buffer */
+
/* Return value valid as long as buffer not modified */
hb_glyph_info_t *
-hb_buffer_get_glyph_infos (hb_buffer_t *buffer);
+hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
+ unsigned int *length);
/* Return value valid as long as buffer not modified */
hb_glyph_position_t *
-hb_buffer_get_glyph_positions (hb_buffer_t *buffer);
+hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
+ unsigned int *length);
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-common.cc b/third_party/harfbuzz-ng/src/hb-common.cc
new file mode 100644
index 0000000..6093289
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-common.cc
@@ -0,0 +1,372 @@
+/*
+ * Copyright © 2009,2010 Red Hat, Inc.
+ * Copyright © 2011 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-private.hh"
+
+#include "hb-version.h"
+
+#include "hb-mutex-private.hh"
+#include "hb-object-private.hh"
+
+#include <locale.h>
+
+
+
+/* hb_tag_t */
+
+hb_tag_t
+hb_tag_from_string (const char *s, int len)
+{
+ char tag[4];
+ unsigned int i;
+
+ if (!s || !len || !*s)
+ return HB_TAG_NONE;
+
+ if (len < 0 || len > 4)
+ len = 4;
+ for (i = 0; i < (unsigned) len && s[i]; i++)
+ tag[i] = s[i];
+ for (; i < 4; i++)
+ tag[i] = ' ';
+
+ return HB_TAG_CHAR4 (tag);
+}
+
+
+/* hb_direction_t */
+
+const char direction_strings[][4] = {
+ "ltr",
+ "rtl",
+ "ttb",
+ "btt"
+};
+
+hb_direction_t
+hb_direction_from_string (const char *str, int len)
+{
+ if (unlikely (!str || !len || !*str))
+ return HB_DIRECTION_INVALID;
+
+ /* Lets match loosely: just match the first letter, such that
+ * all of "ltr", "left-to-right", etc work!
+ */
+ char c = TOLOWER (str[0]);
+ for (unsigned int i = 0; i < ARRAY_LENGTH (direction_strings); i++)
+ if (c == direction_strings[i][0])
+ return (hb_direction_t) i;
+
+ return HB_DIRECTION_INVALID;
+}
+
+const char *
+hb_direction_to_string (hb_direction_t direction)
+{
+ if (likely ((unsigned int) direction < ARRAY_LENGTH (direction_strings)))
+ return direction_strings[direction];
+
+ return "invalid";
+}
+
+
+/* hb_language_t */
+
+struct _hb_language_t {
+ const char s[1];
+};
+
+static const char canon_map[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0,
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
+ '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-',
+ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
+};
+
+static hb_bool_t
+lang_equal (const void *v1,
+ const void *v2)
+{
+ const unsigned char *p1 = (const unsigned char *) v1;
+ const unsigned char *p2 = (const unsigned char *) v2;
+
+ while (canon_map[*p1] && canon_map[*p1] == canon_map[*p2])
+ {
+ p1++, p2++;
+ }
+
+ return (canon_map[*p1] == canon_map[*p2]);
+}
+
+#if 0
+static unsigned int
+lang_hash (const void *key)
+{
+ const unsigned char *p = key;
+ unsigned int h = 0;
+ while (canon_map[*p])
+ {
+ h = (h << 5) - h + canon_map[*p];
+ p++;
+ }
+
+ return h;
+}
+#endif
+
+
+struct hb_language_item_t {
+
+ hb_language_t lang;
+
+ inline bool operator == (const char *s) const {
+ return lang_equal (lang, s);
+ }
+
+ inline hb_language_item_t & operator = (const char *s) {
+ lang = (hb_language_t) strdup (s);
+ for (unsigned char *p = (unsigned char *) lang; *p; p++)
+ *p = canon_map[*p];
+
+ return *this;
+ }
+
+ void finish (void) { free (lang); }
+};
+
+static struct hb_static_lang_set_t : hb_lockable_set_t<hb_language_item_t, hb_static_mutex_t> {
+ ~hb_static_lang_set_t (void) { this->finish (lock); }
+ hb_static_mutex_t lock;
+} langs;
+
+hb_language_t
+hb_language_from_string (const char *str, int len)
+{
+ if (!str || !len || !*str)
+ return HB_LANGUAGE_INVALID;
+
+ char strbuf[32];
+ if (len >= 0) {
+ len = MIN (len, (int) sizeof (strbuf) - 1);
+ str = (char *) memcpy (strbuf, str, len);
+ strbuf[len] = '\0';
+ }
+
+ hb_language_item_t *item = langs.find_or_insert (str, langs.lock);
+
+ return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
+}
+
+const char *
+hb_language_to_string (hb_language_t language)
+{
+ /* This is actually NULL-safe! */
+ return language->s;
+}
+
+hb_language_t
+hb_language_get_default (void)
+{
+ static hb_language_t default_language;
+
+ if (!default_language) {
+ /* This block is not quite threadsafe, but is not as bad as
+ * it looks since it's idempotent. As long as pointer ops
+ * are atomic, we are safe. */
+
+ /* I hear that setlocale() doesn't honor env vars on Windows,
+ * but for now we ignore that. */
+
+ default_language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
+ }
+
+ return default_language;
+}
+
+
+/* hb_script_t */
+
+hb_script_t
+hb_script_from_iso15924_tag (hb_tag_t tag)
+{
+ if (unlikely (tag == HB_TAG_NONE))
+ return HB_SCRIPT_INVALID;
+
+ /* Be lenient, adjust case (one capital letter followed by three small letters) */
+ tag = (tag & 0xDFDFDFDF) | 0x00202020;
+
+ switch (tag) {
+
+ /* These graduated from the 'Q' private-area codes, but
+ * the old code is still aliased by Unicode, and the Qaai
+ * one in use by ICU. */
+ case HB_TAG('Q','a','a','i'): return HB_SCRIPT_INHERITED;
+ case HB_TAG('Q','a','a','c'): return HB_SCRIPT_COPTIC;
+
+ /* Script variants from http://unicode.org/iso15924/ */
+ case HB_TAG('C','y','r','s'): return HB_SCRIPT_CYRILLIC;
+ case HB_TAG('L','a','t','f'): return HB_SCRIPT_LATIN;
+ case HB_TAG('L','a','t','g'): return HB_SCRIPT_LATIN;
+ case HB_TAG('S','y','r','e'): return HB_SCRIPT_SYRIAC;
+ case HB_TAG('S','y','r','j'): return HB_SCRIPT_SYRIAC;
+ case HB_TAG('S','y','r','n'): return HB_SCRIPT_SYRIAC;
+ }
+
+ /* If it looks right, just use the tag as a script */
+ if (((uint32_t) tag & 0xE0E0E0E0) == 0x40606060)
+ return (hb_script_t) tag;
+
+ /* Otherwise, return unknown */
+ return HB_SCRIPT_UNKNOWN;
+}
+
+hb_script_t
+hb_script_from_string (const char *s, int len)
+{
+ return hb_script_from_iso15924_tag (hb_tag_from_string (s, len));
+}
+
+hb_tag_t
+hb_script_to_iso15924_tag (hb_script_t script)
+{
+ return (hb_tag_t) script;
+}
+
+hb_direction_t
+hb_script_get_horizontal_direction (hb_script_t script)
+{
+ switch ((hb_tag_t) script)
+ {
+ case HB_SCRIPT_ARABIC:
+ case HB_SCRIPT_HEBREW:
+ case HB_SCRIPT_SYRIAC:
+ case HB_SCRIPT_THAANA:
+
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_CYPRIOT:
+
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHOENICIAN:
+ case HB_SCRIPT_NKO:
+
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_AVESTAN:
+ case HB_SCRIPT_IMPERIAL_ARAMAIC:
+ case HB_SCRIPT_INSCRIPTIONAL_PAHLAVI:
+ case HB_SCRIPT_INSCRIPTIONAL_PARTHIAN:
+ case HB_SCRIPT_OLD_SOUTH_ARABIAN:
+ case HB_SCRIPT_OLD_TURKIC:
+ case HB_SCRIPT_SAMARITAN:
+
+ /* Unicode-6.0 additions */
+ case HB_SCRIPT_MANDAIC:
+
+ return HB_DIRECTION_RTL;
+ }
+
+ return HB_DIRECTION_LTR;
+}
+
+
+/* hb_user_data_array_t */
+
+
+/* NOTE: Currently we use a global lock for user_data access
+ * threadsafety. If one day we add a mutex to any object, we
+ * should switch to using that insted for these too.
+ */
+
+static hb_static_mutex_t user_data_lock;
+
+bool
+hb_user_data_array_t::set (hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ if (!key)
+ return false;
+
+ if (replace) {
+ if (!data && !destroy) {
+ items.remove (key, user_data_lock);
+ return true;
+ }
+ }
+ hb_user_data_item_t item = {key, data, destroy};
+ bool ret = !!items.replace_or_insert (item, user_data_lock, replace);
+
+ return ret;
+}
+
+void *
+hb_user_data_array_t::get (hb_user_data_key_t *key)
+{
+ hb_user_data_item_t item = {NULL };
+
+ return items.find (key, &item, user_data_lock) ? item.data : NULL;
+}
+
+void
+hb_user_data_array_t::finish (void)
+{
+ items.finish (user_data_lock);
+}
+
+
+/* hb_version */
+
+void
+hb_version (unsigned int *major,
+ unsigned int *minor,
+ unsigned int *micro)
+{
+ *major = HB_VERSION_MAJOR;
+ *minor = HB_VERSION_MINOR;
+ *micro = HB_VERSION_MICRO;
+}
+
+const char *
+hb_version_string (void)
+{
+ return HB_VERSION_STRING;
+}
+
+hb_bool_t
+hb_version_check (unsigned int major,
+ unsigned int minor,
+ unsigned int micro)
+{
+ return HB_VERSION_CHECK (major, minor, micro);
+}
+
+
diff --git a/third_party/harfbuzz-ng/src/hb-common.h b/third_party/harfbuzz-ng/src/hb-common.h
index 1dd02cb..b7fef32 100644
--- a/third_party/harfbuzz-ng/src/hb-common.h
+++ b/third_party/harfbuzz-ng/src/hb-common.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -22,6 +23,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
#ifndef HB_COMMON_H
@@ -37,53 +39,77 @@
HB_BEGIN_DECLS
+#if !defined (HB_DONT_DEFINE_STDINT)
-#ifdef _MSC_VER
-#define _HB__STR2__(x) #x
-#define _HB__STR1__(x) _HB__STR2__(x)
-#define _HB__LOC__ __FILE__ "("_HB__STR1__(__LINE__)") : Warning Msg: "
-#pragma message(_HB__LOC__"Not using stdint.h; integer types may have wrong size")
-typedef signed char int8_t;
-typedef unsigned char uint8_t;
-typedef signed short int16_t;
-typedef unsigned short uint16_t;
-typedef signed int int32_t;
-typedef unsigned int uint32_t;
-typedef signed long long int64_t;
-typedef unsigned long long uint64_t;
-#ifndef __cplusplus
-#define inline __inline
-#endif
+#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
+ defined (_sgi) || defined (__sun) || defined (sun) || \
+ defined (__digital__) || defined (__HP_cc)
+# include <inttypes.h>
+#elif defined (_AIX)
+# include <sys/inttypes.h>
+/* VS 2010 (_MSC_VER 1600) has stdint.h */
+#elif defined (_MSC_VER) && _MSC_VER < 1600
+typedef __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
#else
-#include <stdint.h>
+# include <stdint.h>
#endif
-typedef int hb_bool_t;
-
-typedef uint32_t hb_tag_t;
-#define HB_TAG(a,b,c,d) ((hb_tag_t)(((uint8_t)a<<24)|((uint8_t)b<<16)|((uint8_t)c<<8)|(uint8_t)d))
-#define HB_TAG_STR(s) (HB_TAG(((const char *) s)[0], \
- ((const char *) s)[1], \
- ((const char *) s)[2], \
- ((const char *) s)[3]))
-#define HB_TAG_NONE HB_TAG(0,0,0,0)
+#endif
-hb_tag_t hb_tag_from_string (const char *s);
+typedef int hb_bool_t;
typedef uint32_t hb_codepoint_t;
typedef int32_t hb_position_t;
typedef uint32_t hb_mask_t;
-typedef void (*hb_destroy_func_t) (void *user_data);
+typedef union _hb_var_int_t {
+ uint32_t u32;
+ int32_t i32;
+ uint16_t u16[2];
+ int16_t i16[2];
+ uint8_t u8[4];
+ int8_t i8[4];
+} hb_var_int_t;
+
-typedef enum _hb_direction_t {
- HB_DIRECTION_LTR,
+/* hb_tag_t */
+
+typedef uint32_t hb_tag_t;
+
+#define HB_TAG(a,b,c,d) ((hb_tag_t)((((uint8_t)(a))<<24)|(((uint8_t)(b))<<16)|(((uint8_t)(c))<<8)|((uint8_t)(d))))
+#define HB_UNTAG(tag) ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag))
+
+#define HB_TAG_NONE HB_TAG(0,0,0,0)
+
+/* len=-1 means s is NUL-terminated */
+hb_tag_t hb_tag_from_string (const char *s, int len);
+
+
+/* hb_direction_t */
+
+typedef enum {
+ HB_DIRECTION_INVALID = -1,
+ HB_DIRECTION_LTR = 0,
HB_DIRECTION_RTL,
HB_DIRECTION_TTB,
HB_DIRECTION_BTT
} hb_direction_t;
+/* len=-1 means s is NUL-terminated */
+hb_direction_t
+hb_direction_from_string (const char *str, int len);
+
+const char *
+hb_direction_to_string (hb_direction_t direction);
+
#define HB_DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 0)
#define HB_DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 2)
#define HB_DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 0)
@@ -91,14 +117,204 @@ typedef enum _hb_direction_t {
#define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1))
-typedef union _hb_var_int_t {
- uint32_t u32;
- int32_t i32;
- uint16_t u16[2];
- int16_t i16[2];
- uint8_t u8[4];
- int8_t i8[4];
-} hb_var_int_t;
+/* hb_language_t */
+
+typedef struct _hb_language_t *hb_language_t;
+
+/* len=-1 means s is NUL-terminated */
+hb_language_t
+hb_language_from_string (const char *str, int len);
+
+const char *
+hb_language_to_string (hb_language_t language);
+
+#define HB_LANGUAGE_INVALID ((hb_language_t) NULL)
+
+hb_language_t
+hb_language_get_default (void);
+
+
+/* hb_unicode_general_category_t */
+
+typedef enum
+{
+ HB_UNICODE_GENERAL_CATEGORY_CONTROL, /* Cc */
+ HB_UNICODE_GENERAL_CATEGORY_FORMAT, /* Cf */
+ HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED, /* Cn */
+ HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE, /* Co */
+ HB_UNICODE_GENERAL_CATEGORY_SURROGATE, /* Cs */
+ HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER, /* Ll */
+ HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER, /* Lm */
+ HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER, /* Lo */
+ HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER, /* Lt */
+ HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER, /* Lu */
+ HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK, /* Mc */
+ HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK, /* Me */
+ HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK, /* Mn */
+ HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER, /* Nd */
+ HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER, /* Nl */
+ HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER, /* No */
+ HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION, /* Pc */
+ HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION, /* Pd */
+ HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION, /* Pe */
+ HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION, /* Pf */
+ HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION, /* Pi */
+ HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION, /* Po */
+ HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION, /* Ps */
+ HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL, /* Sc */
+ HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL, /* Sk */
+ HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL, /* Sm */
+ HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL, /* So */
+ HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR, /* Zl */
+ HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR, /* Zp */
+ HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR /* Zs */
+} hb_unicode_general_category_t;
+
+
+/* hb_script_t */
+
+/* http://unicode.org/iso15924/ */
+typedef enum
+{
+ HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'),
+ HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'),
+ HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'),
+ HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'),
+ HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'),
+ HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'),
+ HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'),
+ HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'),
+ HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'),
+ HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'),
+ HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'),
+ HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'),
+ HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'),
+ HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'),
+ HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'),
+ HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'),
+ HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'),
+ HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'),
+ HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'),
+ HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'),
+ HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'),
+ HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'),
+ HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'),
+ HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'),
+ HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'),
+ HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'),
+ HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'),
+ HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'),
+ HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'),
+ HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'),
+ HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'),
+ HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'),
+ HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'),
+ HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'),
+ HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'),
+ HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'),
+ HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'),
+ HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'),
+ HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'),
+ HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'),
+ HB_SCRIPT_CANADIAN_ABORIGINAL = HB_TAG ('C','a','n','s'),
+ HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'),
+ HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'),
+ HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'),
+ HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'),
+ HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'),
+
+ /* Unicode-4.0 additions */
+ HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'),
+ HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'),
+ HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'),
+ HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'),
+ HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'),
+ HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'),
+ HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'),
+ HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'),
+
+ /* Unicode-4.1 additions */
+ HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'),
+ HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'),
+ HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'),
+ HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'),
+ HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'),
+ HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'),
+ HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'),
+
+ /* Unicode-5.0 additions */
+ HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'),
+ HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'),
+ HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'),
+ HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'),
+ HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'),
+ HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'),
+
+ /* Unicode-5.1 additions */
+ HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'),
+ HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'),
+ HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'),
+ HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'),
+ HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'),
+ HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'),
+ HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'),
+ HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'),
+ HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'),
+ HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'),
+ HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'),
+
+ /* Unicode-5.2 additions */
+ HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'),
+ HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'),
+ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'),
+ HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'),
+ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'),
+ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'),
+ HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'),
+ HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'),
+ HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'),
+ HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'),
+ HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'),
+ HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'),
+ HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'),
+ HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'),
+ HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'),
+
+ /* Unicode-6.0 additions */
+ HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'),
+ HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'),
+ HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'),
+
+ /* No script set */
+ HB_SCRIPT_INVALID = HB_TAG_NONE
+} hb_script_t;
+
+
+/* Script functions */
+
+hb_script_t
+hb_script_from_iso15924_tag (hb_tag_t tag);
+
+/* suger for tag_from_string() then script_from_iso15924_tag */
+/* len=-1 means s is NUL-terminated */
+hb_script_t
+hb_script_from_string (const char *s, int len);
+
+hb_tag_t
+hb_script_to_iso15924_tag (hb_script_t script);
+
+hb_direction_t
+hb_script_get_horizontal_direction (hb_script_t script);
+
+
+/* User data */
+
+typedef struct _hb_user_data_key_t {
+ /*< private >*/
+ char unused;
+} hb_user_data_key_t;
+
+typedef void (*hb_destroy_func_t) (void *user_data);
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-language.h b/third_party/harfbuzz-ng/src/hb-fallback-shape-private.hh
index d3c91fb..d0beb16 100644
--- a/third_party/harfbuzz-ng/src/hb-language.h
+++ b/third_party/harfbuzz-ng/src/hb-fallback-shape-private.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -21,26 +21,28 @@
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
- * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_LANGUAGE_H
-#define HB_LANGUAGE_H
+#ifndef HB_FALLBACK_SHAPE_PRIVATE_HH
+#define HB_FALLBACK_SHAPE_PRIVATE_HH
-#include "hb-common.h"
+#include "hb-private.hh"
-HB_BEGIN_DECLS
+#include "hb-shape.h"
-typedef const void *hb_language_t;
+HB_BEGIN_DECLS
-hb_language_t
-hb_language_from_string (const char *str);
-const char *
-hb_language_to_string (hb_language_t language);
+HB_INTERNAL hb_bool_t
+hb_fallback_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options);
HB_END_DECLS
-#endif /* HB_LANGUAGE_H */
+#endif /* HB_FALLBACK_SHAPE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-fallback-shape.cc b/third_party/harfbuzz-ng/src/hb-fallback-shape.cc
new file mode 100644
index 0000000..2fd527f
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-fallback-shape.cc
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2011 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-fallback-shape-private.hh"
+
+#include "hb-buffer-private.hh"
+
+hb_bool_t
+hb_fallback_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options)
+{
+ buffer->guess_properties ();
+
+ unsigned int count = buffer->len;
+
+ for (unsigned int i = 0; i < count; i++)
+ hb_font_get_glyph (font, buffer->info[i].codepoint, 0, &buffer->info[i].codepoint);
+
+ buffer->clear_positions ();
+
+ for (unsigned int i = 0; i < count; i++) {
+ hb_font_get_glyph_advance_for_direction (font, buffer->info[i].codepoint,
+ buffer->props.direction,
+ &buffer->pos[i].x_advance,
+ &buffer->pos[i].y_advance);
+ hb_font_subtract_glyph_origin_for_direction (font, buffer->info[i].codepoint,
+ buffer->props.direction,
+ &buffer->pos[i].x_offset,
+ &buffer->pos[i].y_offset);
+ }
+
+ if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
+ hb_buffer_reverse (buffer);
+
+ return TRUE;
+}
diff --git a/third_party/harfbuzz-ng/src/hb-font-private.h b/third_party/harfbuzz-ng/src/hb-font-private.h
deleted file mode 100644
index b147bce..0000000
--- a/third_party/harfbuzz-ng/src/hb-font-private.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2009 Red Hat, 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_FONT_PRIVATE_H
-#define HB_FONT_PRIVATE_H
-
-#include "hb-private.h"
-
-#include "hb-font.h"
-
-HB_BEGIN_DECLS
-
-
-/*
- * hb_font_funcs_t
- */
-
-struct _hb_font_funcs_t {
- hb_reference_count_t ref_count;
-
- hb_bool_t immutable;
-
- struct {
- hb_font_get_glyph_func_t get_glyph;
- hb_font_get_glyph_advance_func_t get_glyph_advance;
- hb_font_get_glyph_extents_func_t get_glyph_extents;
- hb_font_get_contour_point_func_t get_contour_point;
- hb_font_get_kerning_func_t get_kerning;
- } v;
-};
-
-extern HB_INTERNAL hb_font_funcs_t _hb_font_funcs_nil;
-
-
-/*
- * hb_face_t
- */
-
-struct _hb_face_t {
- hb_reference_count_t ref_count;
-
- hb_get_table_func_t get_table;
- hb_destroy_func_t destroy;
- void *user_data;
-
- hb_blob_t *head_blob;
- const struct head *head_table;
-
- struct hb_ot_layout_t *ot_layout;
-};
-
-
-/*
- * hb_font_t
- */
-
-struct _hb_font_t {
- hb_reference_count_t ref_count;
-
- unsigned int x_scale;
- unsigned int y_scale;
-
- unsigned int x_ppem;
- unsigned int y_ppem;
-
- hb_font_funcs_t *klass;
- hb_destroy_func_t destroy;
- void *user_data;
-};
-
-
-HB_END_DECLS
-
-#endif /* HB_FONT_PRIVATE_H */
diff --git a/third_party/harfbuzz-ng/src/hb-font-private.hh b/third_party/harfbuzz-ng/src/hb-font-private.hh
new file mode 100644
index 0000000..d896e72
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-font-private.hh
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2011 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_FONT_PRIVATE_HH
+#define HB_FONT_PRIVATE_HH
+
+#include "hb-private.hh"
+
+#include "hb-font.h"
+#include "hb-object-private.hh"
+
+
+
+/*
+ * hb_font_funcs_t
+ */
+
+#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
+ HB_FONT_FUNC_IMPLEMENT (glyph) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
+ /* ^--- Add new callbacks here */
+
+struct _hb_font_funcs_t {
+ hb_object_header_t header;
+
+ hb_bool_t immutable;
+
+ /* Don't access these directly. Call hb_font_get_*() instead. */
+
+ struct {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+ } get;
+
+ struct {
+#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+ } user_data;
+
+ struct {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+ } destroy;
+};
+
+
+/*
+ * hb_face_t
+ */
+
+struct _hb_face_t {
+ hb_object_header_t header;
+
+ hb_bool_t immutable;
+
+ hb_reference_table_func_t reference_table;
+ void *user_data;
+ hb_destroy_func_t destroy;
+
+ struct hb_ot_layout_t *ot_layout;
+
+ unsigned int index;
+ unsigned int upem;
+};
+
+
+/*
+ * hb_font_t
+ */
+
+struct _hb_font_t {
+ hb_object_header_t header;
+
+ hb_bool_t immutable;
+
+ hb_font_t *parent;
+ hb_face_t *face;
+
+ int x_scale;
+ int y_scale;
+
+ unsigned int x_ppem;
+ unsigned int y_ppem;
+
+ hb_font_funcs_t *klass;
+ void *user_data;
+ hb_destroy_func_t destroy;
+
+
+ /* Convert from font-space to user-space */
+ inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
+ inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
+
+ /* Convert from parent-font user-space to our user-space */
+ inline hb_position_t parent_scale_x_distance (hb_position_t v) {
+ if (unlikely (parent && parent->x_scale != x_scale))
+ return v * (int64_t) this->x_scale / this->parent->x_scale;
+ return v;
+ }
+ inline hb_position_t parent_scale_y_distance (hb_position_t v) {
+ if (unlikely (parent && parent->y_scale != y_scale))
+ return v * (int64_t) this->y_scale / this->parent->y_scale;
+ return v;
+ }
+ inline hb_position_t parent_scale_x_position (hb_position_t v) {
+ return parent_scale_x_distance (v);
+ }
+ inline hb_position_t parent_scale_y_position (hb_position_t v) {
+ return parent_scale_y_distance (v);
+ }
+
+ inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
+ *x = parent_scale_x_distance (*x);
+ *y = parent_scale_y_distance (*y);
+ }
+ inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
+ *x = parent_scale_x_position (*x);
+ *y = parent_scale_y_position (*y);
+ }
+
+
+ private:
+ inline hb_position_t em_scale (int16_t v, int scale) { return v * (int64_t) scale / hb_face_get_upem (this->face); }
+};
+
+
+
+#endif /* HB_FONT_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-font.cc b/third_party/harfbuzz-ng/src/hb-font.cc
index 63631a9..d549455 100644
--- a/third_party/harfbuzz-ng/src/hb-font.cc
+++ b/third_party/harfbuzz-ng/src/hb-font.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,128 +24,248 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#include "hb-private.h"
-
-#include "hb-font-private.h"
-#include "hb-blob-private.h"
-#include "hb-open-file-private.hh"
+#include "hb-private.hh"
#include "hb-ot-layout-private.hh"
+#include "hb-font-private.hh"
+#include "hb-blob.h"
+#include "hb-open-file-private.hh"
+#include "hb-ot-head-table.hh"
+
#include <string.h>
-HB_BEGIN_DECLS
/*
* hb_font_funcs_t
*/
-static hb_codepoint_t
+static hb_bool_t
hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data HB_UNUSED,
- hb_codepoint_t unicode HB_UNUSED,
- hb_codepoint_t variation_selector HB_UNUSED)
-{ return 0; }
+ void *font_data HB_UNUSED,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return hb_font_get_glyph (font->parent, unicode, variation_selector, glyph);
-static void
-hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data HB_UNUSED,
- hb_codepoint_t glyph HB_UNUSED,
- hb_position_t *x_advance HB_UNUSED,
- hb_position_t *y_advance HB_UNUSED)
-{ }
+ *glyph = 0;
+ return FALSE;
+}
-static void
-hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data HB_UNUSED,
- hb_codepoint_t glyph HB_UNUSED,
- hb_glyph_extents_t *extents HB_UNUSED)
-{ }
+static hb_position_t
+hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return font->parent_scale_x_distance (hb_font_get_glyph_h_advance (font->parent, glyph));
+
+ return font->x_scale;
+}
+
+static hb_position_t
+hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return font->parent_scale_y_distance (hb_font_get_glyph_v_advance (font->parent, glyph));
+
+ return font->y_scale;
+}
+
+static hb_bool_t
+hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent,
+ glyph,
+ x, y);
+ if (ret)
+ font->parent_scale_position (x, y);
+ return ret;
+ }
+
+ *x = *y = 0;
+ return FALSE;
+}
static hb_bool_t
-hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data HB_UNUSED,
- unsigned int point_index HB_UNUSED,
- hb_codepoint_t glyph HB_UNUSED,
- hb_position_t *x HB_UNUSED,
- hb_position_t *y HB_UNUSED)
-{ return false; }
+hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent,
+ glyph,
+ x, y);
+ if (ret)
+ font->parent_scale_position (x, y);
+ return ret;
+ }
+
+ *x = *y = 0;
+ return FALSE;
+}
+
+static hb_position_t
+hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t left_glyph,
+ hb_codepoint_t right_glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return font->parent_scale_x_distance (hb_font_get_glyph_h_kerning (font->parent, left_glyph, right_glyph));
+
+ return 0;
+}
static hb_position_t
-hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data HB_UNUSED,
- hb_codepoint_t first_glyph HB_UNUSED,
- hb_codepoint_t second_glyph HB_UNUSED)
-{ return 0; }
-
-hb_font_funcs_t _hb_font_funcs_nil = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
- TRUE, /* immutable */
+hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t top_glyph,
+ hb_codepoint_t bottom_glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return font->parent_scale_y_distance (hb_font_get_glyph_v_kerning (font->parent, top_glyph, bottom_glyph));
+
+ return 0;
+}
+
+static hb_bool_t
+hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_extents (font->parent,
+ glyph,
+ extents);
+ if (ret) {
+ font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
+ font->parent_scale_distance (&extents->width, &extents->height);
+ }
+ return ret;
+ }
+
+ memset (extents, 0, sizeof (*extents));
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ unsigned int point_index,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_contour_point (font->parent,
+ glyph, point_index,
+ x, y);
+ if (ret)
+ font->parent_scale_position (x, y);
+ return ret;
+ }
+
+ *x = *y = 0;
+ return FALSE;
+}
+
+
+static hb_font_funcs_t _hb_font_funcs_nil = {
+ HB_OBJECT_HEADER_STATIC,
+
+ TRUE, /* immutable */
+
{
- hb_font_get_glyph_nil,
- hb_font_get_glyph_advance_nil,
- hb_font_get_glyph_extents_nil,
- hb_font_get_contour_point_nil,
- hb_font_get_kerning_nil
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
}
};
+
hb_font_funcs_t *
hb_font_funcs_create (void)
{
hb_font_funcs_t *ffuncs;
- if (!HB_OBJECT_DO_CREATE (hb_font_funcs_t, ffuncs))
+ if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
return &_hb_font_funcs_nil;
- ffuncs->v = _hb_font_funcs_nil.v;
+ ffuncs->get = _hb_font_funcs_nil.get;
return ffuncs;
}
hb_font_funcs_t *
-hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
+hb_font_funcs_get_empty (void)
{
- HB_OBJECT_DO_REFERENCE (ffuncs);
+ return &_hb_font_funcs_nil;
}
-unsigned int
-hb_font_funcs_get_reference_count (hb_font_funcs_t *ffuncs)
+hb_font_funcs_t *
+hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
{
- HB_OBJECT_DO_GET_REFERENCE_COUNT (ffuncs);
+ return hb_object_reference (ffuncs);
}
void
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
{
- HB_OBJECT_DO_DESTROY (ffuncs);
+ if (!hb_object_destroy (ffuncs)) return;
+
+#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
+ ffuncs->destroy.name (ffuncs->user_data.name);
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
free (ffuncs);
}
-hb_font_funcs_t *
-hb_font_funcs_copy (hb_font_funcs_t *other_ffuncs)
+hb_bool_t
+hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
{
- hb_font_funcs_t *ffuncs;
-
- if (!HB_OBJECT_DO_CREATE (hb_font_funcs_t, ffuncs))
- return &_hb_font_funcs_nil;
-
- ffuncs->v = other_ffuncs->v;
+ return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
+}
- return ffuncs;
+void *
+hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (ffuncs, key);
}
+
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
{
- if (HB_OBJECT_IS_INERT (ffuncs))
+ if (hb_object_is_inert (ffuncs))
return;
ffuncs->immutable = TRUE;
@@ -158,133 +278,253 @@ hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
}
-void
-hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_func_t glyph_func)
-{
- if (ffuncs->immutable)
- return;
+#define HB_FONT_FUNC_IMPLEMENT(name) \
+ \
+void \
+hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
+ hb_font_get_##name##_func_t func, \
+ void *user_data, \
+ hb_destroy_func_t destroy) \
+{ \
+ if (ffuncs->immutable) { \
+ if (destroy) \
+ destroy (user_data); \
+ return; \
+ } \
+ \
+ if (ffuncs->destroy.name) \
+ ffuncs->destroy.name (ffuncs->user_data.name); \
+ \
+ if (func) { \
+ ffuncs->get.name = func; \
+ ffuncs->user_data.name = user_data; \
+ ffuncs->destroy.name = destroy; \
+ } else { \
+ ffuncs->get.name = hb_font_get_##name##_nil; \
+ ffuncs->user_data.name = NULL; \
+ ffuncs->destroy.name = NULL; \
+ } \
+}
+
+HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
- ffuncs->v.get_glyph = glyph_func ? glyph_func : hb_font_get_glyph_nil;
-}
-void
-hb_font_funcs_set_glyph_advance_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_advance_func_t glyph_advance_func)
+hb_bool_t
+hb_font_get_glyph (hb_font_t *font,
+ hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+ hb_codepoint_t *glyph)
{
- if (ffuncs->immutable)
- return;
-
- ffuncs->v.get_glyph_advance = glyph_advance_func ? glyph_advance_func : hb_font_get_glyph_advance_nil;
+ *glyph = 0;
+ return font->klass->get.glyph (font, font->user_data,
+ unicode, variation_selector, glyph,
+ font->klass->user_data.glyph);
}
-void
-hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_extents_func_t glyph_extents_func)
+hb_position_t
+hb_font_get_glyph_h_advance (hb_font_t *font,
+ hb_codepoint_t glyph)
{
- if (ffuncs->immutable)
- return;
-
- ffuncs->v.get_glyph_extents = glyph_extents_func ? glyph_extents_func : hb_font_get_glyph_extents_nil;
+ return font->klass->get.glyph_h_advance (font, font->user_data,
+ glyph,
+ font->klass->user_data.glyph_h_advance);
}
-void
-hb_font_funcs_set_contour_point_func (hb_font_funcs_t *ffuncs,
- hb_font_get_contour_point_func_t contour_point_func)
+hb_position_t
+hb_font_get_glyph_v_advance (hb_font_t *font,
+ hb_codepoint_t glyph)
{
- if (ffuncs->immutable)
- return;
-
- ffuncs->v.get_contour_point = contour_point_func ? contour_point_func : hb_font_get_contour_point_nil;
+ return font->klass->get.glyph_v_advance (font, font->user_data,
+ glyph,
+ font->klass->user_data.glyph_v_advance);
}
-void
-hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
- hb_font_get_kerning_func_t kerning_func)
+hb_bool_t
+hb_font_get_glyph_h_origin (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x, hb_position_t *y)
{
- if (ffuncs->immutable)
- return;
-
- ffuncs->v.get_kerning = kerning_func ? kerning_func : hb_font_get_kerning_nil;
+ *x = *y = 0;
+ return font->klass->get.glyph_h_origin (font, font->user_data,
+ glyph, x, y,
+ font->klass->user_data.glyph_h_origin);
}
-
-hb_font_get_glyph_func_t
-hb_font_funcs_get_glyph_func (hb_font_funcs_t *ffuncs)
+hb_bool_t
+hb_font_get_glyph_v_origin (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x, hb_position_t *y)
{
- return ffuncs->v.get_glyph;
+ *x = *y = 0;
+ return font->klass->get.glyph_v_origin (font, font->user_data,
+ glyph, x, y,
+ font->klass->user_data.glyph_v_origin);
}
-hb_font_get_glyph_advance_func_t
-hb_font_funcs_get_glyph_advance_func (hb_font_funcs_t *ffuncs)
+hb_position_t
+hb_font_get_glyph_h_kerning (hb_font_t *font,
+ hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
{
- return ffuncs->v.get_glyph_advance;
+ return font->klass->get.glyph_h_kerning (font, font->user_data,
+ left_glyph, right_glyph,
+ font->klass->user_data.glyph_h_kerning);
}
-hb_font_get_glyph_extents_func_t
-hb_font_funcs_get_glyph_extents_func (hb_font_funcs_t *ffuncs)
+hb_position_t
+hb_font_get_glyph_v_kerning (hb_font_t *font,
+ hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
{
- return ffuncs->v.get_glyph_extents;
+ return font->klass->get.glyph_v_kerning (font, font->user_data,
+ left_glyph, right_glyph,
+ font->klass->user_data.glyph_v_kerning);
}
-hb_font_get_contour_point_func_t
-hb_font_funcs_get_contour_point_func (hb_font_funcs_t *ffuncs)
+hb_bool_t
+hb_font_get_glyph_extents (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents)
{
- return ffuncs->v.get_contour_point;
+ memset (extents, 0, sizeof (*extents));
+ return font->klass->get.glyph_extents (font, font->user_data,
+ glyph,
+ extents,
+ font->klass->user_data.glyph_extents);
}
-hb_font_get_kerning_func_t
-hb_font_funcs_get_kerning_func (hb_font_funcs_t *ffuncs)
+hb_bool_t
+hb_font_get_glyph_contour_point (hb_font_t *font,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_position_t *x, hb_position_t *y)
{
- return ffuncs->v.get_kerning;
+ *x = *y = 0;
+ return font->klass->get.glyph_contour_point (font, font->user_data,
+ glyph, point_index,
+ x, y,
+ font->klass->user_data.glyph_contour_point);
}
+/* A bit higher-level, and with fallback */
+
+void
+hb_font_get_glyph_advance_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y)
+{
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
+ *x = hb_font_get_glyph_h_advance (font, glyph);
+ *y = 0;
+ } else {
+ *x = 0;
+ *y = hb_font_get_glyph_v_advance (font, glyph);
+ }
+}
-hb_codepoint_t
-hb_font_get_glyph (hb_font_t *font, hb_face_t *face,
- hb_codepoint_t unicode, hb_codepoint_t variation_selector)
+static void
+guess_v_origin_minus_h_origin (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x, hb_position_t *y)
{
- return font->klass->v.get_glyph (font, face, font->user_data,
- unicode, variation_selector);
+ *x = hb_font_get_glyph_h_advance (font, glyph) / 2;
+
+ /* TODO use font_metics.ascent */
+ *y = font->y_scale;
}
+
void
-hb_font_get_glyph_advance (hb_font_t *font, hb_face_t *face,
- hb_codepoint_t glyph,
- hb_position_t *x_advance, hb_position_t *y_advance)
+hb_font_get_glyph_origin_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y)
+{
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
+ hb_bool_t ret = hb_font_get_glyph_h_origin (font, glyph, x, y);
+ if (!ret && (ret = hb_font_get_glyph_v_origin (font, glyph, x, y))) {
+ hb_position_t dx, dy;
+ guess_v_origin_minus_h_origin (font, glyph, &dx, &dy);
+ *x -= dx; *y -= dy;
+ }
+ } else {
+ hb_bool_t ret = hb_font_get_glyph_v_origin (font, glyph, x, y);
+ if (!ret && (ret = hb_font_get_glyph_h_origin (font, glyph, x, y))) {
+ hb_position_t dx, dy;
+ guess_v_origin_minus_h_origin (font, glyph, &dx, &dy);
+ *x += dx; *y += dy;
+ }
+ }
+}
+
+void
+hb_font_add_glyph_origin_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y)
{
- *x_advance = *y_advance = 0;
- return font->klass->v.get_glyph_advance (font, face, font->user_data,
- glyph, x_advance, y_advance);
+ hb_position_t origin_x, origin_y;
+
+ hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y);
+
+ *x += origin_x;
+ *y += origin_y;
}
void
-hb_font_get_glyph_extents (hb_font_t *font, hb_face_t *face,
- hb_codepoint_t glyph, hb_glyph_extents_t *extents)
+hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y)
{
- memset (extents, 0, sizeof (*extents));
- return font->klass->v.get_glyph_extents (font, face, font->user_data,
- glyph, extents);
+ hb_position_t origin_x, origin_y;
+
+ hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y);
+
+ *x -= origin_x;
+ *y -= origin_y;
+}
+
+void
+hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
+ hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y)
+{
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
+ *x = hb_font_get_glyph_h_kerning (font, first_glyph, second_glyph);
+ *y = 0;
+ } else {
+ *x = 0;
+ *y = hb_font_get_glyph_v_kerning (font, first_glyph, second_glyph);
+ }
}
hb_bool_t
-hb_font_get_contour_point (hb_font_t *font, hb_face_t *face,
- unsigned int point_index,
- hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y)
+hb_font_get_glyph_extents_for_origin (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_glyph_extents_t *extents)
{
- *x = 0; *y = 0;
- return font->klass->v.get_contour_point (font, face, font->user_data,
- point_index,
- glyph, x, y);
+ hb_bool_t ret = hb_font_get_glyph_extents (font, glyph, extents);
+
+ if (ret)
+ hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, &extents->x_bearing, &extents->y_bearing);
+
+ return ret;
}
-hb_position_t
-hb_font_get_kerning (hb_font_t *font, hb_face_t *face,
- hb_codepoint_t first_glyph, hb_codepoint_t second_glyph)
+hb_bool_t
+hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y)
{
- return font->klass->v.get_kerning (font, face, font->user_data,
- first_glyph, second_glyph);
+ hb_bool_t ret = hb_font_get_glyph_contour_point (font, glyph, point_index, x, y);
+
+ if (ret)
+ hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, x, y);
+
+ return ret;
}
@@ -293,40 +533,41 @@ hb_font_get_kerning (hb_font_t *font, hb_face_t *face,
*/
static hb_face_t _hb_face_nil = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
+ HB_OBJECT_HEADER_STATIC,
- NULL, /* get_table */
- NULL, /* destroy */
+ TRUE, /* immutable */
+
+ NULL, /* reference_table */
NULL, /* user_data */
+ NULL, /* destroy */
- NULL, /* head_blob */
- NULL, /* head_table */
+ NULL, /* ot_layout */
- NULL /* ot_layout */
+ 0, /* index */
+ 1000 /* upem */
};
hb_face_t *
-hb_face_create_for_tables (hb_get_table_func_t get_table,
- hb_destroy_func_t destroy,
- void *user_data)
+hb_face_create_for_tables (hb_reference_table_func_t reference_table,
+ void *user_data,
+ hb_destroy_func_t destroy)
{
hb_face_t *face;
- if (!HB_OBJECT_DO_CREATE (hb_face_t, face)) {
+ if (!reference_table || !(face = hb_object_create<hb_face_t> ())) {
if (destroy)
destroy (user_data);
return &_hb_face_nil;
}
- face->get_table = get_table;
- face->destroy = destroy;
+ face->reference_table = reference_table;
face->user_data = user_data;
+ face->destroy = destroy;
- face->ot_layout = _hb_ot_layout_new (face);
+ face->ot_layout = _hb_ot_layout_create (face);
- face->head_blob = Sanitizer<head>::sanitize (hb_face_get_table (face, HB_OT_TAG_head));
- face->head_table = Sanitizer<head>::lock_instance (face->head_blob);
+ face->upem = 0;
return face;
}
@@ -360,10 +601,13 @@ _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
}
static hb_blob_t *
-_hb_face_for_data_get_table (hb_tag_t tag, void *user_data)
+_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
{
hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
+ if (tag == HB_TAG_NONE)
+ return hb_blob_reference (data->blob);
+
const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
const OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
@@ -371,47 +615,51 @@ _hb_face_for_data_get_table (hb_tag_t tag, void *user_data)
hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
- hb_blob_unlock (data->blob);
-
return blob;
}
hb_face_t *
-hb_face_create_for_data (hb_blob_t *blob,
- unsigned int index)
+hb_face_create (hb_blob_t *blob,
+ unsigned int index)
{
+ hb_face_t *face;
+
+ if (unlikely (!blob || !hb_blob_get_length (blob)))
+ return &_hb_face_nil;
+
hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
if (unlikely (!closure))
return &_hb_face_nil;
- return hb_face_create_for_tables (_hb_face_for_data_get_table,
- (hb_destroy_func_t) _hb_face_for_data_closure_destroy,
- closure);
-}
+ face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
+ closure,
+ (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
+
+ hb_face_set_index (face, index);
+ return face;
+}
hb_face_t *
-hb_face_reference (hb_face_t *face)
+hb_face_get_empty (void)
{
- HB_OBJECT_DO_REFERENCE (face);
+ return &_hb_face_nil;
}
-unsigned int
-hb_face_get_reference_count (hb_face_t *face)
+
+hb_face_t *
+hb_face_reference (hb_face_t *face)
{
- HB_OBJECT_DO_GET_REFERENCE_COUNT (face);
+ return hb_object_reference (face);
}
void
hb_face_destroy (hb_face_t *face)
{
- HB_OBJECT_DO_DESTROY (face);
-
- _hb_ot_layout_free (face->ot_layout);
+ if (!hb_object_destroy (face)) return;
- hb_blob_unlock (face->head_blob);
- hb_blob_destroy (face->head_blob);
+ _hb_ot_layout_destroy (face->ot_layout);
if (face->destroy)
face->destroy (face->user_data);
@@ -419,24 +667,97 @@ hb_face_destroy (hb_face_t *face)
free (face);
}
+hb_bool_t
+hb_face_set_user_data (hb_face_t *face,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (face, key, data, destroy, replace);
+}
+
+void *
+hb_face_get_user_data (hb_face_t *face,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (face, key);
+}
+
+void
+hb_face_make_immutable (hb_face_t *face)
+{
+ if (hb_object_is_inert (face))
+ return;
+
+ face->immutable = true;
+}
+
+hb_bool_t
+hb_face_is_immutable (hb_face_t *face)
+{
+ return face->immutable;
+}
+
+
hb_blob_t *
-hb_face_get_table (hb_face_t *face,
- hb_tag_t tag)
+hb_face_reference_table (hb_face_t *face,
+ hb_tag_t tag)
{
hb_blob_t *blob;
- if (unlikely (!face || !face->get_table))
- return &_hb_blob_nil;
+ if (unlikely (!face || !face->reference_table))
+ return hb_blob_get_empty ();
- blob = face->get_table (tag, face->user_data);
+ blob = face->reference_table (face, tag, face->user_data);
+ if (unlikely (!blob))
+ return hb_blob_get_empty ();
return blob;
}
+hb_blob_t *
+hb_face_reference_blob (hb_face_t *face)
+{
+ return hb_face_reference_table (face, HB_TAG_NONE);
+}
+
+void
+hb_face_set_index (hb_face_t *face,
+ unsigned int index)
+{
+ if (hb_object_is_inert (face))
+ return;
+
+ face->index = 0;
+}
+
+unsigned int
+hb_face_get_index (hb_face_t *face)
+{
+ return face->index;
+}
+
+void
+hb_face_set_upem (hb_face_t *face,
+ unsigned int upem)
+{
+ if (hb_object_is_inert (face))
+ return;
+
+ face->upem = upem;
+}
+
unsigned int
hb_face_get_upem (hb_face_t *face)
{
- return (face->head_table ? face->head_table : &Null(head))->get_upem ();
+ if (unlikely (!face->upem)) {
+ hb_blob_t *head_blob = Sanitizer<head>::sanitize (hb_face_reference_table (face, HB_OT_TAG_head));
+ const head *head_table = Sanitizer<head>::lock_instance (head_blob);
+ face->upem = head_table->get_upem ();
+ hb_blob_destroy (head_blob);
+ }
+ return face->upem;
}
@@ -445,7 +766,12 @@ hb_face_get_upem (hb_face_t *face)
*/
static hb_font_t _hb_font_nil = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
+ HB_OBJECT_HEADER_STATIC,
+
+ TRUE, /* immutable */
+
+ NULL, /* parent */
+ &_hb_face_nil,
0, /* x_scale */
0, /* y_scale */
@@ -453,41 +779,73 @@ static hb_font_t _hb_font_nil = {
0, /* x_ppem */
0, /* y_ppem */
- NULL, /* klass */
- NULL, /* destroy */
- NULL /* user_data */
+ &_hb_font_funcs_nil, /* klass */
+ NULL, /* user_data */
+ NULL /* destroy */
};
hb_font_t *
-hb_font_create (void)
+hb_font_create (hb_face_t *face)
{
hb_font_t *font;
- if (!HB_OBJECT_DO_CREATE (hb_font_t, font))
+ if (unlikely (!face))
+ face = &_hb_face_nil;
+ if (unlikely (hb_object_is_inert (face)))
+ return &_hb_font_nil;
+ if (!(font = hb_object_create<hb_font_t> ()))
return &_hb_font_nil;
+ hb_face_make_immutable (face);
+ font->face = hb_face_reference (face);
font->klass = &_hb_font_funcs_nil;
return font;
}
hb_font_t *
-hb_font_reference (hb_font_t *font)
+hb_font_create_sub_font (hb_font_t *parent)
{
- HB_OBJECT_DO_REFERENCE (font);
+ if (unlikely (!parent))
+ return &_hb_font_nil;
+
+ hb_font_t *font = hb_font_create (parent->face);
+
+ if (unlikely (hb_object_is_inert (font)))
+ return font;
+
+ hb_font_make_immutable (parent);
+ font->parent = hb_font_reference (parent);
+
+ font->x_scale = parent->x_scale;
+ font->y_scale = parent->y_scale;
+ font->x_ppem = parent->x_ppem;
+ font->y_ppem = parent->y_ppem;
+
+ font->klass = &_hb_font_funcs_nil;
+
+ return font;
}
-unsigned int
-hb_font_get_reference_count (hb_font_t *font)
+hb_font_t *
+hb_font_get_empty (void)
{
- HB_OBJECT_DO_GET_REFERENCE_COUNT (font);
+ return &_hb_font_nil;
+}
+
+hb_font_t *
+hb_font_reference (hb_font_t *font)
+{
+ return hb_object_reference (font);
}
void
hb_font_destroy (hb_font_t *font)
{
- HB_OBJECT_DO_DESTROY (font);
+ if (!hb_object_destroy (font)) return;
+ hb_font_destroy (font->parent);
+ hb_face_destroy (font->face);
hb_font_funcs_destroy (font->klass);
if (font->destroy)
font->destroy (font->user_data);
@@ -495,14 +853,62 @@ hb_font_destroy (hb_font_t *font)
free (font);
}
+hb_bool_t
+hb_font_set_user_data (hb_font_t *font,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (font, key, data, destroy, replace);
+}
+
+void *
+hb_font_get_user_data (hb_font_t *font,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (font, key);
+}
+
+void
+hb_font_make_immutable (hb_font_t *font)
+{
+ if (hb_object_is_inert (font))
+ return;
+
+ font->immutable = true;
+}
+
+hb_bool_t
+hb_font_is_immutable (hb_font_t *font)
+{
+ return font->immutable;
+}
+
+hb_font_t *
+hb_font_get_parent (hb_font_t *font)
+{
+ return font->parent;
+}
+
+hb_face_t *
+hb_font_get_face (hb_font_t *font)
+{
+ return font->face;
+}
+
+
void
hb_font_set_funcs (hb_font_t *font,
hb_font_funcs_t *klass,
- hb_destroy_func_t destroy,
- void *user_data)
+ void *user_data,
+ hb_destroy_func_t destroy)
{
- if (HB_OBJECT_IS_INERT (font))
+ if (font->immutable) {
+ if (destroy)
+ destroy (user_data);
return;
+ }
if (font->destroy)
font->destroy (font->user_data);
@@ -513,36 +919,36 @@ hb_font_set_funcs (hb_font_t *font,
hb_font_funcs_reference (klass);
hb_font_funcs_destroy (font->klass);
font->klass = klass;
- font->destroy = destroy;
font->user_data = user_data;
+ font->destroy = destroy;
}
void
-hb_font_unset_funcs (hb_font_t *font,
- hb_font_funcs_t **klass,
- hb_destroy_func_t *destroy,
- void **user_data)
+hb_font_set_funcs_data (hb_font_t *font,
+ void *user_data,
+ hb_destroy_func_t destroy)
{
- /* None of the input arguments can be NULL. */
-
- *klass = font->klass;
- *destroy = font->destroy;
- *user_data = font->user_data;
-
- if (HB_OBJECT_IS_INERT (font))
+ /* Destroy user_data? */
+ if (font->immutable) {
+ if (destroy)
+ destroy (user_data);
return;
+ }
+
+ if (font->destroy)
+ font->destroy (font->user_data);
- font->klass = NULL;
- font->destroy = NULL;
- font->user_data = NULL;
+ font->user_data = user_data;
+ font->destroy = destroy;
}
+
void
hb_font_set_scale (hb_font_t *font,
- unsigned int x_scale,
- unsigned int y_scale)
+ int x_scale,
+ int y_scale)
{
- if (HB_OBJECT_IS_INERT (font))
+ if (font->immutable)
return;
font->x_scale = x_scale;
@@ -551,8 +957,8 @@ hb_font_set_scale (hb_font_t *font,
void
hb_font_get_scale (hb_font_t *font,
- unsigned int *x_scale,
- unsigned int *y_scale)
+ int *x_scale,
+ int *y_scale)
{
if (x_scale) *x_scale = font->x_scale;
if (y_scale) *y_scale = font->y_scale;
@@ -563,7 +969,7 @@ hb_font_set_ppem (hb_font_t *font,
unsigned int x_ppem,
unsigned int y_ppem)
{
- if (HB_OBJECT_IS_INERT (font))
+ if (font->immutable)
return;
font->x_ppem = x_ppem;
@@ -580,4 +986,3 @@ hb_font_get_ppem (hb_font_t *font,
}
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-font.h b/third_party/harfbuzz-ng/src/hb-font.h
index f33e56f..8a9dda5 100644
--- a/third_party/harfbuzz-ng/src/hb-font.h
+++ b/third_party/harfbuzz-ng/src/hb-font.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -41,42 +41,62 @@ typedef struct _hb_font_t hb_font_t;
*/
hb_face_t *
-hb_face_create_for_data (hb_blob_t *blob,
- unsigned int index);
+hb_face_create (hb_blob_t *blob,
+ unsigned int index);
-typedef hb_blob_t * (*hb_get_table_func_t) (hb_tag_t tag, void *user_data);
+typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data);
/* calls destroy() when not needing user_data anymore */
hb_face_t *
-hb_face_create_for_tables (hb_get_table_func_t get_table,
- hb_destroy_func_t destroy,
- void *user_data);
+hb_face_create_for_tables (hb_reference_table_func_t reference_table,
+ void *user_data,
+ hb_destroy_func_t destroy);
hb_face_t *
-hb_face_reference (hb_face_t *face);
+hb_face_get_empty (void);
-unsigned int
-hb_face_get_reference_count (hb_face_t *face);
+hb_face_t *
+hb_face_reference (hb_face_t *face);
void
hb_face_destroy (hb_face_t *face);
-/* XXX
- *
- * I have two major concerns about this API as it is right now:
- *
- * - Jonathan Kew convinced me to make it return NULL if table not found (280af1bd),
- * however, that is WRONG IMO. The API should not differentiate between a non-existing
- * table vs a zero-length table vs a very short table. It only leads to implementations
- * that check for non-NULL and assume that they've got a usable table going on... This
- * actually happened with Firefox.
- *
- * - It has to be renamed to reference_table() since unlike any other _get_ API, a reference
- * ownership transfer happens and the user is responsible to destroy the result.
- */
+hb_bool_t
+hb_face_set_user_data (hb_face_t *face,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+
+void *
+hb_face_get_user_data (hb_face_t *face,
+ hb_user_data_key_t *key);
+
+void
+hb_face_make_immutable (hb_face_t *face);
+
+hb_bool_t
+hb_face_is_immutable (hb_face_t *face);
+
+
+hb_blob_t *
+hb_face_reference_table (hb_face_t *face,
+ hb_tag_t tag);
+
hb_blob_t *
-hb_face_get_table (hb_face_t *face,
- hb_tag_t tag);
+hb_face_reference_blob (hb_face_t *face);
+
+void
+hb_face_set_index (hb_face_t *face,
+ unsigned int index);
+
+unsigned int
+hb_face_get_index (hb_face_t *face);
+
+void
+hb_face_set_upem (hb_face_t *face,
+ unsigned int upem);
unsigned int
hb_face_get_upem (hb_face_t *face);
@@ -92,16 +112,26 @@ hb_font_funcs_t *
hb_font_funcs_create (void);
hb_font_funcs_t *
-hb_font_funcs_reference (hb_font_funcs_t *ffuncs);
+hb_font_funcs_get_empty (void);
-unsigned int
-hb_font_funcs_get_reference_count (hb_font_funcs_t *ffuncs);
+hb_font_funcs_t *
+hb_font_funcs_reference (hb_font_funcs_t *ffuncs);
void
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs);
-hb_font_funcs_t *
-hb_font_funcs_copy (hb_font_funcs_t *ffuncs);
+hb_bool_t
+hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+
+void *
+hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key);
+
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs);
@@ -113,88 +143,176 @@ hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
typedef struct _hb_glyph_extents_t
{
- hb_position_t x_bearing;
- hb_position_t y_bearing;
- hb_position_t width;
- hb_position_t height;
+ hb_position_t x_bearing;
+ hb_position_t y_bearing;
+ hb_position_t width;
+ hb_position_t height;
} hb_glyph_extents_t;
-typedef hb_codepoint_t (*hb_font_get_glyph_func_t) (hb_font_t *font, hb_face_t *face, const void *user_data,
- hb_codepoint_t unicode, hb_codepoint_t variation_selector);
-typedef void (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, hb_face_t *face, const void *user_data,
- hb_codepoint_t glyph,
- hb_position_t *x_advance, hb_position_t *y_advance);
-typedef void (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, hb_face_t *face, const void *user_data,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents);
-typedef hb_bool_t (*hb_font_get_contour_point_func_t) (hb_font_t *font, hb_face_t *face, const void *user_data,
- unsigned int point_index, hb_codepoint_t glyph,
- hb_position_t *x, hb_position_t *y);
-typedef hb_position_t (*hb_font_get_kerning_func_t) (hb_font_t *font, hb_face_t *face, const void *user_data,
- hb_codepoint_t first_glyph, hb_codepoint_t second_glyph);
+
+/* func types */
+
+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_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ void *user_data);
+typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
+typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
+
+typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x, hb_position_t *y,
+ void *user_data);
+typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
+typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
+
+typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+ void *user_data);
+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
+
+
+typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data);
+typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_position_t *x, hb_position_t *y,
+ void *user_data);
+
+
+/* func setters */
+
void
hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_func_t glyph_func);
+ hb_font_get_glyph_func_t glyph_func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_font_funcs_set_glyph_advance_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_advance_func_t glyph_advance_func);
+hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_h_advance_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+void
+hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_v_advance_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
- hb_font_get_glyph_extents_func_t glyph_extents_func);
+hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_h_origin_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+void
+hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_v_origin_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_font_funcs_set_contour_point_func (hb_font_funcs_t *ffuncs,
- hb_font_get_contour_point_func_t contour_point_func);
+hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_h_kerning_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+void
+hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_v_kerning_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
- hb_font_get_kerning_func_t kerning_func);
+hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_extents_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+void
+hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_contour_point_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
+/* func dispatch */
-/* These never return NULL. Return fallback defaults instead. */
+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_glyph_func_t
-hb_font_funcs_get_glyph_func (hb_font_funcs_t *ffuncs);
+hb_position_t
+hb_font_get_glyph_h_advance (hb_font_t *font,
+ hb_codepoint_t glyph);
+hb_position_t
+hb_font_get_glyph_v_advance (hb_font_t *font,
+ hb_codepoint_t glyph);
-hb_font_get_glyph_advance_func_t
-hb_font_funcs_get_glyph_advance_func (hb_font_funcs_t *ffuncs);
+hb_bool_t
+hb_font_get_glyph_h_origin (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x, hb_position_t *y);
+hb_bool_t
+hb_font_get_glyph_v_origin (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_position_t *x, hb_position_t *y);
-hb_font_get_glyph_extents_func_t
-hb_font_funcs_get_glyph_extents_func (hb_font_funcs_t *ffuncs);
+hb_position_t
+hb_font_get_glyph_h_kerning (hb_font_t *font,
+ hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
+hb_position_t
+hb_font_get_glyph_v_kerning (hb_font_t *font,
+ hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
-hb_font_get_contour_point_func_t
-hb_font_funcs_get_contour_point_func (hb_font_funcs_t *ffuncs);
+hb_bool_t
+hb_font_get_glyph_extents (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents);
-hb_font_get_kerning_func_t
-hb_font_funcs_get_kerning_func (hb_font_funcs_t *ffuncs);
+hb_bool_t
+hb_font_get_glyph_contour_point (hb_font_t *font,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_position_t *x, hb_position_t *y);
-hb_codepoint_t
-hb_font_get_glyph (hb_font_t *font, hb_face_t *face,
- hb_codepoint_t unicode, hb_codepoint_t variation_selector);
+/* high-level funcs, with fallback */
void
-hb_font_get_glyph_advance (hb_font_t *font, hb_face_t *face,
- hb_codepoint_t glyph,
- hb_position_t *x_advance, hb_position_t *y_advance);
+hb_font_get_glyph_advance_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y);
+void
+hb_font_get_glyph_origin_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y);
+void
+hb_font_add_glyph_origin_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y);
+void
+hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y);
void
-hb_font_get_glyph_extents (hb_font_t *font, hb_face_t *face,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents);
+hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
+ hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y);
hb_bool_t
-hb_font_get_contour_point (hb_font_t *font, hb_face_t *face,
- unsigned int point_index, hb_codepoint_t glyph,
- hb_position_t *x, hb_position_t *y);
+hb_font_get_glyph_extents_for_origin (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_direction_t direction,
+ hb_glyph_extents_t *extents);
-hb_position_t
-hb_font_get_kerning (hb_font_t *font, hb_face_t *face,
- hb_codepoint_t first_glyph, hb_codepoint_t second_glyph);
+hb_bool_t
+hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
+ hb_codepoint_t glyph, unsigned int point_index,
+ hb_direction_t direction,
+ hb_position_t *x, hb_position_t *y);
/*
@@ -204,52 +322,67 @@ hb_font_get_kerning (hb_font_t *font, hb_face_t *face,
/* Fonts are very light-weight objects */
hb_font_t *
-hb_font_create (void);
+hb_font_create (hb_face_t *face);
hb_font_t *
-hb_font_reference (hb_font_t *font);
+hb_font_create_sub_font (hb_font_t *parent);
-unsigned int
-hb_font_get_reference_count (hb_font_t *font);
+hb_font_t *
+hb_font_get_empty (void);
+
+hb_font_t *
+hb_font_reference (hb_font_t *font);
void
hb_font_destroy (hb_font_t *font);
+hb_bool_t
+hb_font_set_user_data (hb_font_t *font,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+
+void *
+hb_font_get_user_data (hb_font_t *font,
+ hb_user_data_key_t *key);
+
+void
+hb_font_make_immutable (hb_font_t *font);
+
+hb_bool_t
+hb_font_is_immutable (hb_font_t *font);
+
+hb_font_t *
+hb_font_get_parent (hb_font_t *font);
+
+hb_face_t *
+hb_font_get_face (hb_font_t *font);
+
+
void
hb_font_set_funcs (hb_font_t *font,
hb_font_funcs_t *klass,
- hb_destroy_func_t destroy,
- void *user_data);
+ void *font_data,
+ hb_destroy_func_t destroy);
-/* Returns what was set and unsets it, but doesn't destroy(user_data).
- * This is useful for wrapping / chaining font_funcs_t's.
- *
- * The client is responsible for:
- *
- * - Take ownership of the reference on the returned klass,
- *
- * - Calling "destroy(user_data)" exactly once if returned destroy func
- * is not NULL and the returned info is not needed anymore.
- */
+/* Be *very* careful with this function! */
void
-hb_font_unset_funcs (hb_font_t *font,
- hb_font_funcs_t **klass,
- hb_destroy_func_t *destroy,
- void **user_data);
+hb_font_set_funcs_data (hb_font_t *font,
+ void *font_data,
+ hb_destroy_func_t destroy);
-/*
- * We should add support for full matrices.
- */
void
hb_font_set_scale (hb_font_t *font,
- unsigned int x_scale,
- unsigned int y_scale);
+ int x_scale,
+ int y_scale);
void
hb_font_get_scale (hb_font_t *font,
- unsigned int *x_scale,
- unsigned int *y_scale);
+ int *x_scale,
+ int *y_scale);
/*
* A zero value means "no hinting in that direction"
diff --git a/third_party/harfbuzz-ng/src/hb-ft.c b/third_party/harfbuzz-ng/src/hb-ft.c
deleted file mode 100644
index e696fe8..0000000
--- a/third_party/harfbuzz-ng/src/hb-ft.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2009 Keith Stribley
- *
- * 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.h"
-
-#include "hb-ft.h"
-
-#include "hb-font-private.h"
-
-#include FT_TRUETYPE_TABLES_H
-
-HB_BEGIN_DECLS
-
-
-static hb_codepoint_t
-hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data,
- hb_codepoint_t unicode,
- hb_codepoint_t variation_selector)
-{
- FT_Face ft_face = (FT_Face) user_data;
-
-#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
- if (unlikely (variation_selector)) {
- hb_codepoint_t glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
- if (glyph)
- return glyph;
- }
-#endif
-
- return FT_Get_Char_Index (ft_face, unicode);
-}
-
-static void
-hb_ft_get_glyph_advance (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data,
- hb_codepoint_t glyph,
- hb_position_t *x_advance,
- hb_position_t *y_advance)
-{
- FT_Face ft_face = (FT_Face) user_data;
- int load_flags = FT_LOAD_DEFAULT;
-
- /* TODO: load_flags, embolden, etc */
-
- if (likely (!FT_Load_Glyph (ft_face, glyph, load_flags)))
- {
- *x_advance = ft_face->glyph->advance.x;
- *y_advance = ft_face->glyph->advance.y;
- }
-}
-
-static void
-hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents)
-{
- FT_Face ft_face = (FT_Face) user_data;
- int load_flags = FT_LOAD_DEFAULT;
-
- /* TODO: load_flags, embolden, etc */
-
- if (likely (!FT_Load_Glyph (ft_face, glyph, load_flags)))
- {
- /* XXX: A few negations should be in order here, not sure. */
- extents->x_bearing = ft_face->glyph->metrics.horiBearingX;
- extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
- extents->width = ft_face->glyph->metrics.width;
- extents->height = ft_face->glyph->metrics.height;
- }
-}
-
-static hb_bool_t
-hb_ft_get_contour_point (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data,
- unsigned int point_index,
- hb_codepoint_t glyph,
- hb_position_t *x,
- hb_position_t *y)
-{
- FT_Face ft_face = (FT_Face) user_data;
- int load_flags = FT_LOAD_DEFAULT;
-
- /* TODO: load_flags, embolden, etc */
-
- if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
- return FALSE;
-
- if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
- return FALSE;
-
- if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
- return FALSE;
-
- *x = ft_face->glyph->outline.points[point_index].x;
- *y = ft_face->glyph->outline.points[point_index].y;
-
- return TRUE;
-}
-
-static hb_position_t
-hb_ft_get_kerning (hb_font_t *font HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- const void *user_data,
- hb_codepoint_t first_glyph,
- hb_codepoint_t second_glyph)
-{
- FT_Face ft_face = (FT_Face) user_data;
- FT_Vector kerning;
-
- /* TODO: Kern type? */
- if (FT_Get_Kerning (ft_face, first_glyph, second_glyph, FT_KERNING_DEFAULT, &kerning))
- return 0;
-
- return kerning.x;
-}
-
-static hb_font_funcs_t ft_ffuncs = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
- TRUE, /* immutable */
- {
- hb_ft_get_glyph,
- hb_ft_get_glyph_advance,
- hb_ft_get_glyph_extents,
- hb_ft_get_contour_point,
- hb_ft_get_kerning
- }
-};
-
-hb_font_funcs_t *
-hb_ft_get_font_funcs (void)
-{
- return &ft_ffuncs;
-}
-
-
-static hb_blob_t *
-get_table (hb_tag_t tag, void *user_data)
-{
- FT_Face ft_face = (FT_Face) user_data;
- FT_Byte *buffer;
- FT_ULong length = 0;
- FT_Error error;
-
- if (unlikely (tag == HB_TAG_NONE))
- return NULL;
-
- error = FT_Load_Sfnt_Table (ft_face, tag, 0, NULL, &length);
- if (error)
- return NULL;
-
- /* TODO Use FT_Memory? */
- buffer = (FT_Byte *) malloc (length);
- if (buffer == NULL)
- return NULL;
-
- error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
- if (error)
- return NULL;
-
- return hb_blob_create ((const char *) buffer, length,
- HB_MEMORY_MODE_WRITABLE,
- free, buffer);
-}
-
-
-hb_face_t *
-hb_ft_face_create (FT_Face ft_face,
- hb_destroy_func_t destroy)
-{
- hb_face_t *face;
-
- if (ft_face->stream->read == NULL) {
- hb_blob_t *blob;
-
- blob = hb_blob_create ((const char *) ft_face->stream->base,
- (unsigned int) ft_face->stream->size,
- /* TODO: Check FT_FACE_FLAG_EXTERNAL_STREAM? */
- HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
- destroy, ft_face);
- face = hb_face_create_for_data (blob, ft_face->face_index);
- hb_blob_destroy (blob);
- } else {
- face = hb_face_create_for_tables (get_table, destroy, ft_face);
- }
-
- return face;
-}
-
-static void
-hb_ft_face_finalize (FT_Face ft_face)
-{
- hb_face_destroy ((hb_face_t *) ft_face->generic.data);
-}
-
-hb_face_t *
-hb_ft_face_create_cached (FT_Face ft_face)
-{
- if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Generic_Finalizer) hb_ft_face_finalize))
- {
- if (ft_face->generic.finalizer)
- ft_face->generic.finalizer (ft_face);
-
- ft_face->generic.data = hb_ft_face_create (ft_face, NULL);
- ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
- }
-
- return hb_face_reference ((hb_face_t *) ft_face->generic.data);
-}
-
-
-hb_font_t *
-hb_ft_font_create (FT_Face ft_face,
- hb_destroy_func_t destroy)
-{
- hb_font_t *font;
-
- font = hb_font_create ();
- hb_font_set_funcs (font,
- hb_ft_get_font_funcs (),
- destroy, ft_face);
- hb_font_set_scale (font,
- ((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM) >> 16,
- ((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM) >> 16);
- hb_font_set_ppem (font,
- ft_face->size->metrics.x_ppem,
- ft_face->size->metrics.y_ppem);
-
- return font;
-}
-
-
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-ft.cc b/third_party/harfbuzz-ng/src/hb-ft.cc
new file mode 100644
index 0000000..23c2cc0
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ft.cc
@@ -0,0 +1,439 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2009 Keith Stribley
+ *
+ * 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ */
+
+#include "hb-private.hh"
+
+#include "hb-ft.h"
+
+#include "hb-font-private.hh"
+
+#include FT_ADVANCES_H
+#include FT_TRUETYPE_TABLES_H
+
+
+
+#ifndef HB_DEBUG_FT
+#define HB_DEBUG_FT (HB_DEBUG+0)
+#endif
+
+
+/* TODO:
+ *
+ * In general, this file does a fine job of what it's supposed to do.
+ * There are, however, things that need more work:
+ *
+ * - We don't handle any load_flags. That definitely has API implications. :(
+ * I believe hb_ft_font_create() should take load_flags input.
+ * In particular, FT_Get_Advance() without the NO_HINTING flag seems to be
+ * buggy.
+ *
+ * - We don't handle / allow for emboldening / obliqueing.
+ *
+ * - Rounding, etc?
+ *
+ * - In the future, we should add constructors to create fonts in font space.
+ *
+ * - I believe transforms are not correctly implemented. FreeType does not
+ * provide any API to get to the transform/delta set on the face. :(
+ *
+ * - Always use FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH?
+ */
+
+
+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)
+
+{
+ FT_Face ft_face = (FT_Face) font_data;
+
+#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
+ if (unlikely (variation_selector)) {
+ *glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
+ if (*glyph)
+ return TRUE;
+ }
+#endif
+
+ *glyph = FT_Get_Char_Index (ft_face, unicode);
+ return *glyph != 0;
+}
+
+static hb_position_t
+hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
+ FT_Fixed v;
+
+ if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
+ return 0;
+
+ return v >> 10;
+}
+
+static hb_position_t
+hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOUT;
+ FT_Fixed v;
+
+ if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
+ return 0;
+
+ /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
+ * have a Y growing upward. Hence the extra negation. */
+ return -v >> 10;
+}
+
+static hb_bool_t
+hb_ft_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph HB_UNUSED,
+ hb_position_t *x HB_UNUSED,
+ hb_position_t *y HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ /* We always work in the horizontal coordinates. */
+ return TRUE;
+}
+
+static hb_bool_t
+hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+ return FALSE;
+
+ /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
+ * have a Y growing upward. Hence the extra negation. */
+ *x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX;
+ *y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
+
+ return TRUE;
+}
+
+static hb_position_t
+hb_ft_get_glyph_h_kerning (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t left_glyph,
+ hb_codepoint_t right_glyph,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ FT_Vector kerningv;
+
+ if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, FT_KERNING_DEFAULT, &kerningv))
+ return 0;
+
+ return kerningv.x;
+}
+
+static hb_position_t
+hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t top_glyph HB_UNUSED,
+ hb_codepoint_t bottom_glyph HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ /* FreeType API doesn't support vertical kerning */
+ return 0;
+}
+
+static hb_bool_t
+hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+ return FALSE;
+
+ extents->x_bearing = ft_face->glyph->metrics.horiBearingX;
+ extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
+ extents->width = ft_face->glyph->metrics.width;
+ extents->height = ft_face->glyph->metrics.height;
+ return TRUE;
+}
+
+static hb_bool_t
+hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ unsigned int point_index,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ FT_Face ft_face = (FT_Face) font_data;
+ int load_flags = FT_LOAD_DEFAULT;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+ return FALSE;
+
+ if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
+ return FALSE;
+
+ if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
+ return FALSE;
+
+ *x = ft_face->glyph->outline.points[point_index].x;
+ *y = ft_face->glyph->outline.points[point_index].y;
+
+ return TRUE;
+}
+
+static hb_font_funcs_t ft_ffuncs = {
+ HB_OBJECT_HEADER_STATIC,
+
+ TRUE, /* immutable */
+
+ {
+ hb_ft_get_glyph,
+ hb_ft_get_glyph_h_advance,
+ hb_ft_get_glyph_v_advance,
+ hb_ft_get_glyph_h_origin,
+ hb_ft_get_glyph_v_origin,
+ hb_ft_get_glyph_h_kerning,
+ hb_ft_get_glyph_v_kerning,
+ hb_ft_get_glyph_extents,
+ hb_ft_get_glyph_contour_point,
+ }
+};
+
+static hb_font_funcs_t *
+_hb_ft_get_font_funcs (void)
+{
+ return &ft_ffuncs;
+}
+
+
+static hb_blob_t *
+reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
+{
+ FT_Face ft_face = (FT_Face) user_data;
+ FT_Byte *buffer;
+ FT_ULong length = 0;
+ FT_Error error;
+
+ /* Note: FreeType like HarfBuzz uses the NONE tag for fetching the entire blob */
+
+ error = FT_Load_Sfnt_Table (ft_face, tag, 0, NULL, &length);
+ if (error)
+ return NULL;
+
+ buffer = (FT_Byte *) malloc (length);
+ if (buffer == NULL)
+ return NULL;
+
+ error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
+ if (error)
+ return NULL;
+
+ return hb_blob_create ((const char *) buffer, length,
+ HB_MEMORY_MODE_WRITABLE,
+ buffer, free);
+}
+
+
+hb_face_t *
+hb_ft_face_create (FT_Face ft_face,
+ hb_destroy_func_t destroy)
+{
+ hb_face_t *face;
+
+ if (ft_face->stream->read == NULL) {
+ hb_blob_t *blob;
+
+ blob = hb_blob_create ((const char *) ft_face->stream->base,
+ (unsigned int) ft_face->stream->size,
+ /* TODO: We assume that it's mmap()'ed, but FreeType code
+ * suggests that there are cases we reach here but font is
+ * not mmapped. For example, when mmap() fails. No idea
+ * how to deal with it better here. */
+ HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
+ ft_face, destroy);
+ face = hb_face_create (blob, ft_face->face_index);
+ hb_blob_destroy (blob);
+ } else {
+ face = hb_face_create_for_tables (reference_table, ft_face, destroy);
+ }
+
+ hb_face_set_index (face, ft_face->face_index);
+ hb_face_set_upem (face, ft_face->units_per_EM);
+
+ return face;
+}
+
+static void
+hb_ft_face_finalize (FT_Face ft_face)
+{
+ hb_face_destroy ((hb_face_t *) ft_face->generic.data);
+}
+
+hb_face_t *
+hb_ft_face_create_cached (FT_Face ft_face)
+{
+ if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Generic_Finalizer) hb_ft_face_finalize))
+ {
+ if (ft_face->generic.finalizer)
+ ft_face->generic.finalizer (ft_face);
+
+ ft_face->generic.data = hb_ft_face_create (ft_face, NULL);
+ ft_face->generic.finalizer = (FT_Generic_Finalizer) hb_ft_face_finalize;
+ }
+
+ return hb_face_reference ((hb_face_t *) ft_face->generic.data);
+}
+
+static void
+_do_nothing (void)
+{
+}
+
+
+hb_font_t *
+hb_ft_font_create (FT_Face ft_face,
+ hb_destroy_func_t destroy)
+{
+ hb_font_t *font;
+ hb_face_t *face;
+
+ face = hb_ft_face_create (ft_face, destroy);
+ font = hb_font_create (face);
+ hb_face_destroy (face);
+ hb_font_set_funcs (font,
+ _hb_ft_get_font_funcs (),
+ ft_face, (hb_destroy_func_t) _do_nothing);
+ hb_font_set_scale (font,
+ ((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM) >> 16,
+ ((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM) >> 16);
+ hb_font_set_ppem (font,
+ ft_face->size->metrics.x_ppem,
+ ft_face->size->metrics.y_ppem);
+
+ return font;
+}
+
+
+
+
+static FT_Library ft_library;
+static hb_bool_t ft_library_initialized;
+static struct ft_library_destructor {
+ ~ft_library_destructor (void) {
+ if (ft_library)
+ FT_Done_FreeType (ft_library);
+ }
+} static_ft_library_destructor;
+
+static FT_Library
+_get_ft_library (void)
+{
+ if (unlikely (!ft_library_initialized)) {
+ FT_Init_FreeType (&ft_library);
+ ft_library_initialized = TRUE;
+ }
+
+ return ft_library;
+}
+
+static void
+_release_blob (FT_Face ft_face)
+{
+ hb_blob_destroy ((hb_blob_t *) ft_face->generic.data);
+}
+
+void
+hb_ft_font_set_funcs (hb_font_t *font)
+{
+ hb_blob_t *blob = hb_face_reference_blob (font->face);
+ unsigned int blob_length;
+ const char *blob_data = hb_blob_get_data (blob, &blob_length);
+ if (unlikely (!blob_length))
+ DEBUG_MSG (FT, font, "Font face has empty blob");
+
+ FT_Face ft_face = NULL;
+ FT_Error err = FT_New_Memory_Face (_get_ft_library (),
+ (const FT_Byte *) blob_data,
+ blob_length,
+ hb_face_get_index (font->face),
+ &ft_face);
+
+ if (unlikely (err)) {
+ hb_blob_destroy (blob);
+ DEBUG_MSG (FT, font, "Font face FT_New_Memory_Face() failed");
+ return;
+ }
+
+ FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
+
+ FT_Set_Char_Size (ft_face,
+ font->x_scale, font->y_scale,
+ font->x_ppem * 72 * 64 / font->x_scale,
+ font->y_ppem * 72 * 64 / font->y_scale);
+
+ ft_face->generic.data = blob;
+ ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
+
+ hb_font_set_funcs (font,
+ _hb_ft_get_font_funcs (),
+ ft_face,
+ (hb_destroy_func_t) FT_Done_Face);
+}
+
+FT_Face
+hb_ft_font_get_face (hb_font_t *font)
+{
+ if (font->destroy == (hb_destroy_func_t) FT_Done_Face ||
+ font->destroy == (hb_destroy_func_t) _do_nothing)
+ return (FT_Face) font->user_data;
+
+ return NULL;
+}
diff --git a/third_party/harfbuzz-ng/src/hb-ft.h b/third_party/harfbuzz-ng/src/hb-ft.h
index be5c854..c1772ac 100644
--- a/third_party/harfbuzz-ng/src/hb-ft.h
+++ b/third_party/harfbuzz-ng/src/hb-ft.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -36,15 +36,12 @@
HB_BEGIN_DECLS
-
-hb_font_funcs_t *
-hb_ft_get_font_funcs (void);
+/* Note: FreeType is not thread-safe. Hence, these functions are not either. */
hb_face_t *
hb_ft_face_create (FT_Face ft_face,
hb_destroy_func_t destroy);
-/* Note: This function is not thread-safe */
hb_face_t *
hb_ft_face_create_cached (FT_Face ft_face);
@@ -53,6 +50,15 @@ hb_ft_font_create (FT_Face ft_face,
hb_destroy_func_t destroy);
+
+/* Makes an hb_font_t use FreeType internally to implement font functions. */
+void
+hb_ft_font_set_funcs (hb_font_t *font);
+
+FT_Face
+hb_ft_font_get_face (hb_font_t *font);
+
+
HB_END_DECLS
#endif /* HB_FT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-glib.c b/third_party/harfbuzz-ng/src/hb-glib.c
deleted file mode 100644
index c548fa6..0000000
--- a/third_party/harfbuzz-ng/src/hb-glib.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2009 Red Hat, 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.h"
-
-#include "hb-glib.h"
-
-#include "hb-unicode-private.h"
-
-#include <glib.h>
-
-HB_BEGIN_DECLS
-
-
-static hb_codepoint_t hb_glib_get_mirroring (hb_codepoint_t unicode) { g_unichar_get_mirror_char (unicode, &unicode); return unicode; }
-static hb_category_t hb_glib_get_general_category (hb_codepoint_t unicode) { return g_unichar_type (unicode); }
-static hb_script_t hb_glib_get_script (hb_codepoint_t unicode) { return g_unichar_get_script (unicode); }
-static unsigned int hb_glib_get_combining_class (hb_codepoint_t unicode) { return g_unichar_combining_class (unicode); }
-static unsigned int hb_glib_get_eastasian_width (hb_codepoint_t unicode) { return g_unichar_iswide (unicode); }
-
-
-static hb_unicode_funcs_t glib_ufuncs = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
- TRUE, /* immutable */
- {
- hb_glib_get_general_category,
- hb_glib_get_combining_class,
- hb_glib_get_mirroring,
- hb_glib_get_script,
- hb_glib_get_eastasian_width
- }
-};
-
-hb_unicode_funcs_t *
-hb_glib_get_unicode_funcs (void)
-{
- return &glib_ufuncs;
-}
-
-
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-glib.cc b/third_party/harfbuzz-ng/src/hb-glib.cc
new file mode 100644
index 0000000..f990988
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-glib.cc
@@ -0,0 +1,349 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2011 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-private.hh"
+
+#include "hb-glib.h"
+
+#include "hb-unicode-private.hh"
+
+
+#if !GLIB_CHECK_VERSION(2,29,14)
+static const hb_script_t
+glib_script_to_script[] =
+{
+ HB_SCRIPT_COMMON,
+ HB_SCRIPT_INHERITED,
+ HB_SCRIPT_ARABIC,
+ HB_SCRIPT_ARMENIAN,
+ HB_SCRIPT_BENGALI,
+ HB_SCRIPT_BOPOMOFO,
+ HB_SCRIPT_CHEROKEE,
+ HB_SCRIPT_COPTIC,
+ HB_SCRIPT_CYRILLIC,
+ HB_SCRIPT_DESERET,
+ HB_SCRIPT_DEVANAGARI,
+ HB_SCRIPT_ETHIOPIC,
+ HB_SCRIPT_GEORGIAN,
+ HB_SCRIPT_GOTHIC,
+ HB_SCRIPT_GREEK,
+ HB_SCRIPT_GUJARATI,
+ HB_SCRIPT_GURMUKHI,
+ HB_SCRIPT_HAN,
+ HB_SCRIPT_HANGUL,
+ HB_SCRIPT_HEBREW,
+ HB_SCRIPT_HIRAGANA,
+ HB_SCRIPT_KANNADA,
+ HB_SCRIPT_KATAKANA,
+ HB_SCRIPT_KHMER,
+ HB_SCRIPT_LAO,
+ HB_SCRIPT_LATIN,
+ HB_SCRIPT_MALAYALAM,
+ HB_SCRIPT_MONGOLIAN,
+ HB_SCRIPT_MYANMAR,
+ HB_SCRIPT_OGHAM,
+ HB_SCRIPT_OLD_ITALIC,
+ HB_SCRIPT_ORIYA,
+ HB_SCRIPT_RUNIC,
+ HB_SCRIPT_SINHALA,
+ HB_SCRIPT_SYRIAC,
+ HB_SCRIPT_TAMIL,
+ HB_SCRIPT_TELUGU,
+ HB_SCRIPT_THAANA,
+ HB_SCRIPT_THAI,
+ HB_SCRIPT_TIBETAN,
+ HB_SCRIPT_CANADIAN_ABORIGINAL,
+ HB_SCRIPT_YI,
+ HB_SCRIPT_TAGALOG,
+ HB_SCRIPT_HANUNOO,
+ HB_SCRIPT_BUHID,
+ HB_SCRIPT_TAGBANWA,
+
+ /* Unicode-4.0 additions */
+ HB_SCRIPT_BRAILLE,
+ HB_SCRIPT_CYPRIOT,
+ HB_SCRIPT_LIMBU,
+ HB_SCRIPT_OSMANYA,
+ HB_SCRIPT_SHAVIAN,
+ HB_SCRIPT_LINEAR_B,
+ HB_SCRIPT_TAI_LE,
+ HB_SCRIPT_UGARITIC,
+
+ /* Unicode-4.1 additions */
+ HB_SCRIPT_NEW_TAI_LUE,
+ HB_SCRIPT_BUGINESE,
+ HB_SCRIPT_GLAGOLITIC,
+ HB_SCRIPT_TIFINAGH,
+ HB_SCRIPT_SYLOTI_NAGRI,
+ HB_SCRIPT_OLD_PERSIAN,
+ HB_SCRIPT_KHAROSHTHI,
+
+ /* Unicode-5.0 additions */
+ HB_SCRIPT_UNKNOWN,
+ HB_SCRIPT_BALINESE,
+ HB_SCRIPT_CUNEIFORM,
+ HB_SCRIPT_PHOENICIAN,
+ HB_SCRIPT_PHAGS_PA,
+ HB_SCRIPT_NKO,
+
+ /* Unicode-5.1 additions */
+ HB_SCRIPT_KAYAH_LI,
+ HB_SCRIPT_LEPCHA,
+ HB_SCRIPT_REJANG,
+ HB_SCRIPT_SUNDANESE,
+ HB_SCRIPT_SAURASHTRA,
+ HB_SCRIPT_CHAM,
+ HB_SCRIPT_OL_CHIKI,
+ HB_SCRIPT_VAI,
+ HB_SCRIPT_CARIAN,
+ HB_SCRIPT_LYCIAN,
+ HB_SCRIPT_LYDIAN,
+
+ /* Unicode-5.2 additions */
+ HB_SCRIPT_AVESTAN,
+ HB_SCRIPT_BAMUM,
+ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS,
+ HB_SCRIPT_IMPERIAL_ARAMAIC,
+ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI,
+ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN,
+ HB_SCRIPT_JAVANESE,
+ HB_SCRIPT_KAITHI,
+ HB_SCRIPT_TAI_THAM,
+ HB_SCRIPT_LISU,
+ HB_SCRIPT_MEETEI_MAYEK,
+ HB_SCRIPT_OLD_SOUTH_ARABIAN,
+ HB_SCRIPT_OLD_TURKIC,
+ HB_SCRIPT_SAMARITAN,
+ HB_SCRIPT_TAI_VIET,
+
+ /* Unicode-6.0 additions */
+ HB_SCRIPT_BATAK,
+ HB_SCRIPT_BRAHMI,
+ HB_SCRIPT_MANDAIC
+};
+#endif
+
+hb_script_t
+hb_glib_script_to_script (GUnicodeScript script)
+{
+#if GLIB_CHECK_VERSION(2,29,14)
+ return (hb_script_t) g_unicode_script_to_iso15924 (script);
+#else
+ if (likely ((unsigned int) script < ARRAY_LENGTH (glib_script_to_script)))
+ return glib_script_to_script[script];
+
+ if (unlikely (script == G_UNICODE_SCRIPT_INVALID_CODE))
+ return HB_SCRIPT_INVALID;
+
+ return HB_SCRIPT_UNKNOWN;
+#endif
+}
+
+GUnicodeScript
+hb_glib_script_from_script (hb_script_t script)
+{
+#if GLIB_CHECK_VERSION(2,29,14)
+ return g_unicode_script_from_iso15924 (script);
+#else
+ unsigned int count = ARRAY_LENGTH (glib_script_to_script);
+ for (unsigned int i = 0; i < count; i++)
+ if (glib_script_to_script[i] == script)
+ return (GUnicodeScript) i;
+
+ if (unlikely (script == HB_SCRIPT_INVALID))
+ return G_UNICODE_SCRIPT_INVALID_CODE;
+
+ return G_UNICODE_SCRIPT_UNKNOWN;
+#endif
+}
+
+
+static unsigned int
+hb_glib_unicode_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+
+{
+ return g_unichar_combining_class (unicode);
+}
+
+static unsigned int
+hb_glib_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+{
+ return g_unichar_iswide (unicode) ? 2 : 1;
+}
+
+static hb_unicode_general_category_t
+hb_glib_unicode_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+
+{
+ /* hb_unicode_general_category_t and GUnicodeType are identical */
+ return (hb_unicode_general_category_t) g_unichar_type (unicode);
+}
+
+static hb_codepoint_t
+hb_glib_unicode_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+{
+ g_unichar_get_mirror_char (unicode, &unicode);
+ return unicode;
+}
+
+static hb_script_t
+hb_glib_unicode_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+{
+ return hb_glib_script_to_script (g_unichar_get_script (unicode));
+}
+
+static hb_bool_t
+hb_glib_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab,
+ void *user_data HB_UNUSED)
+{
+#if GLIB_CHECK_VERSION(2,29,12)
+ return g_unichar_compose (a, b, ab);
+#endif
+
+ /* We don't ifdef-out the fallback code such that compiler always
+ * sees it and makes sure it's compilable. */
+
+ if (!a || !b)
+ return FALSE;
+
+ gchar utf8[12];
+ gchar *normalized;
+ gint len;
+ hb_bool_t ret;
+
+ len = g_unichar_to_utf8 (a, utf8);
+ len += g_unichar_to_utf8 (b, utf8 + len);
+ normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFC);
+ len = g_utf8_strlen (normalized, -1);
+ if (unlikely (!len))
+ return FALSE;
+
+ if (len == 1) {
+ *ab = g_utf8_get_char (normalized);
+ ret = TRUE;
+ } else {
+ ret = FALSE;
+ }
+
+ g_free (normalized);
+ return ret;
+}
+
+static hb_bool_t
+hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b,
+ void *user_data HB_UNUSED)
+{
+#if GLIB_CHECK_VERSION(2,29,12)
+ return g_unichar_decompose (ab, a, b);
+#endif
+
+ /* We don't ifdef-out the fallback code such that compiler always
+ * sees it and makes sure it's compilable. */
+
+ gchar utf8[6];
+ gchar *normalized;
+ gint len;
+ hb_bool_t ret;
+
+ len = g_unichar_to_utf8 (ab, utf8);
+ normalized = g_utf8_normalize (utf8, len, G_NORMALIZE_NFD);
+ len = g_utf8_strlen (normalized, -1);
+ if (unlikely (!len))
+ return FALSE;
+
+ if (len == 1) {
+ *a = g_utf8_get_char (normalized);
+ *b = 0;
+ ret = *a != ab;
+ } else if (len == 2) {
+ *a = g_utf8_get_char (normalized);
+ *b = g_utf8_get_char (g_utf8_next_char (normalized));
+ /* Here's the ugly part: if ab decomposes to a single character and
+ * that character decomposes again, we have to detect that and undo
+ * the second part :-(. */
+ gchar *recomposed = g_utf8_normalize (normalized, -1, G_NORMALIZE_NFC);
+ hb_codepoint_t c = g_utf8_get_char (recomposed);
+ if (c != ab && c != *a) {
+ *a = c;
+ *b = 0;
+ }
+ g_free (recomposed);
+ ret = TRUE;
+ } else {
+ /* If decomposed to more than two characters, take the last one,
+ * and recompose the rest to get the first component. */
+ gchar *end = g_utf8_offset_to_pointer (normalized, len - 1);
+ gchar *recomposed;
+ *b = g_utf8_get_char (end);
+ recomposed = g_utf8_normalize (normalized, end - normalized, G_NORMALIZE_NFC);
+ /* We expect that recomposed has exactly one character now. */
+ *a = g_utf8_get_char (recomposed);
+ g_free (recomposed);
+ ret = TRUE;
+ }
+
+ g_free (normalized);
+ return ret;
+}
+
+
+extern HB_INTERNAL hb_unicode_funcs_t _hb_unicode_funcs_glib;
+hb_unicode_funcs_t _hb_glib_unicode_funcs = {
+ HB_OBJECT_HEADER_STATIC,
+
+ NULL, /* parent */
+ TRUE, /* immutable */
+ {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_glib_unicode_##name,
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+ }
+};
+
+hb_unicode_funcs_t *
+hb_glib_get_unicode_funcs (void)
+{
+ return &_hb_glib_unicode_funcs;
+}
+
diff --git a/third_party/harfbuzz-ng/src/hb-glib.h b/third_party/harfbuzz-ng/src/hb-glib.h
index 81ab15d..3bc3ebf 100644
--- a/third_party/harfbuzz-ng/src/hb-glib.h
+++ b/third_party/harfbuzz-ng/src/hb-glib.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -22,16 +23,25 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
#ifndef HB_GLIB_H
#define HB_GLIB_H
#include "hb.h"
+#include <glib.h>
HB_BEGIN_DECLS
+hb_script_t
+hb_glib_script_to_script (GUnicodeScript script);
+
+GUnicodeScript
+hb_glib_script_from_script (hb_script_t script);
+
+
hb_unicode_funcs_t *
hb_glib_get_unicode_funcs (void);
diff --git a/third_party/harfbuzz-ng/src/hb-gobject-enums.cc b/third_party/harfbuzz-ng/src/hb-gobject-enums.cc
new file mode 100644
index 0000000..9d16c85
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-gobject-enums.cc
@@ -0,0 +1,259 @@
+
+/* Generated data (by glib-mkenums) */
+
+/*
+ * Copyright © 2011 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-private.hh"
+
+/* g++ didn't like older gtype.h gcc-only code path. */
+#include <glib.h>
+#if !GLIB_CHECK_VERSION(2,29,16)
+#undef __GNUC__
+#undef __GNUC_MINOR__
+#define __GNUC__ 2
+#define __GNUC_MINOR__ 6
+#endif
+
+#include "hb-gobject.h"
+
+/* enumerations from "hb-blob.h" */
+inline static /* TODO(behdad) disable these for now until we fix them... */
+GType
+hb_memory_mode_t_hb_memory_mode_t_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { HB_MEMORY_MODE_DUPLICATE, "HB_MEMORY_MODE_DUPLICATE", "duplicate" },
+ { HB_MEMORY_MODE_READONLY, "HB_MEMORY_MODE_READONLY", "readonly" },
+ { HB_MEMORY_MODE_WRITABLE, "HB_MEMORY_MODE_WRITABLE", "writable" },
+ { HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, "HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE", "readonly-may-make-writable" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("hb_memory_mode_t"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+/* enumerations from "hb-common.h" */
+inline static /* TODO(behdad) disable these for now until we fix them... */
+GType
+hb_direction_t_hb_direction_t_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { HB_DIRECTION_INVALID, "HB_DIRECTION_INVALID", "invalid" },
+ { HB_DIRECTION_LTR, "HB_DIRECTION_LTR", "ltr" },
+ { HB_DIRECTION_RTL, "HB_DIRECTION_RTL", "rtl" },
+ { HB_DIRECTION_TTB, "HB_DIRECTION_TTB", "ttb" },
+ { HB_DIRECTION_BTT, "HB_DIRECTION_BTT", "btt" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("hb_direction_t"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+inline static /* TODO(behdad) disable these for now until we fix them... */
+GType
+hb_unicode_general_category_t_hb_unicode_general_category_t_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { HB_UNICODE_GENERAL_CATEGORY_CONTROL, "HB_UNICODE_GENERAL_CATEGORY_CONTROL", "control" },
+ { HB_UNICODE_GENERAL_CATEGORY_FORMAT, "HB_UNICODE_GENERAL_CATEGORY_FORMAT", "format" },
+ { HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED, "HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED", "unassigned" },
+ { HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE, "HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE", "private-use" },
+ { HB_UNICODE_GENERAL_CATEGORY_SURROGATE, "HB_UNICODE_GENERAL_CATEGORY_SURROGATE", "surrogate" },
+ { HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER, "HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER", "lowercase-letter" },
+ { HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER, "HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER", "modifier-letter" },
+ { HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER, "HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER", "other-letter" },
+ { HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER, "HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER", "titlecase-letter" },
+ { HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER, "HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER", "uppercase-letter" },
+ { HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK, "HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK", "spacing-mark" },
+ { HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK, "HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK", "enclosing-mark" },
+ { HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK, "HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK", "non-spacing-mark" },
+ { HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER, "HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER", "decimal-number" },
+ { HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER, "HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER", "letter-number" },
+ { HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER, "HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER", "other-number" },
+ { HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION", "connect-punctuation" },
+ { HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION", "dash-punctuation" },
+ { HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION", "close-punctuation" },
+ { HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION", "final-punctuation" },
+ { HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION", "initial-punctuation" },
+ { HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION", "other-punctuation" },
+ { HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION, "HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION", "open-punctuation" },
+ { HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL", "currency-symbol" },
+ { HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL", "modifier-symbol" },
+ { HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL", "math-symbol" },
+ { HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL, "HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL", "other-symbol" },
+ { HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR, "HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR", "line-separator" },
+ { HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR, "HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR", "paragraph-separator" },
+ { HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR, "HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR", "space-separator" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("hb_unicode_general_category_t"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+inline static /* TODO(behdad) disable these for now until we fix them... */
+GType
+hb_script_t_hb_script_t_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { HB_SCRIPT_COMMON, "HB_SCRIPT_COMMON", "common" },
+ { HB_SCRIPT_INHERITED, "HB_SCRIPT_INHERITED", "inherited" },
+ { HB_SCRIPT_ARABIC, "HB_SCRIPT_ARABIC", "arabic" },
+ { HB_SCRIPT_ARMENIAN, "HB_SCRIPT_ARMENIAN", "armenian" },
+ { HB_SCRIPT_BENGALI, "HB_SCRIPT_BENGALI", "bengali" },
+ { HB_SCRIPT_BOPOMOFO, "HB_SCRIPT_BOPOMOFO", "bopomofo" },
+ { HB_SCRIPT_CHEROKEE, "HB_SCRIPT_CHEROKEE", "cherokee" },
+ { HB_SCRIPT_COPTIC, "HB_SCRIPT_COPTIC", "coptic" },
+ { HB_SCRIPT_CYRILLIC, "HB_SCRIPT_CYRILLIC", "cyrillic" },
+ { HB_SCRIPT_DESERET, "HB_SCRIPT_DESERET", "deseret" },
+ { HB_SCRIPT_DEVANAGARI, "HB_SCRIPT_DEVANAGARI", "devanagari" },
+ { HB_SCRIPT_ETHIOPIC, "HB_SCRIPT_ETHIOPIC", "ethiopic" },
+ { HB_SCRIPT_GEORGIAN, "HB_SCRIPT_GEORGIAN", "georgian" },
+ { HB_SCRIPT_GOTHIC, "HB_SCRIPT_GOTHIC", "gothic" },
+ { HB_SCRIPT_GREEK, "HB_SCRIPT_GREEK", "greek" },
+ { HB_SCRIPT_GUJARATI, "HB_SCRIPT_GUJARATI", "gujarati" },
+ { HB_SCRIPT_GURMUKHI, "HB_SCRIPT_GURMUKHI", "gurmukhi" },
+ { HB_SCRIPT_HAN, "HB_SCRIPT_HAN", "han" },
+ { HB_SCRIPT_HANGUL, "HB_SCRIPT_HANGUL", "hangul" },
+ { HB_SCRIPT_HEBREW, "HB_SCRIPT_HEBREW", "hebrew" },
+ { HB_SCRIPT_HIRAGANA, "HB_SCRIPT_HIRAGANA", "hiragana" },
+ { HB_SCRIPT_KANNADA, "HB_SCRIPT_KANNADA", "kannada" },
+ { HB_SCRIPT_KATAKANA, "HB_SCRIPT_KATAKANA", "katakana" },
+ { HB_SCRIPT_KHMER, "HB_SCRIPT_KHMER", "khmer" },
+ { HB_SCRIPT_LAO, "HB_SCRIPT_LAO", "lao" },
+ { HB_SCRIPT_LATIN, "HB_SCRIPT_LATIN", "latin" },
+ { HB_SCRIPT_MALAYALAM, "HB_SCRIPT_MALAYALAM", "malayalam" },
+ { HB_SCRIPT_MONGOLIAN, "HB_SCRIPT_MONGOLIAN", "mongolian" },
+ { HB_SCRIPT_MYANMAR, "HB_SCRIPT_MYANMAR", "myanmar" },
+ { HB_SCRIPT_OGHAM, "HB_SCRIPT_OGHAM", "ogham" },
+ { HB_SCRIPT_OLD_ITALIC, "HB_SCRIPT_OLD_ITALIC", "old-italic" },
+ { HB_SCRIPT_ORIYA, "HB_SCRIPT_ORIYA", "oriya" },
+ { HB_SCRIPT_RUNIC, "HB_SCRIPT_RUNIC", "runic" },
+ { HB_SCRIPT_SINHALA, "HB_SCRIPT_SINHALA", "sinhala" },
+ { HB_SCRIPT_SYRIAC, "HB_SCRIPT_SYRIAC", "syriac" },
+ { HB_SCRIPT_TAMIL, "HB_SCRIPT_TAMIL", "tamil" },
+ { HB_SCRIPT_TELUGU, "HB_SCRIPT_TELUGU", "telugu" },
+ { HB_SCRIPT_THAANA, "HB_SCRIPT_THAANA", "thaana" },
+ { HB_SCRIPT_THAI, "HB_SCRIPT_THAI", "thai" },
+ { HB_SCRIPT_TIBETAN, "HB_SCRIPT_TIBETAN", "tibetan" },
+ { HB_SCRIPT_CANADIAN_ABORIGINAL, "HB_SCRIPT_CANADIAN_ABORIGINAL", "canadian-aboriginal" },
+ { HB_SCRIPT_YI, "HB_SCRIPT_YI", "yi" },
+ { HB_SCRIPT_TAGALOG, "HB_SCRIPT_TAGALOG", "tagalog" },
+ { HB_SCRIPT_HANUNOO, "HB_SCRIPT_HANUNOO", "hanunoo" },
+ { HB_SCRIPT_BUHID, "HB_SCRIPT_BUHID", "buhid" },
+ { HB_SCRIPT_TAGBANWA, "HB_SCRIPT_TAGBANWA", "tagbanwa" },
+ { HB_SCRIPT_BRAILLE, "HB_SCRIPT_BRAILLE", "braille" },
+ { HB_SCRIPT_CYPRIOT, "HB_SCRIPT_CYPRIOT", "cypriot" },
+ { HB_SCRIPT_LIMBU, "HB_SCRIPT_LIMBU", "limbu" },
+ { HB_SCRIPT_OSMANYA, "HB_SCRIPT_OSMANYA", "osmanya" },
+ { HB_SCRIPT_SHAVIAN, "HB_SCRIPT_SHAVIAN", "shavian" },
+ { HB_SCRIPT_LINEAR_B, "HB_SCRIPT_LINEAR_B", "linear-b" },
+ { HB_SCRIPT_TAI_LE, "HB_SCRIPT_TAI_LE", "tai-le" },
+ { HB_SCRIPT_UGARITIC, "HB_SCRIPT_UGARITIC", "ugaritic" },
+ { HB_SCRIPT_NEW_TAI_LUE, "HB_SCRIPT_NEW_TAI_LUE", "new-tai-lue" },
+ { HB_SCRIPT_BUGINESE, "HB_SCRIPT_BUGINESE", "buginese" },
+ { HB_SCRIPT_GLAGOLITIC, "HB_SCRIPT_GLAGOLITIC", "glagolitic" },
+ { HB_SCRIPT_TIFINAGH, "HB_SCRIPT_TIFINAGH", "tifinagh" },
+ { HB_SCRIPT_SYLOTI_NAGRI, "HB_SCRIPT_SYLOTI_NAGRI", "syloti-nagri" },
+ { HB_SCRIPT_OLD_PERSIAN, "HB_SCRIPT_OLD_PERSIAN", "old-persian" },
+ { HB_SCRIPT_KHAROSHTHI, "HB_SCRIPT_KHAROSHTHI", "kharoshthi" },
+ { HB_SCRIPT_UNKNOWN, "HB_SCRIPT_UNKNOWN", "unknown" },
+ { HB_SCRIPT_BALINESE, "HB_SCRIPT_BALINESE", "balinese" },
+ { HB_SCRIPT_CUNEIFORM, "HB_SCRIPT_CUNEIFORM", "cuneiform" },
+ { HB_SCRIPT_PHOENICIAN, "HB_SCRIPT_PHOENICIAN", "phoenician" },
+ { HB_SCRIPT_PHAGS_PA, "HB_SCRIPT_PHAGS_PA", "phags-pa" },
+ { HB_SCRIPT_NKO, "HB_SCRIPT_NKO", "nko" },
+ { HB_SCRIPT_KAYAH_LI, "HB_SCRIPT_KAYAH_LI", "kayah-li" },
+ { HB_SCRIPT_LEPCHA, "HB_SCRIPT_LEPCHA", "lepcha" },
+ { HB_SCRIPT_REJANG, "HB_SCRIPT_REJANG", "rejang" },
+ { HB_SCRIPT_SUNDANESE, "HB_SCRIPT_SUNDANESE", "sundanese" },
+ { HB_SCRIPT_SAURASHTRA, "HB_SCRIPT_SAURASHTRA", "saurashtra" },
+ { HB_SCRIPT_CHAM, "HB_SCRIPT_CHAM", "cham" },
+ { HB_SCRIPT_OL_CHIKI, "HB_SCRIPT_OL_CHIKI", "ol-chiki" },
+ { HB_SCRIPT_VAI, "HB_SCRIPT_VAI", "vai" },
+ { HB_SCRIPT_CARIAN, "HB_SCRIPT_CARIAN", "carian" },
+ { HB_SCRIPT_LYCIAN, "HB_SCRIPT_LYCIAN", "lycian" },
+ { HB_SCRIPT_LYDIAN, "HB_SCRIPT_LYDIAN", "lydian" },
+ { HB_SCRIPT_AVESTAN, "HB_SCRIPT_AVESTAN", "avestan" },
+ { HB_SCRIPT_BAMUM, "HB_SCRIPT_BAMUM", "bamum" },
+ { HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, "HB_SCRIPT_EGYPTIAN_HIEROGLYPHS", "egyptian-hieroglyphs" },
+ { HB_SCRIPT_IMPERIAL_ARAMAIC, "HB_SCRIPT_IMPERIAL_ARAMAIC", "imperial-aramaic" },
+ { HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, "HB_SCRIPT_INSCRIPTIONAL_PAHLAVI", "inscriptional-pahlavi" },
+ { HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, "HB_SCRIPT_INSCRIPTIONAL_PARTHIAN", "inscriptional-parthian" },
+ { HB_SCRIPT_JAVANESE, "HB_SCRIPT_JAVANESE", "javanese" },
+ { HB_SCRIPT_KAITHI, "HB_SCRIPT_KAITHI", "kaithi" },
+ { HB_SCRIPT_LISU, "HB_SCRIPT_LISU", "lisu" },
+ { HB_SCRIPT_MEETEI_MAYEK, "HB_SCRIPT_MEETEI_MAYEK", "meetei-mayek" },
+ { HB_SCRIPT_OLD_SOUTH_ARABIAN, "HB_SCRIPT_OLD_SOUTH_ARABIAN", "old-south-arabian" },
+ { HB_SCRIPT_OLD_TURKIC, "HB_SCRIPT_OLD_TURKIC", "old-turkic" },
+ { HB_SCRIPT_SAMARITAN, "HB_SCRIPT_SAMARITAN", "samaritan" },
+ { HB_SCRIPT_TAI_THAM, "HB_SCRIPT_TAI_THAM", "tai-tham" },
+ { HB_SCRIPT_TAI_VIET, "HB_SCRIPT_TAI_VIET", "tai-viet" },
+ { HB_SCRIPT_BATAK, "HB_SCRIPT_BATAK", "batak" },
+ { HB_SCRIPT_BRAHMI, "HB_SCRIPT_BRAHMI", "brahmi" },
+ { HB_SCRIPT_MANDAIC, "HB_SCRIPT_MANDAIC", "mandaic" },
+ { HB_SCRIPT_INVALID, "HB_SCRIPT_INVALID", "invalid" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("hb_script_t"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+
+/* Generated data ends here */
+
diff --git a/third_party/harfbuzz-ng/src/hb-gobject-enums.cc.tmpl b/third_party/harfbuzz-ng/src/hb-gobject-enums.cc.tmpl
new file mode 100644
index 0000000..05abd89
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-gobject-enums.cc.tmpl
@@ -0,0 +1,74 @@
+/*** BEGIN file-header ***/
+/*
+ * Copyright © 2011 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-private.hh"
+
+/* g++ didn't like older gtype.h gcc-only code path. */
+#include <glib.h>
+#if !GLIB_CHECK_VERSION(2,29,16)
+#undef __GNUC__
+#undef __GNUC_MINOR__
+#define __GNUC__ 2
+#define __GNUC_MINOR__ 6
+#endif
+
+#include "hb-gobject.h"
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+inline static /* TODO(behdad) disable these for now until we fix them... */
+GType
+@enum_name@_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+/*** END value-tail ***/
diff --git a/third_party/harfbuzz-ng/src/hb-gobject-structs.cc b/third_party/harfbuzz-ng/src/hb-gobject-structs.cc
new file mode 100644
index 0000000..cec4854
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-gobject-structs.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2011 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-private.hh"
+
+/* g++ didn't like older gtype.h gcc-only code path. */
+#include <glib.h>
+#if !GLIB_CHECK_VERSION(2,29,16)
+#undef __GNUC__
+#undef __GNUC_MINOR__
+#define __GNUC__ 2
+#define __GNUC_MINOR__ 6
+#endif
+
+#include "hb-gobject.h"
+
+#define _HB_DEFINE_BOXED_TYPE(Name,underscore_name,copy_func,free_func) \
+GType \
+underscore_name##_get_type (void) \
+{ \
+ static volatile gsize type = 0; \
+ if (g_once_init_enter (&type)) { \
+ GType t = g_boxed_type_register_static (g_intern_static_string (#Name), \
+ (GBoxedCopyFunc) copy_func, \
+ (GBoxedFreeFunc) free_func); \
+ g_once_init_leave (&type, t); \
+ } \
+ return type; \
+}
+
+#define HB_DEFINE_BOXED_TYPE(name) \
+ _HB_DEFINE_BOXED_TYPE (hb_##name, hb_gobject_##name, hb_##name##_reference, hb_##name##_destroy);
+
+HB_DEFINE_BOXED_TYPE (buffer)
+HB_DEFINE_BOXED_TYPE (blob)
+HB_DEFINE_BOXED_TYPE (face)
+HB_DEFINE_BOXED_TYPE (font)
+HB_DEFINE_BOXED_TYPE (font_funcs)
+HB_DEFINE_BOXED_TYPE (unicode_funcs)
+
diff --git a/third_party/harfbuzz-ng/src/hb-unicode-private.h b/third_party/harfbuzz-ng/src/hb-gobject.h
index 419404b..25fc941 100644
--- a/third_party/harfbuzz-ng/src/hb-unicode-private.h
+++ b/third_party/harfbuzz-ng/src/hb-gobject.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -21,44 +21,48 @@
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
- * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_UNICODE_PRIVATE_H
-#define HB_UNICODE_PRIVATE_H
+#ifndef HB_GOBJECT_H
+#define HB_GOBJECT_H
-#include "hb-private.h"
-
-#include "hb-unicode.h"
+#include "hb.h"
+#include <glib-object.h>
HB_BEGIN_DECLS
-/*
- * hb_unicode_funcs_t
- */
+/* Objects */
+
+#define HB_GOBJECT_TYPE_BLOB hb_gobject_blob_get_type ()
+GType
+hb_gobject_blob_get_type (void);
+
+#define HB_GOBJECT_TYPE_BUFFER hb_gobject_buffer_get_type ()
+GType
+hb_gobject_buffer_get_type (void);
-struct _hb_unicode_funcs_t {
- hb_reference_count_t ref_count;
+#define HB_GOBJECT_TYPE_FACE hb_gobject_face_get_type ()
+GType
+hb_gobject_face_get_type (void);
- hb_bool_t immutable;
+#define HB_GOBJECT_TYPE_FONT hb_gobject_font_get_type ()
+GType
+hb_gobject_font_get_type (void);
- struct {
- hb_unicode_get_general_category_func_t get_general_category;
- hb_unicode_get_combining_class_func_t get_combining_class;
- hb_unicode_get_mirroring_func_t get_mirroring;
- hb_unicode_get_script_func_t get_script;
- hb_unicode_get_eastasian_width_func_t get_eastasian_width;
- } v;
-};
+#define HB_GOBJECT_TYPE_FONT_FUNCS hb_gobject_font_funcs_get_type ()
+GType
+hb_gobject_font_funcs_get_type (void);
-extern HB_INTERNAL hb_unicode_funcs_t _hb_unicode_funcs_nil;
+#define HB_GOBJECT_TYPE_UNICODE_FUNCS hb_gobject_unicode_funcs_get_type ()
+GType
+hb_gobject_unicode_funcs_get_type (void);
-HB_INTERNAL hb_direction_t
-_hb_script_get_horizontal_direction (hb_script_t script);
+/* Enums */
HB_END_DECLS
-#endif /* HB_UNICODE_PRIVATE_H */
+#endif /* HB_GOBJECT_H */
diff --git a/third_party/harfbuzz-ng/src/hb-graphite.cc b/third_party/harfbuzz-ng/src/hb-graphite.cc
deleted file mode 100644
index 0a8d681..0000000
--- a/third_party/harfbuzz-ng/src/hb-graphite.cc
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2009 Martin Hosken
- * Copyright (C) 2009 SIL International
- *
- * 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.
- */
-
-#include <graphite/GrClient.h>
-#include <graphite/ITextSource.h>
-#include <graphite/GrData.h>
-#include <graphite/GrConstants.h>
-#include <graphite/Segment.h>
-#include "hb-buffer-private.hh"
-#include "hb-font-private.h"
-#include "hb-graphite.h"
-#include <map>
-
-HB_BEGIN_DECLS
-
-
-namespace TtfUtil
-{
-extern int FontAscent(const void *pOS2);
-extern int FontDescent(const void *pOS2);
-extern int DesignUnits(const void *pHead);
-extern bool FontOs2Style(const void *pOS2, bool &fBold, bool &fItalic);
-}
-
-typedef struct _featureSetting {
- unsigned int id;
- int value;
-} featureSetting;
-
-class HbGrBufferTextSrc : public gr::ITextSource
-{
-public:
- HbGrBufferTextSrc(hb_buffer_t *buff, hb_feature_t *feats, unsigned int num_features)
- {
- hb_feature_t *aFeat = feats;
- featureSetting *aNewFeat;
-
- buffer = hb_buffer_reference(buff);
- features = new featureSetting[num_features];
- nFeatures = num_features;
- aNewFeat = features;
- for (unsigned int i = 0; i < num_features; i++, aFeat++, aNewFeat++)
- {
- aNewFeat->id = aFeat->tag;
- aNewFeat->value = aFeat->value;
- }
- };
- ~HbGrBufferTextSrc() { hb_buffer_destroy(buffer); delete[] features; };
- virtual gr::UtfType utfEncodingForm() { return gr::kutf32; };
- virtual size_t getLength() { return buffer->len; };
- virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf32 * prgchBuffer)
- {
- assert(cch <= buffer->len);
- if (cch > buffer->len)
- return 0;
- for (unsigned int i = ichMin; i < ichMin + cch; i++)
- prgchBuffer[i - ichMin] = buffer->info[i].codepoint;
- return (cch - ichMin);
- };
- virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf16 * prgchBuffer) { return 0 ;};
- virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf8 * prgchBuffer) { return 0; };
- virtual bool getRightToLeft(gr::toffset ich)
- { return hb_buffer_get_direction(buffer) == HB_DIRECTION_RTL; };
- virtual unsigned int getDirectionDepth(gr::toffset ich)
- { return hb_buffer_get_direction(buffer) == HB_DIRECTION_RTL ? 1 : 0; };
- virtual float getVerticalOffset(gr::toffset ich) { return 0; };
- virtual gr::isocode getLanguage(gr::toffset ich)
- {
- gr::isocode aLang;
- char *p = (char *)(buffer->language);
- int i;
- for (i = 0; i < 4; i++)
- {
- if (p != NULL)
- aLang.rgch[i] = *p;
- else
- aLang.rgch[i] = 0;
- if (p && *p)
- p++;
- }
- return aLang;
- }
-
- virtual std::pair<gr::toffset, gr::toffset> propertyRange(gr::toffset ich)
- { return std::pair<gr::toffset, gr::toffset>(0, buffer->len); };
- virtual size_t getFontFeatures(gr::toffset ich, gr::FeatureSetting * prgfset)
- {
- featureSetting *aFeat = features;
- for (unsigned int i = 0; i < nFeatures; i++, aFeat++, prgfset++)
- {
- prgfset->id = aFeat->id;
- prgfset->value = aFeat->value;
- }
- return nFeatures;
- }
- virtual bool sameSegment(gr::toffset ich1, gr::toffset ich2) {return true; };
-
-private:
- hb_buffer_t *buffer;
- featureSetting *features;
- unsigned int nFeatures;
-};
-
-class HbGrFont : public gr::Font
-{
-public:
- HbGrFont(hb_font_t *font, hb_face_t *face) : gr::Font()
- { m_font = hb_font_reference(font); m_face = hb_face_reference(face); initfont(); };
- ~HbGrFont()
- {
- std::map<hb_tag_t,hb_blob_t *>::iterator p = m_blobs.begin();
- while (p != m_blobs.end())
- { hb_blob_destroy((p++)->second); }
- hb_font_destroy(m_font);
- hb_face_destroy(m_face);
- };
- HbGrFont (const HbGrFont &font) : gr::Font(font)
- {
- *this = font;
- m_blobs = std::map<hb_tag_t, hb_blob_t *>(font.m_blobs);
- std::map<hb_tag_t,hb_blob_t *>::iterator p=m_blobs.begin();
- while (p != m_blobs.end()) { hb_blob_reference((*p++).second); }
- hb_font_reference(m_font);
- hb_face_reference(m_face);
- };
- virtual HbGrFont *copyThis() { return new HbGrFont(*this); };
- virtual bool bold() { return m_bold; };
- virtual bool italic() { return m_italic; };
- virtual float ascent() { float asc; getFontMetrics(&asc, NULL, NULL); return asc; };
- virtual float descent() { float desc; getFontMetrics(NULL, &desc, NULL); return desc; };
- virtual float height()
- { float asc, desc; getFontMetrics(&asc, &desc, NULL); return (asc + desc); };
- virtual unsigned int getDPIx() { return m_font->x_ppem; };
- virtual unsigned int getDPIy() { return m_font->y_ppem; };
- virtual const void *getTable(gr::fontTableId32 tableID, size_t *pcbsize)
- {
- hb_blob_t *blob;
- std::map<hb_tag_t,hb_blob_t *>::iterator p=m_blobs.find((hb_tag_t)tableID);
- if (p == m_blobs.end())
- {
- blob = hb_face_get_table(m_face, (hb_tag_t)tableID);
- m_blobs[(hb_tag_t)tableID] = blob;
- }
- else
- { blob = p->second; }
-
- const char *res = hb_blob_lock(blob);
- if (pcbsize)
- *pcbsize = hb_blob_get_length(blob);
- hb_blob_unlock(blob);
- return (const void *)res;
- }
-
- virtual void getFontMetrics(float *pAscent, float *pDescent, float *pEmSquare)
- {
- if (pAscent) *pAscent = 1. * m_ascent * m_font->y_ppem / m_emsquare;
- if (pDescent) *pDescent = 1. * m_descent * m_font->y_ppem / m_emsquare;
- if (pEmSquare) *pEmSquare = m_font->x_scale;
- }
- virtual void getGlyphPoint(gr::gid16 glyphID, unsigned int pointNum, gr::Point &pointReturn)
- {
- hb_position_t x, y;
- hb_font_get_contour_point(m_font, m_face, pointNum, glyphID, &x, &y);
- pointReturn.x = (float)x;
- pointReturn.y = (float)y;
- }
-
- virtual void getGlyphMetrics(gr::gid16 glyphID, gr::Rect &boundingBox, gr::Point &advances)
- {
- hb_glyph_metrics_t metrics;
- hb_font_get_glyph_metrics(m_font, m_face, glyphID, &metrics);
- boundingBox.top = (metrics.y_offset + metrics.height);
- boundingBox.bottom = metrics.y_offset;
- boundingBox.left = metrics.x_offset;
- boundingBox.right = (metrics.x_offset + metrics.width);
- advances.x = metrics.x_advance;
- advances.y = metrics.y_advance;
-// fprintf (stderr, "%d: (%d, %d, %d, %d)+(%d, %d)\n", glyphID, metrics.x_offset, metrics.y_offset, metrics.width, metrics.height, metrics.x_advance, metrics.y_advance);
- }
-
-private:
- HB_INTERNAL void initfont();
-
- hb_font_t *m_font;
- hb_face_t *m_face;
- float m_ascent;
- float m_descent;
- float m_emsquare;
- bool m_bold;
- bool m_italic;
- std::map<hb_tag_t, hb_blob_t *> m_blobs;
-};
-
-void HbGrFont::initfont()
-{
- const void *pOS2 = getTable(gr::kttiOs2, NULL);
- const void *pHead = getTable(gr::kttiHead, NULL);
- TtfUtil::FontOs2Style(pOS2, m_bold, m_italic);
- m_ascent = static_cast<float>(TtfUtil::FontAscent(pOS2));
- m_descent = static_cast<float>(TtfUtil::FontDescent(pOS2));
- m_emsquare = static_cast<float>(TtfUtil::DesignUnits(pHead));
-}
-
-void
-hb_graphite_shape (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features,
- unsigned int num_features)
-{
- /* create text source */
- HbGrBufferTextSrc textSrc(buffer, features, num_features);
-
- /* create grfont */
- HbGrFont grfont(font, face);
-
- /* create segment */
- int *firsts;
- bool *flags;
- int numChars;
- int numGlyphs;
- gr::LayoutEnvironment layout;
- std::pair<gr::GlyphIterator, gr::GlyphIterator>glyph_range;
- gr::GlyphIterator iGlyph;
- hb_codepoint_t *glyph_infos, *pGlyph;
- hb_glyph_position_t *pPosition;
- int cGlyph = 0;
- int cChar = 0;
-
- layout.setStartOfLine(0);
- layout.setEndOfLine(0);
- layout.setDumbFallback(true);
- layout.setJustifier(NULL);
- layout.setRightToLeft(false);
-
- gr::RangeSegment pSegment(&grfont, &textSrc, &layout, (gr::toffset)0,
- static_cast<gr::toffset>(buffer->len), (gr::Segment *)NULL);
-
- /* fill in buffer from segment */
- _hb_buffer_clear_output(buffer);
- pSegment.getUniscribeClusters(NULL, 0, &numChars, NULL, 0, &numGlyphs);
- firsts = new int[numChars];
- flags = new bool[numGlyphs];
- glyph_infos = new hb_codepoint_t[numGlyphs];
- hb_buffer_ensure(buffer, numGlyphs);
- pSegment.getUniscribeClusters(firsts, numChars, NULL, flags, numGlyphs, NULL);
- glyph_range = pSegment.glyphs();
- for (pGlyph = glyph_infos, iGlyph = glyph_range.first; iGlyph != glyph_range.second;
- iGlyph++, pGlyph++)
- { *pGlyph = iGlyph->glyphID(); }
-
- while (cGlyph < numGlyphs)
- {
- if (flags[cGlyph])
- {
- int oldcChar = cChar++;
- int oldcGlyph = cGlyph++;
- while (cChar < numChars && firsts[cChar] == firsts[oldcChar]) cChar++;
- while (cGlyph < numGlyphs && !flags[cGlyph]) cGlyph++;
- _hb_buffer_add_output_glyphs(buffer, cChar - oldcChar, cGlyph - oldcGlyph,
- glyph_infos + oldcGlyph, 0xFFFF, 0xFFFF);
- }
- else
- { cGlyph++; } /* This should never happen */
- }
-
- float curradvx = 0., curradvy = 0.;
- for (pPosition = hb_buffer_get_glyph_positions(buffer), iGlyph = glyph_range.first;
- iGlyph != glyph_range.second; pPosition++, iGlyph++)
- {
- pPosition->x_offset = iGlyph->origin() - curradvx;
- pPosition->y_offset = iGlyph->yOffset() - curradvy;
- pPosition->x_advance = pPosition->x_offset + iGlyph->advanceWidth();
- pPosition->y_advance = pPosition->y_offset + iGlyph->advanceHeight();
- if (pPosition->x_advance < 0 && iGlyph->logicalIndex() != iGlyph->attachedClusterBase()->logicalIndex())
- pPosition->x_advance = 0;
- curradvx += pPosition->x_advance;
- curradvy += pPosition->y_advance;
-// fprintf(stderr, "%d@(%f, %f)+(%f, %f)\n", iGlyph->glyphID(), iGlyph->origin(), iGlyph->yOffset(), iGlyph->advanceWidth(), iGlyph->advanceHeight());
- }
-
- delete[] glyph_infos;
- delete[] firsts;
- delete[] flags;
-}
-
-
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-graphite2.cc b/third_party/harfbuzz-ng/src/hb-graphite2.cc
new file mode 100644
index 0000000..0675759
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-graphite2.cc
@@ -0,0 +1,348 @@
+/*
+ * Copyright © 2011 Martin Hosken
+ * Copyright © 2011 SIL International
+ * Copyright © 2011 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-private.hh"
+
+#include "hb-graphite2.h"
+
+#include "hb-buffer-private.hh"
+#include "hb-font-private.hh"
+#include "hb-ot-tag.h"
+
+#include <graphite2/Font.h>
+#include <graphite2/Segment.h>
+
+
+struct hb_gr_cluster_t {
+ unsigned int base_char;
+ unsigned int num_chars;
+ unsigned int base_glyph;
+ unsigned int num_glyphs;
+};
+
+
+typedef struct hb_gr_tablelist_t {
+ hb_blob_t *blob;
+ struct hb_gr_tablelist_t *next;
+ unsigned int tag;
+} hb_gr_tablelist_t;
+
+static struct hb_gr_face_data_t {
+ hb_face_t *face;
+ gr_face *grface;
+ hb_gr_tablelist_t *tlist;
+} _hb_gr_face_data_nil = {NULL, NULL};
+
+static struct hb_gr_font_data_t {
+ gr_font *grfont;
+ gr_face *grface;
+} _hb_gr_font_data_nil = {NULL, NULL};
+
+
+static const void *hb_gr_get_table (const void *data, unsigned int tag, size_t *len)
+{
+ hb_gr_tablelist_t *pl = NULL, *p;
+ hb_gr_face_data_t *face = (hb_gr_face_data_t *) data;
+ hb_gr_tablelist_t *tlist = face->tlist;
+
+ for (p = tlist; p; p = p->next)
+ if (p->tag == tag ) {
+ unsigned int tlen;
+ const char *d = hb_blob_get_data (p->blob, &tlen);
+ *len = tlen;
+ return d;
+ } else
+ pl = p;
+
+ if (!face->face)
+ return NULL;
+ hb_blob_t *blob = hb_face_reference_table (face->face, tag);
+
+ if (!pl || pl->blob)
+ {
+ p = (hb_gr_tablelist_t *) malloc (sizeof (hb_gr_tablelist_t));
+ if (!p) {
+ hb_blob_destroy (blob);
+ return NULL;
+ }
+ p->next = NULL;
+ if (pl)
+ pl->next = p;
+ else
+ face->tlist = p;
+ pl = p;
+ }
+ pl->blob = blob;
+ pl->tag = tag;
+
+ unsigned int tlen;
+ const char *d = hb_blob_get_data (blob, &tlen);
+ *len = tlen;
+ return d;
+}
+
+static float hb_gr_get_advance (const void *hb_font, unsigned short gid)
+{
+ return hb_font_get_glyph_h_advance ((hb_font_t *) hb_font, gid);
+}
+
+static void _hb_gr_face_data_destroy (void *data)
+{
+ hb_gr_face_data_t *f = (hb_gr_face_data_t *) data;
+ hb_gr_tablelist_t *tlist = f->tlist;
+ while (tlist)
+ {
+ hb_gr_tablelist_t *old = tlist;
+ hb_blob_destroy (tlist->blob);
+ tlist = tlist->next;
+ free (old);
+ }
+ gr_face_destroy (f->grface);
+}
+
+static void _hb_gr_font_data_destroy (void *data)
+{
+ hb_gr_font_data_t *f = (hb_gr_font_data_t *) data;
+
+ gr_font_destroy (f->grfont);
+}
+
+static hb_user_data_key_t hb_gr_data_key;
+
+static hb_gr_face_data_t *
+_hb_gr_face_get_data (hb_face_t *face)
+{
+ hb_gr_face_data_t *data = (hb_gr_face_data_t *) hb_face_get_user_data (face, &hb_gr_data_key);
+ if (likely (data)) return data;
+
+ data = (hb_gr_face_data_t *) calloc (1, sizeof (hb_gr_face_data_t));
+ if (unlikely (!data))
+ return &_hb_gr_face_data_nil;
+
+
+ hb_blob_t *silf_blob = hb_face_reference_table (face, HB_GRAPHITE_TAG_Silf);
+ if (!hb_blob_get_length (silf_blob))
+ {
+ hb_blob_destroy (silf_blob);
+ return &_hb_gr_face_data_nil;
+ }
+
+ data->face = face;
+ data->grface = gr_make_face (data, &hb_gr_get_table, gr_face_default);
+
+
+ if (unlikely (!hb_face_set_user_data (face, &hb_gr_data_key, data,
+ (hb_destroy_func_t) _hb_gr_face_data_destroy,
+ FALSE)))
+ {
+ _hb_gr_face_data_destroy (data);
+ data = (hb_gr_face_data_t *) hb_face_get_user_data (face, &hb_gr_data_key);
+ if (data)
+ return data;
+ else
+ return &_hb_gr_face_data_nil;
+ }
+
+ return data;
+}
+
+static hb_gr_font_data_t *
+_hb_gr_font_get_data (hb_font_t *font)
+{
+ hb_gr_font_data_t *data = (hb_gr_font_data_t *) hb_font_get_user_data (font, &hb_gr_data_key);
+ if (likely (data)) return data;
+
+ data = (hb_gr_font_data_t *) calloc (1, sizeof (hb_gr_font_data_t));
+ if (unlikely (!data))
+ return &_hb_gr_font_data_nil;
+
+
+ hb_blob_t *silf_blob = hb_face_reference_table (font->face, HB_GRAPHITE_TAG_Silf);
+ if (!hb_blob_get_length (silf_blob))
+ {
+ hb_blob_destroy (silf_blob);
+ return &_hb_gr_font_data_nil;
+ }
+
+ data->grface = _hb_gr_face_get_data (font->face)->grface;
+ int scale;
+ hb_font_get_scale (font, &scale, NULL);
+ data->grfont = gr_make_font_with_advance_fn (scale, font, &hb_gr_get_advance, data->grface);
+
+
+ if (unlikely (!hb_font_set_user_data (font, &hb_gr_data_key, data,
+ (hb_destroy_func_t) _hb_gr_font_data_destroy,
+ FALSE)))
+ {
+ _hb_gr_font_data_destroy (data);
+ data = (hb_gr_font_data_t *) hb_font_get_user_data (font, &hb_gr_data_key);
+ if (data)
+ return data;
+ else
+ return &_hb_gr_font_data_nil;
+ }
+
+ return data;
+}
+
+
+hb_bool_t
+hb_graphite_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options)
+{
+
+ buffer->guess_properties ();
+
+ hb_gr_font_data_t *data = _hb_gr_font_get_data (font);
+ if (!data->grface) return FALSE;
+
+ unsigned int charlen;
+ hb_glyph_info_t *bufferi = hb_buffer_get_glyph_infos (buffer, &charlen);
+
+ int success = 0;
+
+ if (!charlen) return TRUE;
+
+ const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
+ const char *lang_end = strchr (lang, '-');
+ int lang_len = lang_end ? lang_end - lang : -1;
+ gr_feature_val *feats = gr_face_featureval_for_lang (data->grface, lang ? hb_tag_from_string (lang, lang_len) : 0);
+
+ while (num_features--)
+ {
+ const gr_feature_ref *fref = gr_face_find_fref (data->grface, features->tag);
+ if (fref)
+ gr_fref_set_feature_value (fref, features->value, feats);
+ features++;
+ }
+
+ unsigned short *gids = NULL;
+ hb_gr_cluster_t *clusters = NULL;
+ gr_segment *seg = NULL;
+ uint32_t *text = NULL;
+ unsigned short *pg;
+ const gr_slot *is;
+ unsigned int ci = 0, ic = 0;
+ float curradvx = 0., curradvy = 0.;
+ unsigned int glyphlen = 0;
+ unsigned int *p;
+
+ text = (uint32_t *) malloc ((charlen + 1) * sizeof (uint32_t));
+ if (!text) goto dieout;
+
+ p = text;
+ for (unsigned int i = 0; i < charlen; ++i)
+ *p++ = bufferi++->codepoint;
+ *p = 0;
+
+ hb_tag_t script_tag[2];
+ hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
+
+ seg = gr_make_seg (data->grfont, data->grface,
+ script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
+ feats,
+ gr_utf32, text, charlen,
+ 2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
+ if (!seg) goto dieout;
+
+ glyphlen = gr_seg_n_slots (seg);
+ clusters = (hb_gr_cluster_t *) calloc (charlen, sizeof (hb_gr_cluster_t));
+ if (!glyphlen || !clusters) goto dieout;
+
+ gids = (uint16_t *) malloc (glyphlen * sizeof (uint16_t));
+ if (!gids) goto dieout;
+
+ pg = gids;
+ for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++)
+ {
+ unsigned int before = gr_slot_before (is);
+ unsigned int after = gr_slot_after (is);
+ *pg = gr_slot_gid (is);
+ pg++;
+ while (clusters[ci].base_char > before && ci)
+ {
+ clusters[ci-1].num_chars += clusters[ci].num_chars;
+ clusters[ci-1].num_glyphs += clusters[ci].num_glyphs;
+ ci--;
+ }
+
+ if (gr_slot_can_insert_before (is) && clusters[ci].num_chars && before >= clusters[ci].base_char + clusters[ci].num_chars)
+ {
+ hb_gr_cluster_t *c = clusters + ci + 1;
+ c->base_char = clusters[ci].base_char + clusters[ci].num_chars;
+ c->num_chars = before - c->base_char;
+ c->base_glyph = ic;
+ c->num_glyphs = 0;
+ ci++;
+ }
+ clusters[ci].num_glyphs++;
+
+ if (clusters[ci].base_char + clusters[ci].num_chars < after + 1)
+ clusters[ci].num_chars = after + 1 - clusters[ci].base_char;
+ }
+ ci++;
+
+ buffer->clear_output ();
+ for (unsigned int i = 0; i < ci; ++i)
+ buffer->replace_glyphs (clusters[i].num_chars, clusters[i].num_glyphs, gids + clusters[i].base_glyph);
+ buffer->swap_buffers ();
+
+ hb_glyph_position_t *pPos;
+ for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg);
+ is; pPos++, is = gr_slot_next_in_segment (is))
+ {
+ pPos->x_offset = gr_slot_origin_X(is) - curradvx;
+ pPos->y_offset = gr_slot_origin_Y(is) - curradvy;
+ pPos->x_advance = gr_slot_advance_X(is, data->grface, data->grfont);
+ pPos->y_advance = gr_slot_advance_Y(is, data->grface, data->grfont);
+// if (pPos->x_advance < 0 && gr_slot_attached_to(is))
+// pPos->x_advance = 0;
+ curradvx += pPos->x_advance;
+ curradvy += pPos->y_advance;
+ }
+ pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx;
+
+ /* TODO(behdad):
+ * This shaper is badly broken with RTL text. It returns glyphs
+ * in the logical order!
+ */
+// if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
+// hb_buffer_reverse (buffer);
+
+ success = 1;
+
+dieout:
+ if (gids) free (gids);
+ if (clusters) free (clusters);
+ if (seg) gr_seg_destroy (seg);
+ if (text) free (text);
+ return success;
+}
diff --git a/third_party/harfbuzz-ng/src/hb-graphite.h b/third_party/harfbuzz-ng/src/hb-graphite2.h
index b5d1176..68bd019 100644
--- a/third_party/harfbuzz-ng/src/hb-graphite.h
+++ b/third_party/harfbuzz-ng/src/hb-graphite2.h
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2009, Martin Hosken
- * Copyright (C) 2009, SIL International
+ * Copyright (C) 2011 Martin Hosken
+ * Copyright (C) 2011 SIL International
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -21,13 +21,12 @@
* 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
*/
-#ifndef HB_GRAPHITE_H
-#define HB_GRAPHITE_H
+#ifndef HB_GRAPHITE2_H
+#define HB_GRAPHITE2_H
+#include "hb-common.h"
#include "hb-shape.h"
HB_BEGIN_DECLS
@@ -35,13 +34,13 @@ HB_BEGIN_DECLS
#define HB_GRAPHITE_TAG_Silf HB_TAG('S','i','l','f')
-void hb_graphite_shape (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features,
- unsigned int num_features);
-
+hb_bool_t
+hb_graphite_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options);
HB_END_DECLS
-#endif /* HB_GRAPHITE_H */
+#endif /* HB_GRAPHITE2_H */
diff --git a/third_party/harfbuzz-ng/src/hb-icu.c b/third_party/harfbuzz-ng/src/hb-icu.c
deleted file mode 100644
index 601ef61..0000000
--- a/third_party/harfbuzz-ng/src/hb-icu.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2009 Keith Stribley
- *
- * 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.h"
-
-#include "hb-icu.h"
-
-#include "hb-unicode-private.h"
-
-#include <unicode/uversion.h>
-#include <unicode/uchar.h>
-#include <unicode/uscript.h>
-
-HB_BEGIN_DECLS
-
-
-static hb_codepoint_t hb_icu_get_mirroring (hb_codepoint_t unicode) { return u_charMirror(unicode); }
-static unsigned int hb_icu_get_combining_class (hb_codepoint_t unicode) { return u_getCombiningClass (unicode); }
-
-static unsigned int
-hb_icu_get_eastasian_width (hb_codepoint_t unicode)
-{
- switch (u_getIntPropertyValue(unicode, UCHAR_EAST_ASIAN_WIDTH))
- {
- case U_EA_WIDE:
- case U_EA_FULLWIDTH:
- return 2;
- case U_EA_NEUTRAL:
- case U_EA_AMBIGUOUS:
- case U_EA_HALFWIDTH:
- case U_EA_NARROW:
- return 1;
- }
- return 1;
-}
-
-static hb_category_t
-hb_icu_get_general_category (hb_codepoint_t unicode)
-{
- switch (u_getIntPropertyValue(unicode, UCHAR_GENERAL_CATEGORY))
- {
- case U_UNASSIGNED: return HB_CATEGORY_UNASSIGNED;
-
- case U_UPPERCASE_LETTER: return HB_CATEGORY_UPPERCASE_LETTER; /* Lu */
- case U_LOWERCASE_LETTER: return HB_CATEGORY_LOWERCASE_LETTER; /* Ll */
- case U_TITLECASE_LETTER: return HB_CATEGORY_TITLECASE_LETTER; /* Lt */
- case U_MODIFIER_LETTER: return HB_CATEGORY_MODIFIER_LETTER; /* Lm */
- case U_OTHER_LETTER: return HB_CATEGORY_OTHER_LETTER; /* Lo */
-
- case U_NON_SPACING_MARK: return HB_CATEGORY_NON_SPACING_MARK; /* Mn */
- case U_ENCLOSING_MARK: return HB_CATEGORY_ENCLOSING_MARK; /* Me */
- case U_COMBINING_SPACING_MARK: return HB_CATEGORY_COMBINING_MARK; /* Mc */
-
- case U_DECIMAL_DIGIT_NUMBER: return HB_CATEGORY_DECIMAL_NUMBER; /* Nd */
- case U_LETTER_NUMBER: return HB_CATEGORY_LETTER_NUMBER; /* Nl */
- case U_OTHER_NUMBER: return HB_CATEGORY_OTHER_NUMBER; /* No */
-
- case U_SPACE_SEPARATOR: return HB_CATEGORY_SPACE_SEPARATOR; /* Zs */
- case U_LINE_SEPARATOR: return HB_CATEGORY_LINE_SEPARATOR; /* Zl */
- case U_PARAGRAPH_SEPARATOR: return HB_CATEGORY_PARAGRAPH_SEPARATOR; /* Zp */
-
- case U_CONTROL_CHAR: return HB_CATEGORY_CONTROL; /* Cc */
- case U_FORMAT_CHAR: return HB_CATEGORY_FORMAT; /* Cf */
- case U_PRIVATE_USE_CHAR: return HB_CATEGORY_PRIVATE_USE; /* Co */
- case U_SURROGATE: return HB_CATEGORY_SURROGATE; /* Cs */
-
-
- case U_DASH_PUNCTUATION: return HB_CATEGORY_DASH_PUNCTUATION; /* Pd */
- case U_START_PUNCTUATION: return HB_CATEGORY_OPEN_PUNCTUATION; /* Ps */
- case U_END_PUNCTUATION: return HB_CATEGORY_CLOSE_PUNCTUATION; /* Pe */
- case U_CONNECTOR_PUNCTUATION: return HB_CATEGORY_CONNECT_PUNCTUATION; /* Pc */
- case U_OTHER_PUNCTUATION: return HB_CATEGORY_OTHER_PUNCTUATION; /* Po */
-
- case U_MATH_SYMBOL: return HB_CATEGORY_MATH_SYMBOL; /* Sm */
- case U_CURRENCY_SYMBOL: return HB_CATEGORY_CURRENCY_SYMBOL; /* Sc */
- case U_MODIFIER_SYMBOL: return HB_CATEGORY_MODIFIER_SYMBOL; /* Sk */
- case U_OTHER_SYMBOL: return HB_CATEGORY_OTHER_SYMBOL; /* So */
-
- case U_INITIAL_PUNCTUATION: return HB_CATEGORY_INITIAL_PUNCTUATION; /* Pi */
- case U_FINAL_PUNCTUATION: return HB_CATEGORY_FINAL_PUNCTUATION; /* Pf */
- }
-
- return HB_CATEGORY_UNASSIGNED;
-}
-
-static hb_script_t
-hb_icu_get_script (hb_codepoint_t unicode)
-{
- UErrorCode status = U_ZERO_ERROR;
- UScriptCode scriptCode = uscript_getScript(unicode, &status);
- switch ((int) scriptCode)
- {
-#define CHECK_ICU_VERSION(major, minor) \
- U_ICU_VERSION_MAJOR_NUM > (major) || (U_ICU_VERSION_MAJOR_NUM == (major) && U_ICU_VERSION_MINOR_NUM >= (minor))
-#define MATCH_SCRIPT(C) case USCRIPT_##C: return HB_SCRIPT_##C
-#define MATCH_SCRIPT2(C1, C2) case USCRIPT_##C1: return HB_SCRIPT_##C2
- MATCH_SCRIPT (INVALID_CODE);
- MATCH_SCRIPT (COMMON); /* Zyyy */
- MATCH_SCRIPT (INHERITED); /* Qaai */
- MATCH_SCRIPT (ARABIC); /* Arab */
- MATCH_SCRIPT (ARMENIAN); /* Armn */
- MATCH_SCRIPT (BENGALI); /* Beng */
- MATCH_SCRIPT (BOPOMOFO); /* Bopo */
- MATCH_SCRIPT (CHEROKEE); /* Cher */
- MATCH_SCRIPT (COPTIC); /* Qaac */
- MATCH_SCRIPT (CYRILLIC); /* Cyrl (Cyrs) */
- MATCH_SCRIPT (DESERET); /* Dsrt */
- MATCH_SCRIPT (DEVANAGARI); /* Deva */
- MATCH_SCRIPT (ETHIOPIC); /* Ethi */
- MATCH_SCRIPT (GEORGIAN); /* Geor (Geon); Geoa) */
- MATCH_SCRIPT (GOTHIC); /* Goth */
- MATCH_SCRIPT (GREEK); /* Grek */
- MATCH_SCRIPT (GUJARATI); /* Gujr */
- MATCH_SCRIPT (GURMUKHI); /* Guru */
- MATCH_SCRIPT (HAN); /* Hani */
- MATCH_SCRIPT (HANGUL); /* Hang */
- MATCH_SCRIPT (HEBREW); /* Hebr */
- MATCH_SCRIPT (HIRAGANA); /* Hira */
- MATCH_SCRIPT (KANNADA); /* Knda */
- MATCH_SCRIPT (KATAKANA); /* Kana */
- MATCH_SCRIPT (KHMER); /* Khmr */
- MATCH_SCRIPT (LAO); /* Laoo */
- MATCH_SCRIPT (LATIN); /* Latn (Latf); Latg) */
- MATCH_SCRIPT (MALAYALAM); /* Mlym */
- MATCH_SCRIPT (MONGOLIAN); /* Mong */
- MATCH_SCRIPT (MYANMAR); /* Mymr */
- MATCH_SCRIPT (OGHAM); /* Ogam */
- MATCH_SCRIPT (OLD_ITALIC); /* Ital */
- MATCH_SCRIPT (ORIYA); /* Orya */
- MATCH_SCRIPT (RUNIC); /* Runr */
- MATCH_SCRIPT (SINHALA); /* Sinh */
- MATCH_SCRIPT (SYRIAC); /* Syrc (Syrj, Syrn); Syre) */
- MATCH_SCRIPT (TAMIL); /* Taml */
- MATCH_SCRIPT (TELUGU); /* Telu */
- MATCH_SCRIPT (THAANA); /* Thaa */
- MATCH_SCRIPT (THAI); /* Thai */
- MATCH_SCRIPT (TIBETAN); /* Tibt */
- MATCH_SCRIPT (CANADIAN_ABORIGINAL);/* Cans */
- MATCH_SCRIPT (YI); /* Yiii */
- MATCH_SCRIPT (TAGALOG); /* Tglg */
- MATCH_SCRIPT (HANUNOO); /* Hano */
- MATCH_SCRIPT (BUHID); /* Buhd */
- MATCH_SCRIPT (TAGBANWA); /* Tagb */
-
- /* Unicode-4.0 additions */
- MATCH_SCRIPT (BRAILLE); /* Brai */
- MATCH_SCRIPT (CYPRIOT); /* Cprt */
- MATCH_SCRIPT (LIMBU); /* Limb */
- MATCH_SCRIPT (OSMANYA); /* Osma */
- MATCH_SCRIPT (SHAVIAN); /* Shaw */
- MATCH_SCRIPT (LINEAR_B); /* Linb */
- MATCH_SCRIPT (TAI_LE); /* Tale */
- MATCH_SCRIPT (UGARITIC); /* Ugar */
-
- /* Unicode-4.1 additions */
- MATCH_SCRIPT (NEW_TAI_LUE); /* Talu */
- MATCH_SCRIPT (BUGINESE); /* Bugi */
- MATCH_SCRIPT (GLAGOLITIC); /* Glag */
- MATCH_SCRIPT (TIFINAGH); /* Tfng */
- MATCH_SCRIPT (SYLOTI_NAGRI); /* Sylo */
- MATCH_SCRIPT (OLD_PERSIAN); /* Xpeo */
- MATCH_SCRIPT (KHAROSHTHI); /* Khar */
-
- /* Unicode-5.0 additions */
- MATCH_SCRIPT (UNKNOWN); /* Zzzz */
- MATCH_SCRIPT (BALINESE); /* Bali */
- MATCH_SCRIPT (CUNEIFORM); /* Xsux */
- MATCH_SCRIPT (PHOENICIAN); /* Phnx */
- MATCH_SCRIPT (PHAGS_PA); /* Phag */
- MATCH_SCRIPT (NKO); /* Nkoo */
-
- /* Unicode-5.1 additions */
- MATCH_SCRIPT (KAYAH_LI); /* Kali */
- MATCH_SCRIPT (LEPCHA); /* Lepc */
- MATCH_SCRIPT (REJANG); /* Rjng */
- MATCH_SCRIPT (SUNDANESE); /* Sund */
- MATCH_SCRIPT (SAURASHTRA); /* Saur */
- MATCH_SCRIPT (CHAM); /* Cham */
- MATCH_SCRIPT (OL_CHIKI); /* Olck */
- MATCH_SCRIPT (VAI); /* Vaii */
- MATCH_SCRIPT (CARIAN); /* Cari */
- MATCH_SCRIPT (LYCIAN); /* Lyci */
- MATCH_SCRIPT (LYDIAN); /* Lydi */
-
- /* Unicode-5.2 additions */
- MATCH_SCRIPT (AVESTAN); /* Avst */
-#if CHECK_ICU_VERSION (4, 4)
- MATCH_SCRIPT (BAMUM); /* Bamu */
-#endif
- MATCH_SCRIPT (EGYPTIAN_HIEROGLYPHS); /* Egyp */
- MATCH_SCRIPT (IMPERIAL_ARAMAIC); /* Armi */
- MATCH_SCRIPT (INSCRIPTIONAL_PAHLAVI); /* Phli */
- MATCH_SCRIPT (INSCRIPTIONAL_PARTHIAN); /* Prti */
- MATCH_SCRIPT (JAVANESE); /* Java */
- MATCH_SCRIPT (KAITHI); /* Kthi */
- MATCH_SCRIPT2(LANNA, TAI_THAM); /* Lana */
-#if CHECK_ICU_VERSION (4, 4)
- MATCH_SCRIPT (LISU); /* Lisu */
-#endif
- MATCH_SCRIPT2(MEITEI_MAYEK, MEETEI_MAYEK);/* Mtei */
-#if CHECK_ICU_VERSION (4, 4)
- MATCH_SCRIPT (OLD_SOUTH_ARABIAN); /* Sarb */
-#endif
- MATCH_SCRIPT2(ORKHON, OLD_TURKIC); /* Orkh */
- MATCH_SCRIPT (SAMARITAN); /* Samr */
- MATCH_SCRIPT (TAI_VIET); /* Tavt */
-
- /* Unicode-6.0 additions */
- MATCH_SCRIPT (BATAK); /* Batk */
- MATCH_SCRIPT (BRAHMI); /* Brah */
- MATCH_SCRIPT2(MANDAEAN, MANDAIC); /* Mand */
-
- }
- return HB_SCRIPT_UNKNOWN;
-}
-
-static hb_unicode_funcs_t icu_ufuncs = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
- TRUE, /* immutable */
- {
- hb_icu_get_general_category,
- hb_icu_get_combining_class,
- hb_icu_get_mirroring,
- hb_icu_get_script,
- hb_icu_get_eastasian_width
- }
-};
-
-hb_unicode_funcs_t *
-hb_icu_get_unicode_funcs (void)
-{
- return &icu_ufuncs;
-}
-
-
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-icu.cc b/third_party/harfbuzz-ng/src/hb-icu.cc
new file mode 100644
index 0000000..5cd0143
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-icu.cc
@@ -0,0 +1,291 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2009 Keith Stribley
+ * Copyright © 2011 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-private.hh"
+
+#include "hb-icu.h"
+
+#include "hb-unicode-private.hh"
+
+#include <unicode/uversion.h>
+#include <unicode/uchar.h>
+#include <unicode/unorm.h>
+#include <unicode/ustring.h>
+
+
+
+hb_script_t
+hb_icu_script_to_script (UScriptCode script)
+{
+ if (unlikely (script == USCRIPT_INVALID_CODE))
+ return HB_SCRIPT_INVALID;
+
+ return hb_script_from_string (uscript_getShortName (script), -1);
+}
+
+UScriptCode
+hb_icu_script_from_script (hb_script_t script)
+{
+ if (unlikely (script == HB_SCRIPT_INVALID))
+ return USCRIPT_INVALID_CODE;
+
+ for (unsigned int i = 0; i < USCRIPT_CODE_LIMIT; i++)
+ if (unlikely (hb_icu_script_to_script ((UScriptCode) i) == script))
+ return (UScriptCode) i;
+
+ return USCRIPT_UNKNOWN;
+}
+
+
+static unsigned int
+hb_icu_unicode_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+
+{
+ return u_getCombiningClass (unicode);
+}
+
+static unsigned int
+hb_icu_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+{
+ switch (u_getIntPropertyValue(unicode, UCHAR_EAST_ASIAN_WIDTH))
+ {
+ case U_EA_WIDE:
+ case U_EA_FULLWIDTH:
+ return 2;
+ case U_EA_NEUTRAL:
+ case U_EA_AMBIGUOUS:
+ case U_EA_HALFWIDTH:
+ case U_EA_NARROW:
+ return 1;
+ }
+ return 1;
+}
+
+static hb_unicode_general_category_t
+hb_icu_unicode_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+{
+ switch (u_getIntPropertyValue(unicode, UCHAR_GENERAL_CATEGORY))
+ {
+ case U_UNASSIGNED: return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
+
+ case U_UPPERCASE_LETTER: return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER;
+ case U_LOWERCASE_LETTER: return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER;
+ case U_TITLECASE_LETTER: return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER;
+ case U_MODIFIER_LETTER: return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER;
+ case U_OTHER_LETTER: return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
+
+ case U_NON_SPACING_MARK: return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK;
+ case U_ENCLOSING_MARK: return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
+ case U_COMBINING_SPACING_MARK: return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK;
+
+ case U_DECIMAL_DIGIT_NUMBER: return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER;
+ case U_LETTER_NUMBER: return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER;
+ case U_OTHER_NUMBER: return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER;
+
+ case U_SPACE_SEPARATOR: return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
+ case U_LINE_SEPARATOR: return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR;
+ case U_PARAGRAPH_SEPARATOR: return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR;
+
+ case U_CONTROL_CHAR: return HB_UNICODE_GENERAL_CATEGORY_CONTROL;
+ case U_FORMAT_CHAR: return HB_UNICODE_GENERAL_CATEGORY_FORMAT;
+ case U_PRIVATE_USE_CHAR: return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE;
+ case U_SURROGATE: return HB_UNICODE_GENERAL_CATEGORY_SURROGATE;
+
+
+ case U_DASH_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION;
+ case U_START_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION;
+ case U_END_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION;
+ case U_CONNECTOR_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION;
+ case U_OTHER_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION;
+
+ case U_MATH_SYMBOL: return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL;
+ case U_CURRENCY_SYMBOL: return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL;
+ case U_MODIFIER_SYMBOL: return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL;
+ case U_OTHER_SYMBOL: return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL;
+
+ case U_INITIAL_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION;
+ case U_FINAL_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION;
+ }
+
+ return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED;
+}
+
+static hb_codepoint_t
+hb_icu_unicode_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+{
+ return u_charMirror(unicode);
+}
+
+static hb_script_t
+hb_icu_unicode_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode,
+ void *user_data HB_UNUSED)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UScriptCode scriptCode = uscript_getScript(unicode, &status);
+
+ if (unlikely (U_FAILURE (status)))
+ return HB_SCRIPT_UNKNOWN;
+
+ return hb_icu_script_to_script (scriptCode);
+}
+
+static hb_bool_t
+hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab,
+ void *user_data HB_UNUSED)
+{
+ if (!a || !b)
+ return FALSE;
+
+ UChar utf16[4], normalized[5];
+ int len;
+ hb_bool_t ret, err;
+ UErrorCode icu_err;
+
+ len = 0;
+ err = FALSE;
+ U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err);
+ if (err) return FALSE;
+ U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err);
+ if (err) return FALSE;
+
+ icu_err = U_ZERO_ERROR;
+ len = unorm_normalize (utf16, len, UNORM_NFC, 0, normalized, ARRAY_LENGTH (normalized), &icu_err);
+ if (U_FAILURE (icu_err))
+ return FALSE;
+ if (u_countChar32 (normalized, len) == 1) {
+ U16_GET_UNSAFE (normalized, 0, *ab);
+ ret = TRUE;
+ } else {
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+static hb_bool_t
+hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b,
+ void *user_data HB_UNUSED)
+{
+ UChar utf16[2], normalized[20];
+ int len;
+ hb_bool_t ret, err;
+ UErrorCode icu_err;
+
+ /* This function is a monster! Maybe it wasn't a good idea adding a
+ * pairwise decompose API... */
+ /* Watchout for the dragons. Err, watchout for macros changing len. */
+
+ len = 0;
+ err = FALSE;
+ U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err);
+ if (err) return FALSE;
+
+ icu_err = U_ZERO_ERROR;
+ len = unorm_normalize (utf16, len, UNORM_NFD, 0, normalized, ARRAY_LENGTH (normalized), &icu_err);
+ if (U_FAILURE (icu_err))
+ return FALSE;
+
+ len = u_countChar32 (normalized, len);
+
+ if (len == 1) {
+ U16_GET_UNSAFE (normalized, 0, *a);
+ *b = 0;
+ ret = *a != ab;
+ } else if (len == 2) {
+ len =0;
+ U16_NEXT_UNSAFE (normalized, len, *a);
+ U16_NEXT_UNSAFE (normalized, len, *b);
+
+ /* Here's the ugly part: if ab decomposes to a single character and
+ * that character decomposes again, we have to detect that and undo
+ * the second part :-(. */
+ UChar recomposed[20];
+ icu_err = U_ZERO_ERROR;
+ unorm_normalize (normalized, len, UNORM_NFC, 0, recomposed, ARRAY_LENGTH (recomposed), &icu_err);
+ if (U_FAILURE (icu_err))
+ return FALSE;
+ hb_codepoint_t c;
+ U16_GET_UNSAFE (recomposed, 0, c);
+ if (c != *a && c != ab) {
+ *a = c;
+ *b = 0;
+ }
+ ret = TRUE;
+ } else {
+ /* If decomposed to more than two characters, take the last one,
+ * and recompose the rest to get the first component. */
+ U16_PREV_UNSAFE (normalized, len, *b);
+ UChar recomposed[20];
+ icu_err = U_ZERO_ERROR;
+ len = unorm_normalize (normalized, len, UNORM_NFC, 0, recomposed, ARRAY_LENGTH (recomposed), &icu_err);
+ if (U_FAILURE (icu_err))
+ return FALSE;
+ /* We expect that recomposed has exactly one character now. */
+ U16_GET_UNSAFE (recomposed, 0, *a);
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+extern HB_INTERNAL hb_unicode_funcs_t _hb_unicode_funcs_icu;
+hb_unicode_funcs_t _hb_icu_unicode_funcs = {
+ HB_OBJECT_HEADER_STATIC,
+
+ NULL, /* parent */
+ TRUE, /* immutable */
+ {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_icu_unicode_##name,
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+ }
+};
+
+hb_unicode_funcs_t *
+hb_icu_get_unicode_funcs (void)
+{
+ return &_hb_icu_unicode_funcs;
+}
+
+
diff --git a/third_party/harfbuzz-ng/src/hb-icu.h b/third_party/harfbuzz-ng/src/hb-icu.h
index cc17af8..ecabec2 100644
--- a/third_party/harfbuzz-ng/src/hb-icu.h
+++ b/third_party/harfbuzz-ng/src/hb-icu.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -22,16 +23,26 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
#ifndef HB_ICU_H
#define HB_ICU_H
#include "hb.h"
+#include <unicode/uscript.h>
+
HB_BEGIN_DECLS
+hb_script_t
+hb_icu_script_to_script (UScriptCode script);
+
+UScriptCode
+hb_icu_script_from_script (hb_script_t script);
+
+
hb_unicode_funcs_t *
hb_icu_get_unicode_funcs (void);
diff --git a/third_party/harfbuzz-ng/src/hb-language.c b/third_party/harfbuzz-ng/src/hb-language.c
deleted file mode 100644
index 2aabada..0000000
--- a/third_party/harfbuzz-ng/src/hb-language.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2009 Red Hat, 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.h"
-
-#include "hb-language.h"
-
-HB_BEGIN_DECLS
-
-
-static const char canon_map[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0,
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
- '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
- 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-',
- 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
- 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
-};
-
-static hb_bool_t
-lang_equal (const void *v1,
- const void *v2)
-{
- const unsigned char *p1 = v1;
- const unsigned char *p2 = v2;
-
- while (canon_map[*p1] && canon_map[*p1] == canon_map[*p2])
- {
- p1++, p2++;
- }
-
- return (canon_map[*p1] == canon_map[*p2]);
-}
-
-#if 0
-static unsigned int
-lang_hash (const void *key)
-{
- const unsigned char *p = key;
- unsigned int h = 0;
- while (canon_map[*p])
- {
- h = (h << 5) - h + canon_map[*p];
- p++;
- }
-
- return h;
-}
-#endif
-
-
-hb_language_t
-hb_language_from_string (const char *str)
-{
- static unsigned int num_langs;
- static unsigned int num_alloced;
- static const char **langs;
- unsigned int i;
- unsigned char *p;
-
- /* TODO Use a hash table or something */
-
- if (!str)
- return NULL;
-
- for (i = 0; i < num_langs; i++)
- if (lang_equal (str, langs[i]))
- return langs[i];
-
- if (unlikely (num_langs == num_alloced)) {
- unsigned int new_alloced = 2 * (8 + num_alloced);
- const char **new_langs = realloc (langs, new_alloced * sizeof (langs[0]));
- if (!new_langs)
- return NULL;
- num_alloced = new_alloced;
- langs = new_langs;
- }
-
- langs[i] = strdup (str);
- for (p = (unsigned char *) langs[i]; *p; p++)
- *p = canon_map[*p];
-
- num_langs++;
-
- return (hb_language_t) langs[i];
-}
-
-const char *
-hb_language_to_string (hb_language_t language)
-{
- return (const char *) language;
-}
-
-
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-mutex-private.hh b/third_party/harfbuzz-ng/src/hb-mutex-private.hh
new file mode 100644
index 0000000..9855a565
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-mutex-private.hh
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2007 Chris Wilson
+ * Copyright © 2009,2010 Red Hat, Inc.
+ * Copyright © 2011 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.
+ *
+ * Contributor(s):
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_MUTEX_PRIVATE_HH
+#define HB_MUTEX_PRIVATE_HH
+
+#include "hb-private.hh"
+
+
+
+/* mutex */
+
+/* We need external help for these */
+
+#ifdef HAVE_GLIB
+
+#include <glib.h>
+
+typedef GStaticMutex hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT G_STATIC_MUTEX_INIT
+#define hb_mutex_impl_init(M) g_static_mutex_init (M)
+#define hb_mutex_impl_lock(M) g_static_mutex_lock (M)
+#define hb_mutex_impl_unlock(M) g_static_mutex_unlock (M)
+#define hb_mutex_impl_free(M) g_static_mutex_free (M)
+
+
+#elif defined(_MSC_VER) || defined(__MINGW32__)
+
+#include <windows.h>
+
+typedef CRITICAL_SECTION hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT { NULL, 0, 0, NULL, NULL, 0 }
+#define hb_mutex_impl_init(M) InitializeCriticalSection (M)
+#define hb_mutex_impl_lock(M) EnterCriticalSection (M)
+#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
+#define hb_mutex_impl_free(M) DeleteCriticalSection (M)
+
+
+#else
+
+#warning "Could not find any system to define platform macros, library will NOT be thread-safe"
+
+typedef volatile int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT 0
+#define hb_mutex_impl_init(M) ((void) (*(M) = 0))
+#define hb_mutex_impl_lock(M) ((void) (*(M) = 1))
+#define hb_mutex_impl_unlock(M) ((void) (*(M) = 0))
+#define hb_mutex_impl_free(M) ((void) (*(M) = 2))
+
+
+#endif
+
+
+struct hb_mutex_t
+{
+ hb_mutex_impl_t m;
+
+ inline void init (void) { hb_mutex_impl_init (&m); }
+ inline void lock (void) { hb_mutex_impl_lock (&m); }
+ inline void unlock (void) { hb_mutex_impl_unlock (&m); }
+ inline void free (void) { hb_mutex_impl_free (&m); }
+};
+
+#define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT}
+#define hb_mutex_init(M) (M)->init ()
+#define hb_mutex_lock(M) (M)->lock ()
+#define hb_mutex_unlock(M) (M)->unlock ()
+#define hb_mutex_free(M) (M)->free ()
+
+
+struct hb_static_mutex_t : hb_mutex_t
+{
+ hb_static_mutex_t (void) { this->init (); }
+ ~hb_static_mutex_t (void) { this->free (); }
+
+ private:
+ NO_COPY (hb_static_mutex_t);
+};
+
+
+
+#endif /* HB_MUTEX_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-object-private.h b/third_party/harfbuzz-ng/src/hb-object-private.h
deleted file mode 100644
index a5b5355..0000000
--- a/third_party/harfbuzz-ng/src/hb-object-private.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2007 Chris Wilson
- * Copyright (C) 2009,2010 Red Hat, 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.
- *
- * Contributor(s):
- * Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OBJECT_PRIVATE_H
-#define HB_OBJECT_PRIVATE_H
-
-#include "hb-private.h"
-
-HB_BEGIN_DECLS
-
-
-/* Encapsulate operations on the object's reference count */
-typedef struct {
- hb_atomic_int_t ref_count;
-} hb_reference_count_t;
-
-#define hb_reference_count_inc(RC) hb_atomic_int_fetch_and_add ((RC).ref_count, 1)
-#define hb_reference_count_dec(RC) hb_atomic_int_fetch_and_add ((RC).ref_count, -1)
-
-#define HB_REFERENCE_COUNT_INIT(RC, VALUE) ((RC).ref_count = (VALUE))
-
-#define HB_REFERENCE_COUNT_GET_VALUE(RC) hb_atomic_int_get ((RC).ref_count)
-#define HB_REFERENCE_COUNT_SET_VALUE(RC, VALUE) hb_atomic_int_set ((RC).ref_count, (VALUE))
-
-#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1)
-#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE}
-
-#define HB_REFERENCE_COUNT_IS_INVALID(RC) (HB_REFERENCE_COUNT_GET_VALUE (RC) == HB_REFERENCE_COUNT_INVALID_VALUE)
-
-#define HB_REFERENCE_COUNT_HAS_REFERENCE(RC) (HB_REFERENCE_COUNT_GET_VALUE (RC) > 0)
-
-
-
-/* Debug */
-
-#ifndef HB_DEBUG_OBJECT
-#define HB_DEBUG_OBJECT (HB_DEBUG+0)
-#endif
-
-static inline void
-_hb_trace_object (const void *obj,
- hb_reference_count_t *ref_count,
- const char *function)
-{
- (void) (HB_DEBUG_OBJECT &&
- fprintf (stderr, "OBJECT(%p) refcount=%d %s\n",
- obj,
- HB_REFERENCE_COUNT_GET_VALUE (*ref_count),
- function));
-}
-
-#define TRACE_OBJECT(obj) _hb_trace_object (obj, &obj->ref_count, __FUNCTION__)
-
-
-
-/* Object allocation and lifecycle manamgement macros */
-
-#define HB_OBJECT_IS_INERT(obj) \
- (unlikely (HB_REFERENCE_COUNT_IS_INVALID ((obj)->ref_count)))
-
-#define HB_OBJECT_DO_INIT_EXPR(obj) \
- HB_REFERENCE_COUNT_INIT (obj->ref_count, 1)
-
-#define HB_OBJECT_DO_INIT(obj) \
- HB_STMT_START { \
- HB_OBJECT_DO_INIT_EXPR (obj); \
- } HB_STMT_END
-
-#define HB_OBJECT_DO_CREATE(Type, obj) \
- likely (( \
- (void) ( \
- ((obj) = (Type *) calloc (1, sizeof (Type))) && \
- ( \
- HB_OBJECT_DO_INIT_EXPR (obj), \
- TRACE_OBJECT (obj), \
- TRUE \
- ) \
- ), \
- (obj) \
- ))
-
-#define HB_OBJECT_DO_REFERENCE(obj) \
- HB_STMT_START { \
- int old_count; \
- if (unlikely (!(obj) || HB_OBJECT_IS_INERT (obj))) \
- return obj; \
- TRACE_OBJECT (obj); \
- old_count = hb_reference_count_inc (obj->ref_count); \
- assert (old_count > 0); \
- return obj; \
- } HB_STMT_END
-
-#define HB_OBJECT_DO_GET_REFERENCE_COUNT(obj) \
- HB_STMT_START { \
- if (unlikely (!(obj) || HB_OBJECT_IS_INERT (obj))) \
- return 0; \
- return HB_REFERENCE_COUNT_GET_VALUE (obj->ref_count); \
- } HB_STMT_END
-
-#define HB_OBJECT_DO_DESTROY(obj) \
- HB_STMT_START { \
- int old_count; \
- if (unlikely (!(obj) || HB_OBJECT_IS_INERT (obj))) \
- return; \
- TRACE_OBJECT (obj); \
- old_count = hb_reference_count_dec (obj->ref_count); \
- assert (old_count > 0); \
- if (old_count != 1) \
- return; \
- } HB_STMT_END
-
-
-HB_END_DECLS
-
-#endif /* HB_OBJECT_PRIVATE_H */
diff --git a/third_party/harfbuzz-ng/src/hb-object-private.hh b/third_party/harfbuzz-ng/src/hb-object-private.hh
new file mode 100644
index 0000000..2e4a385
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-object-private.hh
@@ -0,0 +1,267 @@
+/*
+ * Copyright © 2007 Chris Wilson
+ * Copyright © 2009,2010 Red Hat, Inc.
+ * Copyright © 2011 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.
+ *
+ * Contributor(s):
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OBJECT_PRIVATE_HH
+#define HB_OBJECT_PRIVATE_HH
+
+#include "hb-private.hh"
+
+#include "hb-mutex-private.hh"
+
+
+
+/* Debug */
+
+#ifndef HB_DEBUG_OBJECT
+#define HB_DEBUG_OBJECT (HB_DEBUG+0)
+#endif
+
+
+/* atomic_int */
+
+/* We need external help for these */
+
+#ifdef HAVE_GLIB
+
+#include <glib.h>
+
+typedef volatile int hb_atomic_int_t;
+#if GLIB_CHECK_VERSION(2,29,5)
+#define hb_atomic_int_add(AI, V) g_atomic_int_add (&(AI), V)
+#else
+#define hb_atomic_int_add(AI, V) g_atomic_int_exchange_and_add (&(AI), V)
+#endif
+#define hb_atomic_int_get(AI) g_atomic_int_get (&(AI))
+#define hb_atomic_int_set(AI, V) g_atomic_int_set (&(AI), V)
+
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1600
+
+#include <intrin.h>
+
+typedef long hb_atomic_int_t;
+#define hb_atomic_int_add(AI, V) _InterlockedExchangeAdd (&(AI), V)
+#define hb_atomic_int_get(AI) (_ReadBarrier (), (AI))
+#define hb_atomic_int_set(AI, V) ((void) _InterlockedExchange (&(AI), (V)))
+
+
+#else
+
+#ifdef _MSC_VER
+#pragma message("Could not find any system to define atomic_int macros, library will NOT be thread-safe")
+#else
+#warning "Could not find any system to define atomic_int macros, library will NOT be thread-safe"
+#endif
+
+typedef volatile int hb_atomic_int_t;
+#define hb_atomic_int_add(AI, V) ((AI) += (V), (AI) - (V))
+#define hb_atomic_int_get(AI) (AI)
+#define hb_atomic_int_set(AI, V) ((void) ((AI) = (V)))
+
+
+#endif
+
+
+
+
+/* reference_count */
+
+typedef struct {
+ hb_atomic_int_t ref_count;
+
+#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1)
+#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE}
+
+ inline void init (int v) { ref_count = v; /* non-atomic is fine */ }
+ inline int inc (void) { return hb_atomic_int_add (ref_count, 1); }
+ inline int dec (void) { return hb_atomic_int_add (ref_count, -1); }
+ inline void set (int v) { hb_atomic_int_set (ref_count, v); }
+
+ inline int get (void) const { return hb_atomic_int_get (ref_count); }
+ inline bool is_invalid (void) const { return get () == HB_REFERENCE_COUNT_INVALID_VALUE; }
+
+} hb_reference_count_t;
+
+
+/* user_data */
+
+struct hb_user_data_array_t {
+
+ struct hb_user_data_item_t {
+ hb_user_data_key_t *key;
+ void *data;
+ hb_destroy_func_t destroy;
+
+ inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
+ inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
+
+ void finish (void) { if (destroy) destroy (data); }
+ };
+
+ hb_lockable_set_t<hb_user_data_item_t, hb_static_mutex_t> items;
+
+ HB_INTERNAL bool set (hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+ HB_INTERNAL void *get (hb_user_data_key_t *key);
+
+ HB_INTERNAL void finish (void);
+};
+
+
+/* object_header */
+
+typedef struct _hb_object_header_t hb_object_header_t;
+
+struct _hb_object_header_t {
+ hb_reference_count_t ref_count;
+ hb_user_data_array_t user_data;
+
+#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID}
+
+ static inline void *create (unsigned int size) {
+ hb_object_header_t *obj = (hb_object_header_t *) calloc (1, size);
+
+ if (likely (obj))
+ obj->init ();
+
+ return obj;
+ }
+
+ inline void init (void) {
+ ref_count.init (1);
+ }
+
+ inline bool is_inert (void) const {
+ return unlikely (ref_count.is_invalid ());
+ }
+
+ inline void reference (void) {
+ if (unlikely (!this || this->is_inert ()))
+ return;
+ ref_count.inc ();
+ }
+
+ inline bool destroy (void) {
+ if (unlikely (!this || this->is_inert ()))
+ return false;
+ if (ref_count.dec () != 1)
+ return false;
+
+ ref_count.init (HB_REFERENCE_COUNT_INVALID_VALUE);
+
+ user_data.finish ();
+
+ return true;
+ }
+
+ inline bool set_user_data (hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy_func,
+ hb_bool_t replace) {
+ if (unlikely (!this || this->is_inert ()))
+ return false;
+
+ return user_data.set (key, data, destroy_func, replace);
+ }
+
+ inline void *get_user_data (hb_user_data_key_t *key) {
+ return user_data.get (key);
+ }
+
+ inline void trace (const char *function) const {
+ DEBUG_MSG (OBJECT, (void *) this,
+ "refcount=%d %s",
+ this ? ref_count.get () : 0,
+ function);
+ }
+
+};
+
+
+
+
+/* object */
+
+template <typename Type>
+static inline void hb_object_trace (const Type *obj, const char *function)
+{
+ obj->header.trace (function);
+}
+template <typename Type>
+static inline Type *hb_object_create (void)
+{
+ Type *obj = (Type *) hb_object_header_t::create (sizeof (Type));
+ hb_object_trace (obj, HB_FUNC);
+ return obj;
+}
+template <typename Type>
+static inline bool hb_object_is_inert (const Type *obj)
+{
+ return unlikely (obj->header.is_inert ());
+}
+template <typename Type>
+static inline Type *hb_object_reference (Type *obj)
+{
+ hb_object_trace (obj, HB_FUNC);
+ obj->header.reference ();
+ return obj;
+}
+template <typename Type>
+static inline bool hb_object_destroy (Type *obj)
+{
+ hb_object_trace (obj, HB_FUNC);
+ return obj->header.destroy ();
+}
+template <typename Type>
+static inline bool hb_object_set_user_data (Type *obj,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return obj->header.set_user_data (key, data, destroy, replace);
+}
+
+template <typename Type>
+static inline void *hb_object_get_user_data (Type *obj,
+ hb_user_data_key_t *key)
+{
+ return obj->header.get_user_data (key);
+}
+
+
+
+
+
+#endif /* HB_OBJECT_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-open-file-private.hh b/third_party/harfbuzz-ng/src/hb-open-file-private.hh
index cfb60db..62e1f17 100644
--- a/third_party/harfbuzz-ng/src/hb-open-file-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-open-file-private.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -29,7 +29,6 @@
#include "hb-open-type-private.hh"
-HB_BEGIN_DECLS
/*
@@ -152,7 +151,7 @@ struct TTCHeader
inline unsigned int get_face_count (void) const
{
- switch (u.header.version) {
+ switch (u.header.version.major) {
case 2: /* version 2 is compatible with version 1 */
case 1: return u.version1.get_face_count ();
default:return 0;
@@ -160,7 +159,7 @@ struct TTCHeader
}
inline const OpenTypeFontFace& get_face (unsigned int i) const
{
- switch (u.header.version) {
+ switch (u.header.version.major) {
case 2: /* version 2 is compatible with version 1 */
case 1: return u.version1.get_face (i);
default:return Null(OpenTypeFontFace);
@@ -170,7 +169,7 @@ struct TTCHeader
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
if (unlikely (!u.header.version.sanitize (c))) return false;
- switch (u.header.version) {
+ switch (u.header.version.major) {
case 2: /* version 2 is compatible with version 1 */
case 1: return u.version1.sanitize (c);
default:return true;
@@ -253,6 +252,5 @@ struct OpenTypeFontFile
};
-HB_END_DECLS
#endif /* HB_OPEN_FILE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-open-type-private.hh b/third_party/harfbuzz-ng/src/hb-open-type-private.hh
index 8f3001b..8143b28 100644
--- a/third_party/harfbuzz-ng/src/hb-open-type-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-open-type-private.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007,2008,2009,2010 Red Hat, Inc.
+ * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -27,12 +27,10 @@
#ifndef HB_OPEN_TYPE_PRIVATE_HH
#define HB_OPEN_TYPE_PRIVATE_HH
-#include "hb-private.h"
+#include "hb-private.hh"
#include "hb-blob.h"
-HB_BEGIN_DECLS
-HB_END_DECLS
/*
@@ -144,29 +142,6 @@ ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
#define Null(Type) Null<Type>()
-/*
- * Trace
- */
-
-
-template <int max_depth>
-struct hb_trace_t {
- explicit hb_trace_t (unsigned int *pdepth, const char *what, const char *function, const void *obj) : pdepth(pdepth) {
- (void) (*pdepth < max_depth &&
- fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, *pdepth, *pdepth, function));
- if (max_depth) ++*pdepth;
- }
- ~hb_trace_t (void) { if (max_depth) --*pdepth; }
-
- private:
- unsigned int *pdepth;
-};
-template <> /* Optimize when tracing is disabled */
-struct hb_trace_t<0> {
- explicit hb_trace_t (unsigned int *pdepth HB_UNUSED, const char *what HB_UNUSED, const char *function HB_UNUSED, const void *obj HB_UNUSED) {}
-};
-
-
/*
* Sanitize
@@ -178,33 +153,36 @@ struct hb_trace_t<0> {
#define TRACE_SANITIZE() \
- hb_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", HB_FUNC, this); \
+ hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", this, NULL, HB_FUNC);
struct hb_sanitize_context_t
{
- inline void init (hb_blob_t *blob)
+ inline void init (hb_blob_t *b)
+ {
+ this->blob = hb_blob_reference (b);
+ this->writable = false;
+ }
+
+ inline void setup (void)
{
- this->blob = hb_blob_reference (blob);
- this->start = hb_blob_lock (blob);
- this->end = this->start + hb_blob_get_length (blob);
- this->writable = hb_blob_is_writable (blob);
+ this->start = hb_blob_get_data (this->blob, NULL);
+ this->end = this->start + hb_blob_get_length (this->blob);
this->edit_count = 0;
this->debug_depth = 0;
- (void) (HB_DEBUG_SANITIZE &&
- fprintf (stderr, "sanitize %p init [%p..%p] (%lu bytes)\n",
- this->blob, this->start, this->end,
- (unsigned long) (this->end - this->start)));
+ DEBUG_MSG (SANITIZE, this->blob,
+ "init [%p..%p] (%lu bytes)",
+ this->start, this->end,
+ (unsigned long) (this->end - this->start));
}
inline void finish (void)
{
- (void) (HB_DEBUG_SANITIZE &&
- fprintf (stderr, "sanitize %p fini [%p..%p] %u edit requests\n",
- this->blob, this->start, this->end, this->edit_count));
+ DEBUG_MSG (SANITIZE, this->blob,
+ "fini [%p..%p] %u edit requests",
+ this->start, this->end, this->edit_count);
- hb_blob_unlock (this->blob);
hb_blob_destroy (this->blob);
this->blob = NULL;
this->start = this->end = NULL;
@@ -217,13 +195,12 @@ struct hb_sanitize_context_t
p <= this->end &&
(unsigned int) (this->end - p) >= len;
- (void) (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE &&
- fprintf (stderr, "SANITIZE(%p) %-*d-> range [%p..%p] (%d bytes) in [%p..%p] -> %s\n",
- p,
- this->debug_depth, this->debug_depth,
- p, p + len, len,
- this->start, this->end,
- ret ? "pass" : "FAIL"));
+ DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth,
+ "%-*d-> range [%p..%p] (%d bytes) in [%p..%p] -> %s",
+ this->debug_depth, this->debug_depth,
+ p, p + len, len,
+ this->start, this->end,
+ ret ? "pass" : "FAIL");
return likely (ret);
}
@@ -231,15 +208,14 @@ struct hb_sanitize_context_t
inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
{
const char *p = (const char *) base;
- bool overflows = record_size > 0 && len >= ((unsigned int) -1) / record_size;
+ bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
- (void) (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE &&
- fprintf (stderr, "SANITIZE(%p) %-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s\n",
- p,
- this->debug_depth, this->debug_depth,
- p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
- this->start, this->end,
- !overflows ? "does not overflow" : "OVERFLOWS FAIL"));
+ DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth,
+ "%-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s",
+ this->debug_depth, this->debug_depth,
+ p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
+ this->start, this->end,
+ !overflows ? "does not overflow" : "OVERFLOWS FAIL");
return likely (!overflows && this->check_range (base, record_size * len));
}
@@ -255,14 +231,13 @@ struct hb_sanitize_context_t
const char *p = (const char *) base;
this->edit_count++;
- (void) (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE &&
- fprintf (stderr, "SANITIZE(%p) %-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s\n",
- p,
- this->debug_depth, this->debug_depth,
- this->edit_count,
- p, p + len, len,
- this->start, this->end,
- this->writable ? "granted" : "REJECTED"));
+ DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth,
+ "%-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
+ this->debug_depth, this->debug_depth,
+ this->edit_count,
+ p, p + len, len,
+ this->start, this->end,
+ this->writable ? "granted" : "REJECTED");
return this->writable;
}
@@ -286,14 +261,12 @@ struct Sanitizer
/* TODO is_sane() stuff */
- if (!blob)
- return hb_blob_create_empty ();
+ c->init (blob);
retry:
- (void) (HB_DEBUG_SANITIZE &&
- fprintf (stderr, "Sanitizer %p start %s\n", blob, HB_FUNC));
+ DEBUG_MSG_FUNC (SANITIZE, blob, "start");
- c->init (blob);
+ c->setup ();
if (unlikely (!c->start)) {
c->finish ();
@@ -305,44 +278,45 @@ struct Sanitizer
sane = t->sanitize (c);
if (sane) {
if (c->edit_count) {
- (void) (HB_DEBUG_SANITIZE &&
- fprintf (stderr, "Sanitizer %p passed first round with %d edits; doing a second round %s\n",
- blob, c->edit_count, HB_FUNC));
+ DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count);
/* sanitize again to ensure no toe-stepping */
c->edit_count = 0;
sane = t->sanitize (c);
if (c->edit_count) {
- (void) (HB_DEBUG_SANITIZE &&
- fprintf (stderr, "Sanitizer %p requested %d edits in second round; FAILLING %s\n",
- blob, c->edit_count, HB_FUNC));
+ DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count);
sane = false;
}
}
- c->finish ();
} else {
unsigned int edit_count = c->edit_count;
- c->finish ();
- if (edit_count && !hb_blob_is_writable (blob) && hb_blob_try_writable (blob)) {
- /* ok, we made it writable by relocating. try again */
- (void) (HB_DEBUG_SANITIZE &&
- fprintf (stderr, "Sanitizer %p retry %s\n", blob, HB_FUNC));
- goto retry;
+ if (edit_count && !c->writable) {
+ c->start = hb_blob_get_data_writable (blob, NULL);
+ c->end = c->start + hb_blob_get_length (blob);
+
+ if (c->start) {
+ c->writable = true;
+ /* ok, we made it writable by relocating. try again */
+ DEBUG_MSG_FUNC (SANITIZE, blob, "retry");
+ goto retry;
+ }
}
}
- (void) (HB_DEBUG_SANITIZE &&
- fprintf (stderr, "Sanitizer %p %s %s\n", blob, sane ? "passed" : "FAILED", HB_FUNC));
+ c->finish ();
+
+ DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED");
if (sane)
return blob;
else {
hb_blob_destroy (blob);
- return hb_blob_create_empty ();
+ return hb_blob_get_empty ();
}
}
static const Type* lock_instance (hb_blob_t *blob) {
- const char *base = hb_blob_lock (blob);
+ hb_blob_make_immutable (blob);
+ const char *base = hb_blob_get_data (blob, NULL);
return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
}
};
@@ -364,27 +338,27 @@ struct Sanitizer
*/
-template <typename Type, int Bytes> class BEInt;
+template <typename Type, int Bytes> struct BEInt;
/* LONGTERMTODO: On machines allowing unaligned access, we can make the
* following tighter by using byteswap instructions on ints directly. */
template <typename Type>
-class BEInt<Type, 2>
+struct BEInt<Type, 2>
{
public:
inline void set (Type i) { hb_be_uint16_put (v,i); }
inline operator Type (void) const { return hb_be_uint16_get (v); }
- inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_cmp (v, o.v); }
+ inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); }
inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
private: uint8_t v[2];
};
template <typename Type>
-class BEInt<Type, 4>
+struct BEInt<Type, 4>
{
public:
inline void set (Type i) { hb_be_uint32_put (v,i); }
inline operator Type (void) const { return hb_be_uint32_get (v); }
- inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_cmp (v, o.v); }
+ inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); }
inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
private: uint8_t v[4];
};
@@ -408,11 +382,22 @@ struct IntType
DEFINE_SIZE_STATIC (sizeof (Type));
};
+/* Typedef these to avoid clash with windows.h */
+#define USHORT HB_USHORT
+#define SHORT HB_SHORT
+#define ULONG HB_ULONG
+#define LONG HB_LONG
typedef IntType<uint16_t> USHORT; /* 16-bit unsigned integer. */
typedef IntType<int16_t> SHORT; /* 16-bit signed integer. */
typedef IntType<uint32_t> ULONG; /* 32-bit unsigned integer. */
typedef IntType<int32_t> LONG; /* 32-bit signed integer. */
+/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
+typedef SHORT FWORD;
+
+/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
+typedef USHORT UFWORD;
+
/* 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
@@ -479,7 +464,7 @@ struct CheckSum : ULONG
struct FixedVersion
{
- inline operator uint32_t (void) const { return (major << 16) + minor; }
+ inline uint32_t to_int (void) const { return (major << 16) + minor; }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
@@ -712,8 +697,8 @@ struct SortedArrayOf : ArrayOf<Type> {
template <typename SearchType>
inline int search (const SearchType &x) const {
- class Cmp {
- public: static int cmp (const SearchType *a, const Type *b) { return b->cmp (*a); }
+ struct Cmp {
+ static int cmp (const SearchType *a, const Type *b) { return b->cmp (*a); }
};
const Type *p = (const Type *) bsearch (&x, this->array, this->len, sizeof (this->array[0]), (hb_compare_func_t) Cmp::cmp);
return p ? p - this->array : -1;
@@ -721,7 +706,5 @@ struct SortedArrayOf : ArrayOf<Type> {
};
-HB_BEGIN_DECLS
-HB_END_DECLS
#endif /* HB_OPEN_TYPE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-head-private.hh b/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
index 3a4bbbf..a4d8d5f 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-head-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-head-table.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright © 2010 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,16 +24,15 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_HEAD_PRIVATE_HH
-#define HB_OT_HEAD_PRIVATE_HH
+#ifndef HB_OT_HEAD_TABLE_HH
+#define HB_OT_HEAD_TABLE_HH
#include "hb-open-type-private.hh"
-HB_BEGIN_DECLS
/*
- * head
+ * head -- Font Header
*/
#define HB_OT_TAG_head HB_TAG('h','e','a','d')
@@ -50,7 +49,6 @@ struct head
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
- /* Shall we check for magicNumber here? Who cares? */
return c->check_struct (this) && likely (version.major == 1);
}
@@ -141,6 +139,5 @@ struct head
};
-HB_END_DECLS
-#endif /* HB_OT_HEAD_PRIVATE_HH */
+#endif /* HB_OT_HEAD_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh b/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
new file mode 100644
index 0000000..34bf494
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-hhea-table.hh
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2011 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_HHEA_TABLE_HH
+#define HB_OT_HHEA_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+
+
+/*
+ * hhea -- The Horizontal Header Table
+ */
+
+#define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
+
+
+struct hhea
+{
+ static const hb_tag_t Tag = HB_OT_TAG_hhea;
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE ();
+ return c->check_struct (this) && likely (version.major == 1);
+ }
+
+ private:
+ FixedVersion version; /* 0x00010000 for version 1.0. */
+ FWORD ascender; /* Typographic ascent. <a
+ * href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
+ * (Distance from baseline of highest
+ * ascender)</a> */
+ FWORD descender; /* Typographic descent. <a
+ * href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
+ * (Distance from baseline of lowest
+ * descender)</a> */
+ FWORD lineGap; /* Typographic line gap. Negative
+ * LineGap values are treated as zero
+ * in Windows 3.1, System 6, and
+ * System 7. */
+ UFWORD advanceWidthMax; /* Maximum advance width value in
+ * 'hmtx' table. */
+ FWORD minLeftSideBearing; /* Minimum left sidebearing value in
+ * 'hmtx' table. */
+ FWORD minRightSideBearing; /* Minimum right sidebearing value;
+ * calculated as Min(aw - lsb -
+ * (xMax - xMin)). */
+ FWORD xMaxExtent; /* Max(lsb + (xMax - xMin)). */
+ SHORT caretSlopeRise; /* Used to calculate the slope of the
+ * cursor (rise/run); 1 for vertical. */
+ SHORT caretSlopeRun; /* 0 for vertical. */
+ SHORT caretOffset; /* The amount by which a slanted
+ * highlight on a glyph needs
+ * to be shifted to produce the
+ * best appearance. Set to 0 for
+ * non--slanted fonts */
+ SHORT reserved1; /* set to 0 */
+ SHORT reserved2; /* set to 0 */
+ SHORT reserved3; /* set to 0 */
+ SHORT reserved4; /* set to 0 */
+ SHORT metricDataFormat; /* 0 for current format. */
+ USHORT numberOfHMetrics; /* Number of hMetric entries in 'hmtx'
+ * table */
+ public:
+ DEFINE_SIZE_STATIC (36);
+};
+
+
+#endif /* HB_OT_HHEA_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
new file mode 100644
index 0000000..b58799c
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-hmtx-table.hh
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2011 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_HMTX_TABLE_HH
+#define HB_OT_HMTX_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+
+
+/*
+ * hmtx -- The Horizontal Metrics Table
+ */
+
+#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
+
+
+struct LongHorMetric
+{
+ USHORT advanceWidth;
+ SHORT lsb;
+ public:
+ DEFINE_SIZE_STATIC (4);
+};
+
+struct hmtx
+{
+ static const hb_tag_t Tag = HB_OT_TAG_hmtx;
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE ();
+ /* We don't check for anything specific here. The users of the
+ * struct do all the hard work... */
+ return true;
+ }
+
+ private:
+ LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side
+ * bearing values for each glyph. The
+ * value numOfHMetrics comes from
+ * the 'hhea' table. If the font is
+ * monospaced, only one entry need
+ * be in the array, but that entry is
+ * required. The last entry applies to
+ * all subsequent glyphs. */
+ SHORT leftSideBearingX[VAR]; /* Here the advanceWidth is assumed
+ * to be the same as the advanceWidth
+ * for the last entry above. The
+ * number of entries in this array is
+ * derived from numGlyphs (from 'maxp'
+ * table) minus numberOfHMetrics. This
+ * generally is used with a run of
+ * monospaced glyphs (e.g., Kanji
+ * fonts or Courier fonts). Only one
+ * run is allowed and it must be at
+ * the end. This allows a monospaced
+ * font to vary the left side bearing
+ * values for each glyph. */
+ public:
+ DEFINE_SIZE_ARRAY2 (0, longHorMetric, leftSideBearingX);
+};
+
+#endif /* HB_OT_HMTX_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
index 9ff5ca9..5d19e08 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-common-private.hh
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2007,2008,2009 Red Hat, Inc.
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -38,8 +38,6 @@
#define NOT_COVERED ((unsigned int) 0x110000)
#define MAX_NESTING_LEVEL 8
-HB_BEGIN_DECLS
-HB_END_DECLS
/*
@@ -89,10 +87,10 @@ struct RecordArrayOf : SortedArrayOf<Record<Type> > {
hb_tag_t *record_tags /* OUT */) const
{
if (record_count) {
- const Record<Type> *array = this->sub_array (start_offset, record_count);
+ const Record<Type> *arr = this->sub_array (start_offset, record_count);
unsigned int count = *record_count;
for (unsigned int i = 0; i < count; i++)
- record_tags[i] = array[i].tag;
+ record_tags[i] = arr[i].tag;
}
return this->len;
}
@@ -150,10 +148,10 @@ struct IndexArray : ArrayOf<Index>
unsigned int *_indexes /* OUT */) const
{
if (_count) {
- const USHORT *array = this->sub_array (start_offset, _count);
+ const USHORT *arr = this->sub_array (start_offset, _count);
unsigned int count = *_count;
for (unsigned int i = 0; i < count; i++)
- _indexes[i] = array[i];
+ _indexes[i] = arr[i];
}
return this->len;
}
@@ -526,13 +524,13 @@ struct ClassDef
struct Device
{
- inline hb_position_t get_x_delta (hb_ot_layout_context_t *c) const
- { return get_delta (c->font->x_ppem, c->font->x_scale); }
+ inline hb_position_t get_x_delta (hb_font_t *font) const
+ { return get_delta (font->x_ppem, font->x_scale); }
- inline hb_position_t get_y_delta (hb_ot_layout_context_t *c) const
- { return get_delta (c->font->y_ppem, c->font->y_scale); }
+ inline hb_position_t get_y_delta (hb_font_t *font) const
+ { return get_delta (font->y_ppem, font->y_scale); }
- inline int get_delta (unsigned int ppem, unsigned int scale) const
+ inline int get_delta (unsigned int ppem, int scale) const
{
if (!ppem) return 0;
@@ -540,10 +538,6 @@ struct Device
if (!pixels) return 0;
- /* pixels is at most in the -8..7 range. So 64-bit arithmetic is
- * not really necessary here. A simple cast to int may just work
- * as well. But since this code is not reached that often and
- * for the sake of correctness, we do a 64bit operation. */
return pixels * (int64_t) scale / ppem;
}
@@ -598,7 +592,5 @@ struct Device
};
-HB_BEGIN_DECLS
-HB_END_DECLS
#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
index 4172a7c..ee9c508 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2007,2008,2009 Red Hat, Inc.
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -26,14 +26,13 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_LAYOUT_GDEF_PRIVATE_HH
-#define HB_OT_LAYOUT_GDEF_PRIVATE_HH
+#ifndef HB_OT_LAYOUT_GDEF_TABLE_HH
+#define HB_OT_LAYOUT_GDEF_TABLE_HH
#include "hb-ot-layout-common-private.hh"
-#include "hb-font-private.h"
+#include "hb-font-private.hh"
-HB_BEGIN_DECLS
/*
@@ -96,9 +95,9 @@ struct CaretValueFormat1
friend struct CaretValue;
private:
- inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
+ inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
{
- return HB_DIRECTION_IS_HORIZONTAL (direction) ? c->scale_x (coordinate) : c->scale_y (coordinate);
+ return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -118,10 +117,10 @@ struct CaretValueFormat2
friend struct CaretValue;
private:
- inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t direction, hb_codepoint_t glyph_id) const
+ inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
{
hb_position_t x, y;
- if (hb_font_get_contour_point (c->font, c->face, caretValuePoint, glyph_id, &x, &y))
+ if (hb_font_get_glyph_contour_point_for_origin (font, glyph_id, caretValuePoint, direction, &x, &y))
return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
else
return 0;
@@ -143,11 +142,11 @@ struct CaretValueFormat3
{
friend struct CaretValue;
- inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t direction, hb_codepoint_t glyph_id) const
+ inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
{
return HB_DIRECTION_IS_HORIZONTAL (direction) ?
- c->scale_x (coordinate) + (this+deviceTable).get_x_delta (c) :
- c->scale_y (coordinate) + (this+deviceTable).get_y_delta (c);
+ font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
+ font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -169,12 +168,12 @@ struct CaretValueFormat3
struct CaretValue
{
- inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t direction, hb_codepoint_t glyph_id) const
+ inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
{
switch (u.format) {
- case 1: return u.format1.get_caret_value (c, direction, glyph_id);
- case 2: return u.format2.get_caret_value (c, direction, glyph_id);
- case 3: return u.format3.get_caret_value (c, direction, glyph_id);
+ case 1: return u.format1.get_caret_value (font, direction, glyph_id);
+ case 2: return u.format2.get_caret_value (font, direction, glyph_id);
+ case 3: return u.format3.get_caret_value (font, direction, glyph_id);
default:return 0;
}
}
@@ -203,18 +202,18 @@ struct CaretValue
struct LigGlyph
{
- inline unsigned int get_lig_carets (hb_ot_layout_context_t *c,
+ inline unsigned int get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
- int *caret_array /* OUT */) const
+ hb_position_t *caret_array /* OUT */) const
{
if (caret_count) {
const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
unsigned int count = *caret_count;
for (unsigned int i = 0; i < count; i++)
- caret_array[i] = (this+array[i]).get_caret_value (c, direction, glyph_id);
+ caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id);
}
return carets.len;
@@ -236,12 +235,12 @@ struct LigGlyph
struct LigCaretList
{
- inline unsigned int get_lig_carets (hb_ot_layout_context_t *c,
+ inline unsigned int get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
- int *caret_array /* OUT */) const
+ hb_position_t *caret_array /* OUT */) const
{
unsigned int index = (this+coverage) (glyph_id);
if (index == NOT_COVERED)
@@ -251,7 +250,7 @@ struct LigCaretList
return 0;
}
const LigGlyph &lig_glyph = this+ligGlyph[index];
- return lig_glyph.get_lig_carets (c, direction, glyph_id, start_offset, caret_count, caret_array);
+ return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array);
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -321,7 +320,7 @@ struct MarkGlyphSets
/*
- * GDEF
+ * GDEF -- The Glyph Definition Table
*/
struct GDEF
@@ -352,17 +351,17 @@ struct GDEF
{ return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
inline bool has_lig_carets (void) const { return ligCaretList != 0; }
- inline unsigned int get_lig_carets (hb_ot_layout_context_t *c,
+ inline unsigned int get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
- int *caret_array /* OUT */) const
- { return (this+ligCaretList).get_lig_carets (c, direction, glyph_id, start_offset, caret_count, caret_array); }
+ hb_position_t *caret_array /* OUT */) const
+ { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
- inline bool has_mark_sets (void) const { return version >= 0x00010002 && markGlyphSetsDef[0] != 0; }
+ inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002 && markGlyphSetsDef[0] != 0; }
inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
- { return version >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
+ { return version.to_int () >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
@@ -371,7 +370,7 @@ struct GDEF
&& attachList.sanitize (c, this)
&& ligCaretList.sanitize (c, this)
&& markAttachClassDef.sanitize (c, this)
- && (version < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this));
+ && (version.to_int () < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this));
}
@@ -424,6 +423,5 @@ struct GDEF
};
-HB_END_DECLS
-#endif /* HB_OT_LAYOUT_GDEF_PRIVATE_HH */
+#endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
index 11bb286..412850b 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2007,2008,2009,2010 Red Hat, Inc.
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
+ * Copyright © 2010 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -26,15 +26,14 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_LAYOUT_GPOS_PRIVATE_HH
-#define HB_OT_LAYOUT_GPOS_PRIVATE_HH
+#ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
+#define HB_OT_LAYOUT_GPOS_TABLE_HH
#include "hb-ot-layout-gsubgpos-private.hh"
-HB_BEGIN_DECLS
-/* buffer var allocations */
+/* buffer **position** var allocations */
#define attach_lookback() var.u16[0] /* number of glyphs to go back to attach this glyph to its base */
#define cursive_chain() var.i16[1] /* character to which this connects, may be positive or negative */
@@ -94,41 +93,48 @@ struct ValueFormat : USHORT
inline unsigned int get_size (void) const
{ return get_len () * Value::static_size; }
- void apply_value (hb_ot_layout_context_t *layout,
- const void *base,
- const Value *values,
- hb_glyph_position_t &glyph_pos) const
+ void apply_value (hb_font_t *font,
+ hb_direction_t direction,
+ const void *base,
+ const Value *values,
+ hb_glyph_position_t &glyph_pos) const
{
unsigned int x_ppem, y_ppem;
unsigned int format = *this;
+ hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction);
if (!format) return;
- /* design units -> fractional pixel */
- if (format & xPlacement) glyph_pos.x_offset += layout->scale_x (get_short (values++));
- if (format & yPlacement) glyph_pos.y_offset += layout->scale_y (get_short (values++));
- if (format & xAdvance) glyph_pos.x_advance += layout->scale_x (get_short (values++));
- if (format & yAdvance) glyph_pos.y_advance += layout->scale_y (get_short (values++));
+ if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++));
+ if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++));
+ if (format & xAdvance) {
+ if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values++)); else values++;
+ }
+ /* y_advance values grow downward but font-space grows upward, hence negation */
+ if (format & yAdvance) {
+ if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values++)); else values++;
+ }
if (!has_device ()) return;
- x_ppem = layout->font->x_ppem;
- y_ppem = layout->font->y_ppem;
+ x_ppem = font->x_ppem;
+ y_ppem = font->y_ppem;
if (!x_ppem && !y_ppem) return;
/* pixel -> fractional pixel */
if (format & xPlaDevice) {
- if (x_ppem) glyph_pos.x_offset += (base + get_device (values++)).get_x_delta (layout); else values++;
+ if (x_ppem) glyph_pos.x_offset += (base + get_device (values++)).get_x_delta (font); else values++;
}
if (format & yPlaDevice) {
- if (y_ppem) glyph_pos.y_offset += (base + get_device (values++)).get_y_delta (layout); else values++;
+ if (y_ppem) glyph_pos.y_offset += (base + get_device (values++)).get_y_delta (font); else values++;
}
if (format & xAdvDevice) {
- if (x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (layout); else values++;
+ if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (font); else values++;
}
if (format & yAdvDevice) {
- if (y_ppem) glyph_pos.y_advance += (base + get_device (values++)).get_y_delta (layout); else values++;
+ /* y_advance values grow downward but font-space grows upward, hence negation */
+ if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values++)).get_y_delta (font); else values++;
}
}
@@ -209,11 +215,11 @@ struct AnchorFormat1
friend struct Anchor;
private:
- inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id HB_UNUSED,
+ inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
- *x = layout->scale_x (xCoordinate);
- *y = layout->scale_y (yCoordinate);
+ *x = font->em_scale_x (xCoordinate);
+ *y = font->em_scale_y (yCoordinate);
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -234,18 +240,18 @@ struct AnchorFormat2
friend struct Anchor;
private:
- inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id,
+ inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
hb_position_t *x, hb_position_t *y) const
{
- unsigned int x_ppem = layout->font->x_ppem;
- unsigned int y_ppem = layout->font->y_ppem;
+ unsigned int x_ppem = font->x_ppem;
+ unsigned int y_ppem = font->y_ppem;
hb_position_t cx, cy;
hb_bool_t ret = false;
if (x_ppem || y_ppem)
- ret = hb_font_get_contour_point (layout->font, layout->face, anchorPoint, glyph_id, &cx, &cy);
- *x = x_ppem && ret ? cx : layout->scale_x (xCoordinate);
- *y = y_ppem && ret ? cy : layout->scale_y (yCoordinate);
+ ret = hb_font_get_glyph_contour_point_for_origin (font, glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+ *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate);
+ *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate);
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -267,17 +273,16 @@ struct AnchorFormat3
friend struct Anchor;
private:
- inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id HB_UNUSED,
+ inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
hb_position_t *x, hb_position_t *y) const
{
- *x = layout->scale_x (xCoordinate);
- *y = layout->scale_y (yCoordinate);
-
- /* pixel -> fractional pixel */
- if (layout->font->x_ppem)
- *x += (this+xDeviceTable).get_x_delta (layout);
- if (layout->font->y_ppem)
- *y += (this+yDeviceTable).get_x_delta (layout);
+ *x = font->em_scale_x (xCoordinate);
+ *y = font->em_scale_y (yCoordinate);
+
+ if (font->x_ppem)
+ *x += (this+xDeviceTable).get_x_delta (font);
+ if (font->y_ppem)
+ *y += (this+yDeviceTable).get_x_delta (font);
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -305,15 +310,15 @@ struct AnchorFormat3
struct Anchor
{
- inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id,
+ inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
hb_position_t *x, hb_position_t *y) const
{
*x = *y = 0;
switch (u.format) {
- case 1: u.format1.get_anchor (layout, glyph_id, x, y); return;
- case 2: u.format2.get_anchor (layout, glyph_id, x, y); return;
- case 3: u.format3.get_anchor (layout, glyph_id, x, y); return;
- default: return;
+ case 1: u.format1.get_anchor (font, glyph_id, x, y); return;
+ case 2: u.format2.get_anchor (font, glyph_id, x, y); return;
+ case 3: u.format3.get_anchor (font, glyph_id, x, y); return;
+ default: return;
}
}
@@ -403,15 +408,15 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
hb_position_t mark_x, mark_y, base_x, base_y;
- mark_anchor.get_anchor (c->layout, c->buffer->info[c->buffer->i].codepoint, &mark_x, &mark_y);
- glyph_anchor.get_anchor (c->layout, c->buffer->info[glyph_pos].codepoint, &base_x, &base_y);
+ mark_anchor.get_anchor (c->font, c->buffer->info[c->buffer->idx].codepoint, &mark_x, &mark_y);
+ glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, &base_x, &base_y);
- hb_glyph_position_t &o = c->buffer->pos[c->buffer->i];
+ hb_glyph_position_t &o = c->buffer->pos[c->buffer->idx];
o.x_offset = base_x - mark_x;
o.y_offset = base_y - mark_y;
- o.attach_lookback() = c->buffer->i - glyph_pos;
+ o.attach_lookback() = c->buffer->idx - glyph_pos;
- c->buffer->i++;
+ c->buffer->idx++;
return true;
}
@@ -432,13 +437,14 @@ struct SinglePosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
- valueFormat.apply_value (c->layout, this, values, c->buffer->pos[c->buffer->i]);
+ valueFormat.apply_value (c->font, c->direction, this,
+ values, c->buffer->pos[c->buffer->idx]);
- c->buffer->i++;
+ c->buffer->idx++;
return true;
}
@@ -471,18 +477,18 @@ struct SinglePosFormat2
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
if (likely (index >= valueCount))
return false;
- valueFormat.apply_value (c->layout, this,
+ valueFormat.apply_value (c->font, c->direction, this,
&values[index * valueFormat.get_len ()],
- c->buffer->pos[c->buffer->i]);
+ c->buffer->pos[c->buffer->idx]);
- c->buffer->i++;
+ c->buffer->idx++;
return true;
}
@@ -574,11 +580,13 @@ struct PairSet
{
if (c->buffer->info[pos].codepoint == record->secondGlyph)
{
- valueFormats[0].apply_value (c->layout, this, &record->values[0], c->buffer->pos[c->buffer->i]);
- valueFormats[1].apply_value (c->layout, this, &record->values[len1], c->buffer->pos[pos]);
+ valueFormats[0].apply_value (c->font, c->direction, this,
+ &record->values[0], c->buffer->pos[c->buffer->idx]);
+ valueFormats[1].apply_value (c->font, c->direction, this,
+ &record->values[len1], c->buffer->pos[pos]);
if (len2)
pos++;
- c->buffer->i = pos;
+ c->buffer->idx = pos;
return true;
}
record = &StructAtOffset<PairValueRecord> (record, record_size);
@@ -621,23 +629,18 @@ struct PairPosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length);
- if (unlikely (c->buffer->i + 2 > end))
+ hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
+ if (skippy_iter.has_no_chance ())
return false;
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
- unsigned int j = c->buffer->i + 1;
- while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
- {
- if (unlikely (j == end))
- return false;
- j++;
- }
+ if (!skippy_iter.next ())
+ return false;
- return (this+pairSet[index]).apply (c, &valueFormat1, j);
+ return (this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx);
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -683,38 +686,35 @@ struct PairPosFormat2
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length);
- if (unlikely (c->buffer->i + 2 > end))
+ hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
+ if (skippy_iter.has_no_chance ())
return false;
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
- unsigned int j = c->buffer->i + 1;
- while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
- {
- if (unlikely (j == end))
- return false;
- j++;
- }
+ if (!skippy_iter.next ())
+ return false;
unsigned int len1 = valueFormat1.get_len ();
unsigned int len2 = valueFormat2.get_len ();
unsigned int record_len = len1 + len2;
- unsigned int klass1 = (this+classDef1) (c->buffer->info[c->buffer->i].codepoint);
- unsigned int klass2 = (this+classDef2) (c->buffer->info[j].codepoint);
+ unsigned int klass1 = (this+classDef1) (c->buffer->info[c->buffer->idx].codepoint);
+ unsigned int klass2 = (this+classDef2) (c->buffer->info[skippy_iter.idx].codepoint);
if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
return false;
const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
- valueFormat1.apply_value (c->layout, this, v, c->buffer->pos[c->buffer->i]);
- valueFormat2.apply_value (c->layout, this, v + len1, c->buffer->pos[j]);
+ valueFormat1.apply_value (c->font, c->direction, this,
+ v, c->buffer->pos[c->buffer->idx]);
+ valueFormat2.apply_value (c->font, c->direction, this,
+ v + len1, c->buffer->pos[skippy_iter.idx]);
+ c->buffer->idx = skippy_iter.idx;
if (len2)
- j++;
- c->buffer->i = j;
+ c->buffer->idx++;
return true;
}
@@ -836,69 +836,82 @@ struct CursivePosFormat1
if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)
return false;
- unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length);
- if (unlikely (c->buffer->i + 2 > end))
+ hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
+ if (skippy_iter.has_no_chance ())
return false;
- const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->info[c->buffer->i].codepoint)];
+ const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->info[c->buffer->idx].codepoint)];
if (!this_record.exitAnchor)
return false;
- unsigned int j = c->buffer->i + 1;
- while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
- {
- if (unlikely (j == end))
- return false;
- j++;
- }
+ if (!skippy_iter.next ())
+ return false;
- const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buffer->info[j].codepoint)];
+ const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buffer->info[skippy_iter.idx].codepoint)];
if (!next_record.entryAnchor)
return false;
- unsigned int i = c->buffer->i;
+ unsigned int i = c->buffer->idx;
+ unsigned int j = skippy_iter.idx;
hb_position_t entry_x, entry_y, exit_x, exit_y;
- (this+this_record.exitAnchor).get_anchor (c->layout, c->buffer->info[i].codepoint, &exit_x, &exit_y);
- (this+next_record.entryAnchor).get_anchor (c->layout, c->buffer->info[j].codepoint, &entry_x, &entry_y);
-
- hb_direction_t direction = c->buffer->props.direction;
-
- /* Align the exit anchor of the left/top glyph with the entry anchor of the right/bottom glyph
- * by adjusting advance of the left/top glyph. */
- if (HB_DIRECTION_IS_BACKWARD (direction))
- {
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
- c->buffer->pos[j].x_advance = c->buffer->pos[j].x_offset + entry_x - exit_x;
- else
- c->buffer->pos[j].y_advance = c->buffer->pos[j].y_offset + entry_y - exit_y;
- }
- else
- {
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
- c->buffer->pos[i].x_advance = c->buffer->pos[i].x_offset + exit_x - entry_x;
- else
- c->buffer->pos[i].y_advance = c->buffer->pos[i].y_offset + exit_y - entry_y;
+ (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepoint, &exit_x, &exit_y);
+ (this+next_record.entryAnchor).get_anchor (c->font, c->buffer->info[j].codepoint, &entry_x, &entry_y);
+
+ hb_glyph_position_t *pos = c->buffer->pos;
+
+ hb_position_t d;
+ /* Main-direction adjustment */
+ switch (c->direction) {
+ case HB_DIRECTION_LTR:
+ pos[i].x_advance = exit_x + pos[i].x_offset;
+
+ d = entry_x + pos[j].x_offset;
+ pos[j].x_advance -= d;
+ pos[j].x_offset -= d;
+ break;
+ case HB_DIRECTION_RTL:
+ d = exit_x + pos[i].x_offset;
+ pos[i].x_advance -= d;
+ pos[i].x_offset -= d;
+
+ pos[j].x_advance = entry_x + pos[j].x_offset;
+ break;
+ case HB_DIRECTION_TTB:
+ pos[i].y_advance = exit_y + pos[i].y_offset;
+
+ d = entry_y + pos[j].y_offset;
+ pos[j].y_advance -= d;
+ pos[j].y_offset -= d;
+ break;
+ case HB_DIRECTION_BTT:
+ d = exit_y + pos[i].y_offset;
+ pos[i].y_advance -= d;
+ pos[i].y_offset -= d;
+
+ pos[j].y_advance = entry_y;
+ break;
+ case HB_DIRECTION_INVALID:
+ default:
+ break;
}
- if (c->lookup_props & LookupFlag::RightToLeft)
- {
- c->buffer->pos[i].cursive_chain() = j - i;
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
- c->buffer->pos[i].y_offset = entry_y - exit_y;
+ /* Cross-direction adjustment */
+ if (c->lookup_props & LookupFlag::RightToLeft) {
+ pos[i].cursive_chain() = j - i;
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
+ pos[i].y_offset = entry_y - exit_y;
else
- c->buffer->pos[i].x_offset = entry_x - exit_x;
- }
- else
- {
- c->buffer->pos[j].cursive_chain() = i - j;
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
- c->buffer->pos[j].y_offset = exit_y - entry_y;
+ pos[i].x_offset = entry_x - exit_x;
+ } else {
+ pos[j].cursive_chain() = i - j;
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
+ pos[j].y_offset = exit_y - entry_y;
else
- c->buffer->pos[j].x_offset = exit_x - entry_x;
+ pos[j].x_offset = exit_x - entry_x;
}
- c->buffer->i = j;
+ c->buffer->idx = j;
return true;
}
@@ -964,29 +977,25 @@ struct MarkBasePosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (mark_index == NOT_COVERED))
return false;
/* now we search backwards for a non-mark glyph */
unsigned int property;
- unsigned int j = c->buffer->i;
- do
- {
- if (unlikely (!j))
- return false;
- j--;
- } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], LookupFlag::IgnoreMarks, &property));
+ hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
+ if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks))
+ return false;
/* The following assertion is too strong, so we've disabled it. */
if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH))
{/*return false;*/}
- unsigned int base_index = (this+baseCoverage) (c->buffer->info[j].codepoint);
+ unsigned int base_index = (this+baseCoverage) (c->buffer->info[skippy_iter.idx].codepoint);
if (base_index == NOT_COVERED)
return false;
- return (this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, j);
+ return (this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx);
}
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -1066,24 +1075,21 @@ struct MarkLigPosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int mark_index = (this+markCoverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (mark_index == NOT_COVERED))
return false;
/* now we search backwards for a non-mark glyph */
unsigned int property;
- unsigned int j = c->buffer->i;
- do
- {
- if (unlikely (!j))
- return false;
- j--;
- } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], LookupFlag::IgnoreMarks, &property));
+ hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
+ if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks))
+ return false;
/* The following assertion is too strong, so we've disabled it. */
if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE))
{/*return false;*/}
+ unsigned int j = skippy_iter.idx;
unsigned int lig_index = (this+ligatureCoverage) (c->buffer->info[j].codepoint);
if (lig_index == NOT_COVERED)
return false;
@@ -1100,9 +1106,9 @@ struct MarkLigPosFormat1
* is identical to the ligature ID of the found ligature. If yes, we
* can directly use the component index. If not, we attach the mark
* glyph to the last component of the ligature. */
- if (c->buffer->info[j].lig_id() && c->buffer->info[j].lig_id() == c->buffer->info[c->buffer->i].lig_id() && c->buffer->info[c->buffer->i].lig_comp())
+ if (c->buffer->info[j].lig_id() && c->buffer->info[j].lig_id() == c->buffer->info[c->buffer->idx].lig_id() && c->buffer->info[c->buffer->idx].lig_comp())
{
- comp_index = c->buffer->info[c->buffer->i].lig_comp() - 1;
+ comp_index = c->buffer->info[c->buffer->idx].lig_comp() - 1;
if (comp_index >= comp_count)
comp_index = comp_count - 1;
}
@@ -1185,28 +1191,26 @@ struct MarkMarkPosFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int mark1_index = (this+mark1Coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int mark1_index = (this+mark1Coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (mark1_index == NOT_COVERED))
return false;
/* now we search backwards for a suitable mark glyph until a non-mark glyph */
unsigned int property;
- unsigned int j = c->buffer->i;
- do
- {
- if (unlikely (!j))
- return false;
- j--;
- } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, &property));
+ hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
+ if (!skippy_iter.prev (&property))
+ return false;
if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK))
return false;
+ unsigned int j = skippy_iter.idx;
+
/* Two marks match only if they belong to the same base, or same component
* of the same ligature. That is, the component numbers must match, and
* if those are non-zero, the ligid number should also match. */
- if ((c->buffer->info[j].lig_comp() != c->buffer->info[c->buffer->i].lig_comp()) ||
- (c->buffer->info[j].lig_comp() && c->buffer->info[j].lig_id() != c->buffer->info[c->buffer->i].lig_id()))
+ if ((c->buffer->info[j].lig_comp() != c->buffer->info[c->buffer->idx].lig_comp()) ||
+ (c->buffer->info[j].lig_comp() && c->buffer->info[j].lig_id() != c->buffer->info[c->buffer->idx].lig_id()))
return false;
unsigned int mark2_index = (this+mark2Coverage) (c->buffer->info[j].codepoint);
@@ -1277,9 +1281,7 @@ struct MarkMarkPos
};
-HB_BEGIN_DECLS
static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index);
-HB_END_DECLS
struct ContextPos : Context
{
@@ -1402,7 +1404,7 @@ struct PosLookup : Lookup
inline const PosLookupSubTable& get_subtable (unsigned int i) const
{ return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
- inline bool apply_once (hb_ot_layout_context_t *layout,
+ inline bool apply_once (hb_font_t *font,
hb_buffer_t *buffer,
hb_mask_t lookup_mask,
unsigned int context_length,
@@ -1411,14 +1413,16 @@ struct PosLookup : Lookup
unsigned int lookup_type = get_type ();
hb_apply_context_t c[1] = {{0}};
- c->layout = layout;
+ c->font = font;
+ c->face = font->face;
c->buffer = buffer;
+ c->direction = buffer->props.direction;
c->lookup_mask = lookup_mask;
c->context_length = context_length;
c->nesting_level_left = nesting_level_left;
c->lookup_props = get_props ();
- if (!_hb_ot_layout_check_glyph_property (c->layout->face, &c->buffer->info[c->buffer->i], c->lookup_props, &c->property))
+ if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->info[c->buffer->idx], c->lookup_props, &c->property))
return false;
for (unsigned int i = 0; i < get_subtable_count (); i++)
@@ -1428,7 +1432,7 @@ struct PosLookup : Lookup
return false;
}
- inline bool apply_string (hb_ot_layout_context_t *layout,
+ inline bool apply_string (hb_font_t *font,
hb_buffer_t *buffer,
hb_mask_t mask) const
{
@@ -1437,14 +1441,14 @@ struct PosLookup : Lookup
if (unlikely (!buffer->len))
return false;
- buffer->i = 0;
- while (buffer->i < buffer->len)
+ buffer->idx = 0;
+ while (buffer->idx < buffer->len)
{
- if ((buffer->info[buffer->i].mask & mask) &&
- apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
+ if ((buffer->info[buffer->idx].mask & mask) &&
+ apply_once (font, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
ret = true;
else
- buffer->i++;
+ buffer->idx++;
}
return ret;
@@ -1461,7 +1465,7 @@ struct PosLookup : Lookup
typedef OffsetListOf<PosLookup> PosLookupList;
/*
- * GPOS
+ * GPOS -- The Glyph Positioning Table
*/
struct GPOS : GSUBGPOS
@@ -1471,12 +1475,13 @@ struct GPOS : GSUBGPOS
inline const PosLookup& get_lookup (unsigned int i) const
{ return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
- inline bool position_lookup (hb_ot_layout_context_t *layout,
+ inline bool position_lookup (hb_font_t *font,
hb_buffer_t *buffer,
unsigned int lookup_index,
hb_mask_t mask) const
- { return get_lookup (lookup_index).apply_string (layout, buffer, mask); }
+ { return get_lookup (lookup_index).apply_string (font, buffer, mask); }
+ static inline void position_start (hb_buffer_t *buffer);
static inline void position_finish (hb_buffer_t *buffer);
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -1489,61 +1494,79 @@ struct GPOS : GSUBGPOS
DEFINE_SIZE_STATIC (10);
};
-void
-GPOS::position_finish (hb_buffer_t *buffer)
+
+static void
+fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
{
- unsigned int i, j;
- unsigned int len = hb_buffer_get_length (buffer);
- hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer);
- hb_direction_t direction = buffer->props.direction;
+ unsigned int j = pos[i].cursive_chain();
+ if (likely (!j))
+ return;
- /* Handle cursive connections:
- * First handle all chain-back connections, then handle all chain-forward connections. */
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
- {
- for (j = 0; j < len; j++) {
- if (pos[j].cursive_chain() < 0)
- pos[j].y_offset += pos[j + pos[j].cursive_chain()].y_offset;
- }
- for (i = len; i > 0; i--) {
- j = i - 1;
- if (pos[j].cursive_chain() > 0)
- pos[j].y_offset += pos[j + pos[j].cursive_chain()].y_offset;
+ j += i;
+
+ pos[i].cursive_chain() = 0;
+
+ fix_cursive_minor_offset (pos, j, direction);
+
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ pos[i].y_offset += pos[j].y_offset;
+ else
+ pos[i].x_offset += pos[j].x_offset;
+}
+
+static void
+fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
+{
+ if (likely (!(pos[i].attach_lookback())))
+ return;
+
+ unsigned int j = i - pos[i].attach_lookback();
+
+ pos[i].x_advance = 0;
+ pos[i].y_advance = 0;
+ pos[i].x_offset += pos[j].x_offset;
+ pos[i].y_offset += pos[j].y_offset;
+
+ 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 (j = 0; j < len; j++) {
- if (pos[j].cursive_chain() < 0)
- pos[j].x_offset += pos[j + pos[j].cursive_chain()].x_offset;
- }
- for (i = len; i > 0; i--) {
- j = i - 1;
- if (pos[j].cursive_chain() > 0)
- pos[j].x_offset += pos[j + pos[j].cursive_chain()].x_offset;
+ 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;
}
- }
+}
+
+void
+GPOS::position_start (hb_buffer_t *buffer)
+{
+ buffer->clear_positions ();
+
+ unsigned int count = buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ buffer->pos[i].attach_lookback() = buffer->pos[i].cursive_chain() = 0;
+}
+
+void
+GPOS::position_finish (hb_buffer_t *buffer)
+{
+ unsigned int len;
+ hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
+ hb_direction_t direction = buffer->props.direction;
+ /* Handle cursive connections */
+ for (unsigned int i = 0; i < len; i++)
+ fix_cursive_minor_offset (pos, i, direction);
/* Handle attachments */
- for (i = 0; i < len; i++)
- if (pos[i].attach_lookback())
- {
- unsigned int back = i - pos[i].attach_lookback();
- pos[i].x_offset += pos[back].x_offset;
- pos[i].y_offset += pos[back].y_offset;
-
- if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
- for (j = back + 1; j < i + 1; j++) {
- pos[i].x_offset += pos[j].x_advance;
- pos[i].y_offset += pos[j].y_advance;
- }
- else
- for (j = back; j < i; j++) {
- pos[i].x_offset -= pos[j].x_advance;
- pos[i].y_offset -= pos[j].y_advance;
- }
- }
+ for (unsigned int i = 0; i < len; i++)
+ fix_mark_attachment (pos, i, direction);
+
+ HB_BUFFER_DEALLOCATE_VAR (buffer, lig_comp);
+ HB_BUFFER_DEALLOCATE_VAR (buffer, lig_id);
+ HB_BUFFER_DEALLOCATE_VAR (buffer, props_cache);
}
@@ -1566,7 +1589,7 @@ inline bool ExtensionPos::sanitize (hb_sanitize_context_t *c)
static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index)
{
- const GPOS &gpos = *(c->layout->face->ot_layout->gpos);
+ const GPOS &gpos = *(c->face->ot_layout->gpos);
const PosLookup &l = gpos.get_lookup (lookup_index);
if (unlikely (c->nesting_level_left == 0))
@@ -1575,7 +1598,7 @@ static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
if (unlikely (c->context_length < 1))
return false;
- return l.apply_once (c->layout, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
+ return l.apply_once (c->font, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
}
@@ -1583,6 +1606,5 @@ static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
#undef cursive_chain
-HB_END_DECLS
-#endif /* HB_OT_LAYOUT_GPOS_PRIVATE_HH */
+#endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
index ae1c5f3..f7ec3cc 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2007,2008,2009,2010 Red Hat, Inc.
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
+ * Copyright © 2010 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -26,12 +26,11 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_LAYOUT_GSUB_PRIVATE_HH
-#define HB_OT_LAYOUT_GSUB_PRIVATE_HH
+#ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
+#define HB_OT_LAYOUT_GSUB_TABLE_HH
#include "hb-ot-layout-gsubgpos-private.hh"
-HB_BEGIN_DECLS
struct SingleSubstFormat1
@@ -43,12 +42,14 @@ struct SingleSubstFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint;
+ hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint;
unsigned int index = (this+coverage) (glyph_id);
if (likely (index == NOT_COVERED))
return false;
- glyph_id += deltaGlyphID;
+ /* According to the Adobe Annotated OpenType Suite, result is always
+ * limited to 16bit. */
+ glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF;
c->replace_glyph (glyph_id);
return true;
@@ -80,7 +81,7 @@ struct SingleSubstFormat2
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint;
+ hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint;
unsigned int index = (this+coverage) (glyph_id);
if (likely (index == NOT_COVERED))
return false;
@@ -188,7 +189,7 @@ struct MultipleSubstFormat1
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
@@ -257,8 +258,8 @@ struct AlternateSubstFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint;
- hb_mask_t glyph_mask = c->buffer->info[c->buffer->i].mask;
+ hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint;
+ hb_mask_t glyph_mask = c->buffer->info[c->buffer->idx].mask;
hb_mask_t lookup_mask = c->lookup_mask;
unsigned int index = (this+coverage) (glyph_id);
@@ -342,28 +343,27 @@ struct Ligature
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- unsigned int i, j;
unsigned int count = component.len;
- unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length);
- if (unlikely (count < 2 || c->buffer->i + count > end))
+ if (unlikely (count < 2))
+ return false;
+
+ hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
+ if (skippy_iter.has_no_chance ())
return false;
bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
bool found_non_mark = false;
- for (i = 1, j = c->buffer->i + 1; i < count; i++, j++)
+ for (unsigned int i = 1; i < count; i++)
{
unsigned int property;
- while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, &property))
- {
- if (unlikely (j + count - i == end))
- return false;
- j++;
- }
+
+ if (!skippy_iter.next (&property))
+ return false;
found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
- if (likely (c->buffer->info[j].codepoint != component[i]))
+ if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i]))
return false;
}
@@ -372,12 +372,12 @@ struct Ligature
/* Allocate new ligature id */
unsigned int lig_id = allocate_lig_id (c->buffer);
- c->buffer->info[c->buffer->i].lig_comp() = 0;
- c->buffer->info[c->buffer->i].lig_id() = lig_id;
+ c->buffer->info[c->buffer->idx].lig_comp() = 0;
+ c->buffer->info[c->buffer->idx].lig_id() = lig_id;
- if (j == c->buffer->i + i) /* No input glyphs skipped */
+ if (skippy_iter.idx < c->buffer->idx + count) /* No input glyphs skipped */
{
- c->replace_glyphs_be16 (i, 1, (const uint16_t *) &ligGlyph);
+ c->replace_glyphs_be16 (count, 1, (const uint16_t *) &ligGlyph);
}
else
{
@@ -390,29 +390,23 @@ struct Ligature
value it is later possible to check whether a specific
component value really belongs to a given ligature. */
- for (i = 1; i < count; i++)
+ for (unsigned int i = 1; i < count; i++)
{
- while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[c->buffer->i], c->lookup_props, NULL))
+ while (c->should_mark_skip_current_glyph ())
{
- c->buffer->info[c->buffer->i].lig_comp() = i;
- c->buffer->info[c->buffer->i].lig_id() = lig_id;
- c->replace_glyph (c->buffer->info[c->buffer->i].codepoint);
+ c->buffer->info[c->buffer->idx].lig_comp() = i;
+ c->buffer->info[c->buffer->idx].lig_id() = lig_id;
+ c->replace_glyph (c->buffer->info[c->buffer->idx].codepoint);
}
/* Skip the base glyph */
- c->buffer->i++;
+ c->buffer->idx++;
}
}
return true;
}
- inline uint16_t allocate_lig_id (hb_buffer_t *buffer) const {
- uint16_t lig_id = buffer->next_serial ();
- if (unlikely (!lig_id)) lig_id = buffer->next_serial (); /* in case of overflows */
- return lig_id;
- }
-
public:
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
@@ -471,7 +465,7 @@ struct LigatureSubstFormat1
inline bool apply (hb_apply_context_t *c) const
{
TRACE_APPLY ();
- hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint;
+ hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint;
unsigned int index = (this+coverage) (glyph_id);
if (likely (index == NOT_COVERED))
@@ -530,9 +524,7 @@ struct LigatureSubst
};
-HB_BEGIN_DECLS
static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index);
-HB_END_DECLS
struct ContextSubst : Context
{
@@ -591,7 +583,7 @@ struct ReverseChainSingleSubstFormat1
if (unlikely (c->context_length != NO_CONTEXT))
return false; /* No chaining to this type */
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
@@ -606,8 +598,8 @@ struct ReverseChainSingleSubstFormat1
match_coverage, this,
1))
{
- c->buffer->info[c->buffer->i].codepoint = substitute[index];
- c->buffer->i--; /* Reverse! */
+ c->buffer->info[c->buffer->idx].codepoint = substitute[index];
+ c->buffer->idx--; /* Reverse! */
return true;
}
@@ -762,7 +754,7 @@ struct SubstLookup : Lookup
}
- inline bool apply_once (hb_ot_layout_context_t *layout,
+ inline bool apply_once (hb_face_t *face,
hb_buffer_t *buffer,
hb_mask_t lookup_mask,
unsigned int context_length,
@@ -771,14 +763,15 @@ struct SubstLookup : Lookup
unsigned int lookup_type = get_type ();
hb_apply_context_t c[1] = {{0}};
- c->layout = layout;
+ c->face = face;
c->buffer = buffer;
+ c->direction = buffer->props.direction;
c->lookup_mask = lookup_mask;
c->context_length = context_length;
c->nesting_level_left = nesting_level_left;
c->lookup_props = get_props ();
- if (!_hb_ot_layout_check_glyph_property (c->layout->face, &c->buffer->info[c->buffer->i], c->lookup_props, &c->property))
+ if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->info[c->buffer->idx], c->lookup_props, &c->property))
return false;
if (unlikely (lookup_type == SubstLookupSubTable::Extension))
@@ -803,7 +796,7 @@ struct SubstLookup : Lookup
return false;
}
- inline bool apply_string (hb_ot_layout_context_t *layout,
+ inline bool apply_string (hb_face_t *face,
hb_buffer_t *buffer,
hb_mask_t mask) const
{
@@ -816,33 +809,33 @@ struct SubstLookup : Lookup
{
/* in/out forward substitution */
buffer->clear_output ();
- buffer->i = 0;
- while (buffer->i < buffer->len)
+ buffer->idx = 0;
+ while (buffer->idx < buffer->len)
{
- if ((buffer->info[buffer->i].mask & mask) &&
- apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
+ if ((buffer->info[buffer->idx].mask & mask) &&
+ apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
ret = true;
else
buffer->next_glyph ();
}
if (ret)
- buffer->swap ();
+ buffer->swap_buffers ();
}
else
{
/* in-place backward substitution */
- buffer->i = buffer->len - 1;
+ buffer->idx = buffer->len - 1;
do
{
- if ((buffer->info[buffer->i].mask & mask) &&
- apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
+ if ((buffer->info[buffer->idx].mask & mask) &&
+ apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
ret = true;
else
- buffer->i--;
+ buffer->idx--;
}
- while ((int) buffer->i >= 0);
+ while ((int) buffer->idx >= 0);
}
return ret;
@@ -859,7 +852,7 @@ struct SubstLookup : Lookup
typedef OffsetListOf<SubstLookup> SubstLookupList;
/*
- * GSUB
+ * GSUB -- The Glyph Substitution Table
*/
struct GSUB : GSUBGPOS
@@ -869,11 +862,14 @@ struct GSUB : GSUBGPOS
inline const SubstLookup& get_lookup (unsigned int i) const
{ return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
- inline bool substitute_lookup (hb_ot_layout_context_t *layout,
+ inline bool substitute_lookup (hb_face_t *face,
hb_buffer_t *buffer,
unsigned int lookup_index,
hb_mask_t mask) const
- { return get_lookup (lookup_index).apply_string (layout, buffer, mask); }
+ { return get_lookup (lookup_index).apply_string (face, buffer, mask); }
+
+ static inline void substitute_start (hb_buffer_t *buffer);
+ static inline void substitute_finish (hb_buffer_t *buffer);
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE ();
@@ -886,6 +882,24 @@ struct GSUB : GSUBGPOS
};
+void
+GSUB::substitute_start (hb_buffer_t *buffer)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, props_cache);
+ HB_BUFFER_ALLOCATE_VAR (buffer, lig_id);
+ HB_BUFFER_ALLOCATE_VAR (buffer, lig_comp);
+
+ unsigned int count = buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ buffer->info[i].props_cache() = buffer->info[i].lig_id() = buffer->info[i].lig_comp() = 0;
+}
+
+void
+GSUB::substitute_finish (hb_buffer_t *buffer)
+{
+}
+
+
/* Out-of-class implementation for methods recursing */
inline bool ExtensionSubst::apply (hb_apply_context_t *c) const
@@ -913,7 +927,7 @@ inline bool ExtensionSubst::is_reverse (void) const
static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index)
{
- const GSUB &gsub = *(c->layout->face->ot_layout->gsub);
+ const GSUB &gsub = *(c->face->ot_layout->gsub);
const SubstLookup &l = gsub.get_lookup (lookup_index);
if (unlikely (c->nesting_level_left == 0))
@@ -922,10 +936,9 @@ static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
if (unlikely (c->context_length < 1))
return false;
- return l.apply_once (c->layout, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
+ return l.apply_once (c->face, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
}
-HB_END_DECLS
-#endif /* HB_OT_LAYOUT_GSUB_PRIVATE_HH */
+#endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
index c2b2eea..13386c2 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2007,2008,2009,2010 Red Hat, Inc.
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
+ * Copyright © 2010 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -30,14 +30,19 @@
#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
#include "hb-buffer-private.hh"
-#include "hb-ot-layout-gdef-private.hh"
-
-HB_BEGIN_DECLS
+#include "hb-ot-layout-gdef-table.hh"
/* buffer var allocations */
-#define lig_id() var2.u16[0] /* unique ligature id */
-#define lig_comp() var2.u16[1] /* component number in the ligature (0 = base) */
+#define lig_id() var2.u8[2] /* unique ligature id */
+#define lig_comp() var2.u8[3] /* component number in the ligature (0 = base) */
+
+static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) {
+ uint8_t lig_id = buffer->next_serial ();
+ if (unlikely (!lig_id)) lig_id = buffer->next_serial (); /* in case of overflow */
+ return lig_id;
+}
+
#ifndef HB_DEBUG_APPLY
@@ -45,22 +50,107 @@ HB_BEGIN_DECLS
#endif
#define TRACE_APPLY() \
- hb_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", HB_FUNC, this); \
+ hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", this, NULL, HB_FUNC);
-HB_BEGIN_DECLS
struct hb_apply_context_t
{
unsigned int debug_depth;
- hb_ot_layout_context_t *layout;
+ hb_font_t *font;
+ hb_face_t *face;
hb_buffer_t *buffer;
+ hb_direction_t direction;
hb_mask_t lookup_mask;
unsigned int context_length;
unsigned int nesting_level_left;
unsigned int lookup_props;
unsigned int property; /* propety of first glyph */
+ struct mark_skipping_forward_iterator_t
+ {
+ inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_,
+ unsigned int start_index_,
+ unsigned int num_items_)
+ {
+ c = c_;
+ idx = start_index_;
+ num_items = num_items_;
+ end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
+ }
+ inline bool has_no_chance (void) const
+ {
+ return unlikely (num_items && idx + num_items >= end);
+ }
+ inline bool next (unsigned int *property_out,
+ unsigned int lookup_props)
+ {
+ assert (num_items > 0);
+ do
+ {
+ if (has_no_chance ())
+ return false;
+ idx++;
+ } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[idx], lookup_props, property_out));
+ num_items--;
+ return true;
+ }
+ inline bool next (unsigned int *property_out = NULL)
+ {
+ return next (property_out, c->lookup_props);
+ }
+
+ unsigned int idx;
+ private:
+ hb_apply_context_t *c;
+ unsigned int num_items;
+ unsigned int end;
+ };
+
+ struct mark_skipping_backward_iterator_t
+ {
+ inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_,
+ unsigned int start_index_,
+ unsigned int num_items_)
+ {
+ c = c_;
+ idx = start_index_;
+ num_items = num_items_;
+ }
+ inline bool has_no_chance (void) const
+ {
+ return unlikely (idx < num_items);
+ }
+ inline bool prev (unsigned int *property_out,
+ unsigned int lookup_props)
+ {
+ assert (num_items > 0);
+ do
+ {
+ if (has_no_chance ())
+ return false;
+ idx--;
+ } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->out_info[idx], lookup_props, property_out));
+ num_items--;
+ return true;
+ }
+ inline bool prev (unsigned int *property_out = NULL)
+ {
+ return prev (property_out, c->lookup_props);
+ }
+
+ unsigned int idx;
+ private:
+ hb_apply_context_t *c;
+ unsigned int num_items;
+ };
+
+ inline bool should_mark_skip_current_glyph (void) const
+ {
+ return _hb_ot_layout_skip_mark (face, &buffer->info[buffer->idx], lookup_props, NULL);
+ }
+
+
inline void replace_glyph (hb_codepoint_t glyph_index) const
{
@@ -78,14 +168,14 @@ struct hb_apply_context_t
inline void guess_glyph_class (unsigned int klass)
{
/* XXX if ! has gdef */
- buffer->info[buffer->i].props_cache() = klass;
+ buffer->info[buffer->idx].props_cache() = klass;
}
private:
inline void clear_property (void) const
{
/* XXX if has gdef */
- buffer->info[buffer->i].props_cache() = 0;
+ buffer->info[buffer->idx].props_cache() = 0;
}
};
@@ -126,25 +216,20 @@ static inline bool match_input (hb_apply_context_t *c,
const void *match_data,
unsigned int *context_length_out)
{
- unsigned int i, j;
- unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length);
- if (unlikely (c->buffer->i + count > end))
+ hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
+ if (skippy_iter.has_no_chance ())
return false;
- for (i = 1, j = c->buffer->i + 1; i < count; i++, j++)
+ for (unsigned int i = 1; i < count; i++)
{
- while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
- {
- if (unlikely (j + count - i == end))
- return false;
- j++;
- }
+ if (!skippy_iter.next ())
+ return false;
- if (likely (!match_func (c->buffer->info[j].codepoint, input[i - 1], match_data)))
+ if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data)))
return false;
}
- *context_length_out = j - c->buffer->i;
+ *context_length_out = skippy_iter.idx - c->buffer->idx + 1;
return true;
}
@@ -155,19 +240,16 @@ static inline bool match_backtrack (hb_apply_context_t *c,
match_func_t match_func,
const void *match_data)
{
- if (unlikely (c->buffer->out_len < count))
+ hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count);
+ if (skippy_iter.has_no_chance ())
return false;
- for (unsigned int i = 0, j = c->buffer->out_len - 1; i < count; i++, j--)
+ for (unsigned int i = 0; i < count; i++)
{
- while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->out_info[j], c->lookup_props, NULL))
- {
- if (unlikely (j + 1 == count - i))
- return false;
- j--;
- }
+ if (!skippy_iter.prev ())
+ return false;
- if (likely (!match_func (c->buffer->out_info[j].codepoint, backtrack[i], match_data)))
+ if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data)))
return false;
}
@@ -181,28 +263,22 @@ static inline bool match_lookahead (hb_apply_context_t *c,
const void *match_data,
unsigned int offset)
{
- unsigned int i, j;
- unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length);
- if (unlikely (c->buffer->i + offset + count > end))
+ hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count);
+ if (skippy_iter.has_no_chance ())
return false;
- for (i = 0, j = c->buffer->i + offset; i < count; i++, j++)
+ for (unsigned int i = 0; i < count; i++)
{
- while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
- {
- if (unlikely (j + count - i == end))
- return false;
- j++;
- }
+ if (!skippy_iter.next ())
+ return false;
- if (likely (!match_func (c->buffer->info[j].codepoint, lookahead[i], match_data)))
+ if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data)))
return false;
}
return true;
}
-HB_END_DECLS
struct LookupRecord
@@ -221,7 +297,6 @@ struct LookupRecord
};
-HB_BEGIN_DECLS
static inline bool apply_lookup (hb_apply_context_t *c,
unsigned int count, /* Including the first glyph */
@@ -229,8 +304,8 @@ static inline bool apply_lookup (hb_apply_context_t *c,
const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
apply_lookup_func_t apply_func)
{
- unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length);
- if (unlikely (count == 0 || c->buffer->i + count > end))
+ unsigned int end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
+ if (unlikely (count == 0 || c->buffer->idx + count > end))
return false;
/* TODO We don't support lookupRecord arrays that are not increasing:
@@ -242,17 +317,19 @@ static inline bool apply_lookup (hb_apply_context_t *c,
*/
for (unsigned int i = 0; i < count; /* NOP */)
{
- while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[c->buffer->i], c->lookup_props, NULL))
+ if (unlikely (c->buffer->idx == end))
+ return true;
+ while (c->should_mark_skip_current_glyph ())
{
- if (unlikely (c->buffer->i == end))
- return true;
/* No lookup applied for this index */
c->buffer->next_glyph ();
+ if (unlikely (c->buffer->idx == end))
+ return true;
}
if (lookupCount && i == lookupRecord->sequenceIndex)
{
- unsigned int old_pos = c->buffer->i;
+ unsigned int old_pos = c->buffer->idx;
/* Apply a lookup */
bool done = apply_func (c, lookupRecord->lookupListIndex);
@@ -260,8 +337,8 @@ static inline bool apply_lookup (hb_apply_context_t *c,
lookupRecord++;
lookupCount--;
/* Err, this is wrong if the lookup jumped over some glyphs */
- i += c->buffer->i - old_pos;
- if (unlikely (c->buffer->i == end))
+ i += c->buffer->idx - old_pos;
+ if (unlikely (c->buffer->idx == end))
return true;
if (!done)
@@ -279,7 +356,6 @@ static inline bool apply_lookup (hb_apply_context_t *c,
return true;
}
-HB_END_DECLS
/* Contextual lookups */
@@ -383,7 +459,7 @@ struct ContextFormat1
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
@@ -422,12 +498,12 @@ struct ContextFormat2
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
const ClassDef &class_def = this+classDef;
- index = class_def (c->buffer->info[c->buffer->i].codepoint);
+ index = class_def (c->buffer->info[c->buffer->idx].codepoint);
const RuleSet &rule_set = this+ruleSet[index];
struct ContextLookupContext lookup_context = {
{match_class, apply_func},
@@ -467,7 +543,7 @@ struct ContextFormat3
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage[0]) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage[0]) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
@@ -562,8 +638,8 @@ static inline bool chain_context_lookup (hb_apply_context_t *c,
ChainContextLookupContext &lookup_context)
{
/* First guess */
- if (unlikely (c->buffer->out_len < backtrackCount ||
- c->buffer->i + inputCount + lookaheadCount > c->buffer->len ||
+ if (unlikely (c->buffer->backtrack_len () < backtrackCount ||
+ c->buffer->idx + inputCount + lookaheadCount > c->buffer->len ||
inputCount + lookaheadCount > c->context_length))
return false;
@@ -670,7 +746,7 @@ struct ChainContextFormat1
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
@@ -708,7 +784,7 @@ struct ChainContextFormat2
inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
{
TRACE_APPLY ();
- unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
@@ -716,7 +792,7 @@ struct ChainContextFormat2
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
- index = input_class_def (c->buffer->info[c->buffer->i].codepoint);
+ index = input_class_def (c->buffer->info[c->buffer->idx].codepoint);
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextLookupContext lookup_context = {
{match_class, apply_func},
@@ -771,7 +847,7 @@ struct ChainContextFormat3
TRACE_APPLY ();
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
- unsigned int index = (this+input[0]) (c->buffer->info[c->buffer->i].codepoint);
+ unsigned int index = (this+input[0]) (c->buffer->info[c->buffer->idx].codepoint);
if (likely (index == NOT_COVERED))
return false;
@@ -976,6 +1052,5 @@ struct GSUBGPOS
};
-HB_END_DECLS
#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
index b0088fb..bf7e43b 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -27,21 +27,22 @@
#ifndef HB_OT_LAYOUT_PRIVATE_HH
#define HB_OT_LAYOUT_PRIVATE_HH
-#include "hb-private.h"
+#include "hb-private.hh"
#include "hb-ot-layout.h"
-#include "hb-ot-head-private.hh"
-#include "hb-font-private.h"
+#include "hb-font-private.hh"
#include "hb-buffer-private.hh"
-HB_BEGIN_DECLS
+/*
+ * GDEF
+ */
+
/* buffer var allocations */
#define props_cache() var1.u16[1] /* glyph_props cache */
-
/* XXX cleanup */
typedef enum {
HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED = 0x0001,
@@ -52,6 +53,24 @@ typedef enum {
} hb_ot_layout_glyph_class_t;
+HB_INTERNAL unsigned int
+_hb_ot_layout_get_glyph_property (hb_face_t *face,
+ hb_glyph_info_t *info);
+
+HB_INTERNAL hb_bool_t
+_hb_ot_layout_check_glyph_property (hb_face_t *face,
+ hb_glyph_info_t *ginfo,
+ unsigned int lookup_props,
+ unsigned int *property_out);
+
+HB_INTERNAL hb_bool_t
+_hb_ot_layout_skip_mark (hb_face_t *face,
+ hb_glyph_info_t *ginfo,
+ unsigned int lookup_props,
+ unsigned int *property_out);
+
+
+
/*
* hb_ot_layout_t
*/
@@ -67,48 +86,13 @@ struct hb_ot_layout_t
const struct GPOS *gpos;
};
-struct hb_ot_layout_context_t
-{
- hb_face_t *face;
- hb_font_t *font;
-
- /* Convert from font-space to user-space */
- inline hb_position_t scale_x (int16_t v) { return scale (v, this->font->x_scale); }
- inline hb_position_t scale_y (int16_t v) { return scale (v, this->font->y_scale); }
-
- private:
- inline hb_position_t scale (int16_t v, unsigned int scale) { return v * (int64_t) scale / this->face->head_table->get_upem (); }
-};
-
HB_INTERNAL hb_ot_layout_t *
-_hb_ot_layout_new (hb_face_t *face);
+_hb_ot_layout_create (hb_face_t *face);
HB_INTERNAL void
-_hb_ot_layout_free (hb_ot_layout_t *layout);
-
-
-/*
- * GDEF
- */
-
-HB_INTERNAL unsigned int
-_hb_ot_layout_get_glyph_property (hb_face_t *face,
- hb_glyph_info_t *info);
-
-HB_INTERNAL hb_bool_t
-_hb_ot_layout_check_glyph_property (hb_face_t *face,
- hb_glyph_info_t *ginfo,
- unsigned int lookup_props,
- unsigned int *property_out);
-
-HB_INTERNAL hb_bool_t
-_hb_ot_layout_skip_mark (hb_face_t *face,
- hb_glyph_info_t *ginfo,
- unsigned int lookup_props,
- unsigned int *property_out);
+_hb_ot_layout_destroy (hb_ot_layout_t *layout);
-HB_END_DECLS
#endif /* HB_OT_LAYOUT_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.cc b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
index fc4b1d3..f3e0713 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 1998-2004 David Turner and Werner Lemberg
- * Copyright (C) 2006 Behdad Esfahbod
- * Copyright (C) 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 1998-2004 David Turner and Werner Lemberg
+ * Copyright © 2006 Behdad Esfahbod
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -26,46 +26,40 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#define HB_OT_LAYOUT_CC
-
#include "hb-ot-layout-private.hh"
-#include "hb-ot-layout-gdef-private.hh"
-#include "hb-ot-layout-gsub-private.hh"
-#include "hb-ot-layout-gpos-private.hh"
+#include "hb-ot-layout-gdef-table.hh"
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-maxp-table.hh"
#include <stdlib.h>
#include <string.h>
-HB_BEGIN_DECLS
hb_ot_layout_t *
-_hb_ot_layout_new (hb_face_t *face)
+_hb_ot_layout_create (hb_face_t *face)
{
- /* Remove this object altogether */
+ /* TODO Remove this object altogether */
hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
- layout->gdef_blob = Sanitizer<GDEF>::sanitize (hb_face_get_table (face, HB_OT_TAG_GDEF));
+ layout->gdef_blob = Sanitizer<GDEF>::sanitize (hb_face_reference_table (face, HB_OT_TAG_GDEF));
layout->gdef = Sanitizer<GDEF>::lock_instance (layout->gdef_blob);
- layout->gsub_blob = Sanitizer<GSUB>::sanitize (hb_face_get_table (face, HB_OT_TAG_GSUB));
+ layout->gsub_blob = Sanitizer<GSUB>::sanitize (hb_face_reference_table (face, HB_OT_TAG_GSUB));
layout->gsub = Sanitizer<GSUB>::lock_instance (layout->gsub_blob);
- layout->gpos_blob = Sanitizer<GPOS>::sanitize (hb_face_get_table (face, HB_OT_TAG_GPOS));
+ layout->gpos_blob = Sanitizer<GPOS>::sanitize (hb_face_reference_table (face, HB_OT_TAG_GPOS));
layout->gpos = Sanitizer<GPOS>::lock_instance (layout->gpos_blob);
return layout;
}
void
-_hb_ot_layout_free (hb_ot_layout_t *layout)
+_hb_ot_layout_destroy (hb_ot_layout_t *layout)
{
- hb_blob_unlock (layout->gdef_blob);
- hb_blob_unlock (layout->gsub_blob);
- hb_blob_unlock (layout->gpos_blob);
-
hb_blob_destroy (layout->gdef_blob);
hb_blob_destroy (layout->gsub_blob);
hb_blob_destroy (layout->gpos_blob);
@@ -78,13 +72,11 @@ _get_gdef (hb_face_t *face)
{
return likely (face->ot_layout && face->ot_layout->gdef) ? *face->ot_layout->gdef : Null(GDEF);
}
-
static inline const GSUB&
_get_gsub (hb_face_t *face)
{
return likely (face->ot_layout && face->ot_layout->gsub) ? *face->ot_layout->gsub : Null(GSUB);
}
-
static inline const GPOS&
_get_gpos (hb_face_t *face)
{
@@ -193,17 +185,13 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
unsigned int
hb_ot_layout_get_ligature_carets (hb_font_t *font,
- hb_face_t *face,
hb_direction_t direction,
hb_codepoint_t glyph,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
int *caret_array /* OUT */)
{
- hb_ot_layout_context_t c;
- c.font = font;
- c.face = face;
- return _get_gdef (face).get_lig_carets (&c, direction, glyph, start_offset, caret_count, caret_array);
+ return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
}
/*
@@ -263,27 +251,48 @@ hb_bool_t
hb_ot_layout_table_choose_script (hb_face_t *face,
hb_tag_t table_tag,
const hb_tag_t *script_tags,
- unsigned int *script_index)
+ unsigned int *script_index,
+ hb_tag_t *chosen_script)
{
ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
while (*script_tags)
{
- if (g.find_script_index (*script_tags, script_index))
+ if (g.find_script_index (*script_tags, script_index)) {
+ if (chosen_script)
+ *chosen_script = *script_tags;
return TRUE;
+ }
script_tags++;
}
/* try finding 'DFLT' */
- if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
+ if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) {
+ if (chosen_script)
+ *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT;
return FALSE;
+ }
/* try with 'dflt'; MS site has had typos and many fonts use it now :( */
- if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
+ if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) {
+ if (chosen_script)
+ *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE;
+ return FALSE;
+ }
+
+ /* try with 'latn'; some old fonts put their features there even though
+ they're really trying to support Thai, for example :( */
+#define HB_OT_TAG_LATIN_SCRIPT HB_TAG ('l', 'a', 't', 'n')
+ if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) {
+ if (chosen_script)
+ *chosen_script = HB_OT_TAG_LATIN_SCRIPT;
return FALSE;
+ }
if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
+ if (chosen_script)
+ *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
return FALSE;
}
@@ -439,16 +448,25 @@ hb_ot_layout_has_substitution (hb_face_t *face)
return &_get_gsub (face) != &Null(GSUB);
}
+void
+hb_ot_layout_substitute_start (hb_buffer_t *buffer)
+{
+ GSUB::substitute_start (buffer);
+}
+
hb_bool_t
hb_ot_layout_substitute_lookup (hb_face_t *face,
hb_buffer_t *buffer,
unsigned int lookup_index,
hb_mask_t mask)
{
- hb_ot_layout_context_t c;
- c.font = NULL;
- c.face = face;
- return _get_gsub (face).substitute_lookup (&c, buffer, lookup_index, mask);
+ return _get_gsub (face).substitute_lookup (face, buffer, lookup_index, mask);
+}
+
+void
+hb_ot_layout_substitute_finish (hb_buffer_t *buffer HB_UNUSED)
+{
+ GSUB::substitute_finish (buffer);
}
@@ -462,17 +480,19 @@ hb_ot_layout_has_positioning (hb_face_t *face)
return &_get_gpos (face) != &Null(GPOS);
}
+void
+hb_ot_layout_position_start (hb_buffer_t *buffer)
+{
+ GPOS::position_start (buffer);
+}
+
hb_bool_t
hb_ot_layout_position_lookup (hb_font_t *font,
- hb_face_t *face,
hb_buffer_t *buffer,
unsigned int lookup_index,
hb_mask_t mask)
{
- hb_ot_layout_context_t c;
- c.font = font;
- c.face = face;
- return _get_gpos (face).position_lookup (&c, buffer, lookup_index, mask);
+ return _get_gpos (font->face).position_lookup (font, buffer, lookup_index, mask);
}
void
@@ -482,4 +502,3 @@ hb_ot_layout_position_finish (hb_buffer_t *buffer)
}
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.h b/third_party/harfbuzz-ng/src/hb-ot-layout.h
index 9619eb7..447e35d 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout.h
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -59,12 +59,11 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
/* Ligature caret positions */
unsigned int
hb_ot_layout_get_ligature_carets (hb_font_t *font,
- hb_face_t *face,
hb_direction_t direction,
hb_codepoint_t glyph,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
- int *caret_array /* OUT */);
+ hb_position_t *caret_array /* OUT */);
/*
@@ -93,7 +92,8 @@ hb_bool_t
hb_ot_layout_table_choose_script (hb_face_t *face,
hb_tag_t table_tag,
const hb_tag_t *script_tags,
- unsigned int *script_index);
+ unsigned int *script_index,
+ hb_tag_t *chosen_script);
unsigned int
hb_ot_layout_table_get_feature_tags (hb_face_t *face,
@@ -166,12 +166,20 @@ hb_ot_layout_feature_get_lookup_indexes (hb_face_t *face,
hb_bool_t
hb_ot_layout_has_substitution (hb_face_t *face);
+/* Should be called before all the substitute_lookup's are done. */
+void
+hb_ot_layout_substitute_start (hb_buffer_t *buffer);
+
hb_bool_t
hb_ot_layout_substitute_lookup (hb_face_t *face,
hb_buffer_t *buffer,
unsigned int lookup_index,
hb_mask_t mask);
+/* Should be called after all the substitute_lookup's are done */
+void
+hb_ot_layout_substitute_finish (hb_buffer_t *buffer);
+
/*
* GPOS
*/
@@ -179,9 +187,12 @@ hb_ot_layout_substitute_lookup (hb_face_t *face,
hb_bool_t
hb_ot_layout_has_positioning (hb_face_t *face);
+/* Should be called before all the position_lookup's are done. Resets positions to zero. */
+void
+hb_ot_layout_position_start (hb_buffer_t *buffer);
+
hb_bool_t
hb_ot_layout_position_lookup (hb_font_t *font,
- hb_face_t *face,
hb_buffer_t *buffer,
unsigned int lookup_index,
hb_mask_t mask);
diff --git a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh b/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
index 0a1d9f6..710cc0a 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-map-private.hh
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2009,2010 Red Hat, Inc.
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2009,2010 Red Hat, Inc.
+ * Copyright © 2010,2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -33,32 +33,56 @@
#include "hb-ot-layout.h"
-HB_BEGIN_DECLS
-#define MAX_FEATURES 100 /* FIXME */
-#define MAX_LOOKUPS 1000 /* FIXME */
-
static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
-struct hb_ot_map_t {
+struct hb_ot_map_t
+{
+ friend struct hb_ot_map_builder_t;
- private:
+ public:
- struct feature_info_t {
- hb_tag_t tag;
- unsigned int seq; /* sequence#, used for stable sorting only */
- unsigned int max_value;
- bool global; /* whether the feature applies value to every glyph in the buffer */
- unsigned int default_value; /* for non-global features, what should the unset glyphs take */
+ hb_ot_map_t (void) { memset (this, 0, sizeof (*this)); }
- static int cmp (const feature_info_t *a, const feature_info_t *b)
- { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); }
- };
+ typedef void (*gsub_pause_func_t) (const hb_ot_map_t *map, hb_face_t *face, hb_buffer_t *buffer, void *user_data);
+ typedef void (*gpos_pause_func_t) (const hb_ot_map_t *map, hb_font_t *font, hb_buffer_t *buffer, void *user_data);
+
+ inline hb_mask_t get_global_mask (void) const { return global_mask; }
+
+ inline hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const {
+ const feature_map_t *map = features.bsearch (&tag);
+ if (shift) *shift = map ? map->shift : 0;
+ return map ? map->mask : 0;
+ }
+
+ inline hb_mask_t get_1_mask (hb_tag_t tag) const {
+ const feature_map_t *map = features.bsearch (&tag);
+ return map ? map->_1_mask : 0;
+ }
+
+ inline hb_tag_t get_chosen_script (unsigned int table_index) const
+ { return chosen_script[table_index]; }
+
+ inline void substitute (hb_face_t *face, hb_buffer_t *buffer) const
+ { apply (0, (hb_ot_map_t::apply_lookup_func_t) hb_ot_layout_substitute_lookup, face, buffer); }
+ inline void position (hb_font_t *font, hb_buffer_t *buffer) const
+ { apply (1, (hb_ot_map_t::apply_lookup_func_t) hb_ot_layout_position_lookup, font, buffer); }
+
+ inline void finish (void) {
+ features.finish ();
+ lookups[0].finish ();
+ lookups[1].finish ();
+ pauses[0].finish ();
+ pauses[1].finish ();
+ }
+
+ private:
struct feature_map_t {
hb_tag_t tag; /* should be first for our bsearch to work */
- unsigned int index[2]; /* GSUB, GPOS */
+ unsigned int index[2]; /* GSUB/GPOS */
+ unsigned int stage[2]; /* GSUB/GPOS */
unsigned int shift;
hb_mask_t mask;
hb_mask_t _1_mask; /* mask for value=1, for quick access */
@@ -75,69 +99,93 @@ struct hb_ot_map_t {
{ return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; }
};
+ typedef void (*pause_func_t) (const hb_ot_map_t *map, void *face_or_font, hb_buffer_t *buffer, void *user_data);
+ typedef struct {
+ pause_func_t func;
+ void *user_data;
+ } pause_callback_t;
+
+ struct pause_map_t {
+ unsigned int num_lookups; /* Cumulative */
+ pause_callback_t callback;
+ };
+
+ typedef hb_bool_t (*apply_lookup_func_t) (void *face_or_font,
+ hb_buffer_t *buffer,
+ unsigned int lookup_index,
+ hb_mask_t mask);
+
HB_INTERNAL void add_lookups (hb_face_t *face,
unsigned int table_index,
unsigned int feature_index,
hb_mask_t mask);
+ HB_INTERNAL void apply (unsigned int table_index,
+ hb_ot_map_t::apply_lookup_func_t apply_lookup_func,
+ void *face_or_font,
+ hb_buffer_t *buffer) const;
+ hb_mask_t global_mask;
+
+ hb_tag_t chosen_script[2];
+ hb_prealloced_array_t<feature_map_t, 8> features;
+ hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
+ hb_prealloced_array_t<pause_map_t, 1> pauses[2]; /* GSUB/GPOS */
+};
+
+
+struct hb_ot_map_builder_t
+{
public:
- hb_ot_map_t (void) : feature_count (0) {}
+ hb_ot_map_builder_t (void) { memset (this, 0, sizeof (*this)); }
- void add_feature (hb_tag_t tag, unsigned int value, bool global)
- {
- feature_info_t *info = &feature_infos[feature_count++];
- info->tag = tag;
- info->seq = feature_count;
- info->max_value = value;
- info->global = global;
- info->default_value = global ? value : 0;
- }
+ HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value, bool global);
inline void add_bool_feature (hb_tag_t tag, bool global = true)
{ add_feature (tag, 1, global); }
- HB_INTERNAL void compile (hb_face_t *face,
- const hb_segment_properties_t *props);
-
- inline hb_mask_t get_global_mask (void) const { return global_mask; }
+ inline void add_gsub_pause (hb_ot_map_t::gsub_pause_func_t pause_func, void *user_data)
+ { add_pause (0, (hb_ot_map_t::pause_func_t) pause_func, user_data); }
+ inline void add_gpos_pause (hb_ot_map_t::gpos_pause_func_t pause_func, void *user_data)
+ { add_pause (1, (hb_ot_map_t::pause_func_t) pause_func, user_data); }
- inline hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const {
- const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), (hb_compare_func_t) feature_map_t::cmp);
- if (shift) *shift = map ? map->shift : 0;
- return map ? map->mask : 0;
- }
+ HB_INTERNAL void compile (hb_face_t *face,
+ const hb_segment_properties_t *props,
+ struct hb_ot_map_t &m);
- inline hb_mask_t get_1_mask (hb_tag_t tag) const {
- const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), (hb_compare_func_t) feature_map_t::cmp);
- return map ? map->_1_mask : 0;
+ inline void finish (void) {
+ feature_infos.finish ();
+ pauses[0].finish ();
+ pauses[1].finish ();
}
- inline void substitute (hb_face_t *face, hb_buffer_t *buffer) const {
- for (unsigned int i = 0; i < lookup_count[0]; i++)
- hb_ot_layout_substitute_lookup (face, buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask);
- }
+ private:
- inline void position (hb_font_t *font, hb_face_t *face, hb_buffer_t *buffer) const {
- for (unsigned int i = 0; i < lookup_count[1]; i++)
- hb_ot_layout_position_lookup (font, face, buffer, lookup_maps[1][i].index, lookup_maps[1][i].mask);
- }
+ struct feature_info_t {
+ hb_tag_t tag;
+ unsigned int seq; /* sequence#, used for stable sorting only */
+ unsigned int max_value;
+ bool global; /* whether the feature applies value to every glyph in the buffer */
+ unsigned int default_value; /* for non-global features, what should the unset glyphs take */
+ unsigned int stage[2]; /* GSUB/GPOS */
- private:
+ static int cmp (const feature_info_t *a, const feature_info_t *b)
+ { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); }
+ };
- hb_mask_t global_mask;
+ struct pause_info_t {
+ unsigned int stage;
+ hb_ot_map_t::pause_callback_t callback;
+ };
- unsigned int feature_count;
- feature_info_t feature_infos[MAX_FEATURES]; /* used before compile() only */
- feature_map_t feature_maps[MAX_FEATURES];
+ HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func, void *user_data);
- lookup_map_t lookup_maps[2][MAX_LOOKUPS]; /* GSUB/GPOS */
- unsigned int lookup_count[2];
+ unsigned int current_stage[2]; /* GSUB/GPOS */
+ hb_prealloced_array_t<feature_info_t,16> feature_infos;
+ hb_prealloced_array_t<pause_info_t, 1> pauses[2]; /* GSUB/GPOS */
};
-HB_END_DECLS
-
#endif /* HB_OT_MAP_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-map.cc b/third_party/harfbuzz-ng/src/hb-ot-map.cc
index ca96ba9..a54e306 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-map.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-map.cc
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2009,2010 Red Hat, Inc.
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2009,2010 Red Hat, Inc.
+ * Copyright © 2010,2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -30,7 +30,6 @@
#include "hb-ot-shape-private.hh"
-HB_BEGIN_DECLS
void
@@ -39,76 +38,133 @@ hb_ot_map_t::add_lookups (hb_face_t *face,
unsigned int feature_index,
hb_mask_t mask)
{
- unsigned int i = MAX_LOOKUPS - lookup_count[table_index];
- lookup_map_t *lookups = lookup_maps[table_index] + lookup_count[table_index];
+ unsigned int lookup_indices[32];
+ unsigned int offset, len;
+
+ offset = 0;
+ do {
+ len = ARRAY_LENGTH (lookup_indices);
+ hb_ot_layout_feature_get_lookup_indexes (face,
+ table_tags[table_index],
+ feature_index,
+ offset, &len,
+ lookup_indices);
+
+ for (unsigned int i = 0; i < len; i++) {
+ hb_ot_map_t::lookup_map_t *lookup = lookups[table_index].push ();
+ if (unlikely (!lookup))
+ return;
+ lookup->mask = mask;
+ lookup->index = lookup_indices[i];
+ }
+
+ offset += len;
+ } while (len == ARRAY_LENGTH (lookup_indices));
+}
- unsigned int *lookup_indices = (unsigned int *) lookups;
- hb_ot_layout_feature_get_lookup_indexes (face,
- table_tags[table_index],
- feature_index,
- 0, &i,
- lookup_indices);
+void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, bool global)
+{
+ feature_info_t *info = feature_infos.push();
+ if (unlikely (!info)) return;
+ info->tag = tag;
+ info->seq = feature_infos.len;
+ info->max_value = value;
+ info->global = global;
+ info->default_value = global ? value : 0;
+ info->stage[0] = current_stage[0];
+ info->stage[1] = current_stage[1];
+}
+
+void hb_ot_map_t::apply (unsigned int table_index,
+ hb_ot_map_t::apply_lookup_func_t apply_lookup_func,
+ void *face_or_font,
+ hb_buffer_t *buffer) const
+{
+ unsigned int i = 0;
- lookup_count[table_index] += i;
+ for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; pause_index++) {
+ const pause_map_t *pause = &pauses[table_index][pause_index];
+ for (; i < pause->num_lookups; i++)
+ apply_lookup_func (face_or_font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask);
- while (i--) {
- lookups[i].mask = mask;
- lookups[i].index = lookup_indices[i];
+ pause->callback.func (this, face_or_font, buffer, pause->callback.user_data);
}
+
+ for (; i < lookups[table_index].len; i++)
+ apply_lookup_func (face_or_font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask);
}
+void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func, void *user_data)
+{
+ if (pause_func) {
+ pause_info_t *p = pauses[table_index].push ();
+ if (likely (p)) {
+ p->stage = current_stage[table_index];
+ p->callback.func = pause_func;
+ p->callback.user_data = user_data;
+ }
+ }
+
+ current_stage[table_index]++;
+}
+
void
-hb_ot_map_t::compile (hb_face_t *face,
- const hb_segment_properties_t *props)
+hb_ot_map_builder_t::compile (hb_face_t *face,
+ const hb_segment_properties_t *props,
+ hb_ot_map_t &m)
{
- global_mask = 1;
- lookup_count[0] = lookup_count[1] = 0;
+ m.global_mask = 1;
- if (!feature_count)
+ if (!feature_infos.len)
return;
/* Fetch script/language indices for GSUB/GPOS. We need these later to skip
* features not available in either table and not waste precious bits for them. */
- const hb_tag_t *script_tags;
+ hb_tag_t script_tags[3] = {HB_TAG_NONE};
hb_tag_t language_tag;
- script_tags = hb_ot_tags_from_script (props->script);
+ hb_ot_tags_from_script (props->script, &script_tags[0], &script_tags[1]);
language_tag = hb_ot_tag_from_language (props->language);
unsigned int script_index[2], language_index[2];
for (unsigned int table_index = 0; table_index < 2; table_index++) {
hb_tag_t table_tag = table_tags[table_index];
- hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index]);
+ hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &m.chosen_script[table_index]);
hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
}
/* Sort features and merge duplicates */
- qsort (feature_infos, feature_count, sizeof (feature_infos[0]), (hb_compare_func_t) feature_info_t::cmp);
- unsigned int j = 0;
- for (unsigned int i = 1; i < feature_count; i++)
- if (feature_infos[i].tag != feature_infos[j].tag)
- feature_infos[++j] = feature_infos[i];
- else {
- if (feature_infos[i].global)
- feature_infos[j] = feature_infos[i];
+ {
+ feature_infos.sort ();
+ unsigned int j = 0;
+ for (unsigned int i = 1; i < feature_infos.len; i++)
+ if (feature_infos[i].tag != feature_infos[j].tag)
+ feature_infos[++j] = feature_infos[i];
else {
- feature_infos[j].global = false;
- feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value);
+ if (feature_infos[i].global) {
+ feature_infos[j].global = true;
+ feature_infos[j].max_value = feature_infos[i].max_value;
+ feature_infos[j].default_value = feature_infos[i].default_value;
+ } else {
+ feature_infos[j].global = false;
+ feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value);
+ }
+ feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_infos[i].stage[0]);
+ feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_infos[i].stage[1]);
/* Inherit default_value from j */
}
- }
- feature_count = j + 1;
+ feature_infos.shrink (j + 1);
+ }
/* Allocate bits now */
unsigned int next_bit = 1;
- j = 0;
- for (unsigned int i = 0; i < feature_count; i++) {
+ for (unsigned int i = 0; i < feature_infos.len; i++) {
const feature_info_t *info = &feature_infos[i];
unsigned int bits_needed;
@@ -136,11 +192,15 @@ hb_ot_map_t::compile (hb_face_t *face,
continue;
- feature_map_t *map = &feature_maps[j++];
+ hb_ot_map_t::feature_map_t *map = m.features.push ();
+ if (unlikely (!map))
+ break;
map->tag = info->tag;
map->index[0] = feature_index[0];
map->index[1] = feature_index[1];
+ map->stage[0] = info->stage[0];
+ map->stage[1] = info->stage[1];
if (info->global && info->max_value == 1) {
/* Uses the global bit */
map->shift = 0;
@@ -150,13 +210,16 @@ hb_ot_map_t::compile (hb_face_t *face,
map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
next_bit += bits_needed;
if (info->global)
- global_mask |= (info->default_value << map->shift) & map->mask;
+ m.global_mask |= (info->default_value << map->shift) & map->mask;
}
map->_1_mask = (1 << map->shift) & map->mask;
}
- feature_count = j;
+ feature_infos.shrink (0); /* Done with these */
+
+ add_gsub_pause (NULL, NULL);
+ add_gpos_pause (NULL, NULL);
for (unsigned int table_index = 0; table_index < 2; table_index++) {
hb_tag_t table_tag = table_tags[table_index];
@@ -169,26 +232,43 @@ hb_ot_map_t::compile (hb_face_t *face,
script_index[table_index],
language_index[table_index],
&required_feature_index))
- add_lookups (face, table_index, required_feature_index, 1);
-
- for (unsigned i = 0; i < feature_count; i++)
- add_lookups (face, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
+ m.add_lookups (face, table_index, required_feature_index, 1);
- /* Sort lookups and merge duplicates */
- qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), (hb_compare_func_t) lookup_map_t::cmp);
- if (lookup_count[table_index])
+ unsigned int pause_index = 0;
+ unsigned int last_num_lookups = 0;
+ for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
{
- unsigned int j = 0;
- for (unsigned int i = 1; i < lookup_count[table_index]; i++)
- if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
- lookup_maps[table_index][++j] = lookup_maps[table_index][i];
- else
- lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
- j++;
- lookup_count[table_index] = j;
+ for (unsigned i = 0; i < m.features.len; i++)
+ if (m.features[i].stage[table_index] == stage)
+ m.add_lookups (face, table_index, m.features[i].index[table_index], m.features[i].mask);
+
+ /* Sort lookups and merge duplicates */
+ if (last_num_lookups < m.lookups[table_index].len)
+ {
+ m.lookups[table_index].sort (last_num_lookups, m.lookups[table_index].len);
+
+ unsigned int j = last_num_lookups;
+ for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++)
+ if (m.lookups[table_index][i].index != m.lookups[table_index][j].index)
+ m.lookups[table_index][++j] = m.lookups[table_index][i];
+ else
+ m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask;
+ m.lookups[table_index].shrink (j + 1);
+ }
+
+ last_num_lookups = m.lookups[table_index].len;
+
+ if (pause_index < pauses[table_index].len && pauses[table_index][pause_index].stage == stage) {
+ hb_ot_map_t::pause_map_t *pause_map = m.pauses[table_index].push ();
+ if (likely (pause_map)) {
+ pause_map->num_lookups = last_num_lookups;
+ pause_map->callback = pauses[table_index][pause_index].callback;
+ }
+
+ pause_index++;
+ }
}
}
}
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh b/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
new file mode 100644
index 0000000..c3ac1c2
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-maxp-table.hh
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2011 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_MAXP_TABLE_HH
+#define HB_OT_MAXP_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+
+
+/*
+ * maxp -- The Maximum Profile Table
+ */
+
+#define HB_OT_TAG_maxp HB_TAG('m','a','x','p')
+
+struct maxp
+{
+ static const hb_tag_t Tag = HB_OT_TAG_maxp;
+
+ inline unsigned int get_num_glyphs (void) const {
+ return numGlyphs;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE ();
+ return c->check_struct (this) &&
+ likely (version.major == 1 ||
+ (version.major == 0 && version.minor == 0x5000));
+ }
+
+ /* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */
+ private:
+ FixedVersion version; /* Version of the maxp table (0.5 or 1.0),
+ * 0x00005000 or 0x00010000. */
+ USHORT numGlyphs; /* The number of glyphs in the font. */
+ public:
+ DEFINE_SIZE_STATIC (6);
+};
+
+
+
+#endif /* HB_OT_MAXP_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-name-table.hh b/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
new file mode 100644
index 0000000..0e9f7a4
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-name-table.hh
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2011 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_NAME_TABLE_HH
+#define HB_OT_NAME_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+
+
+/*
+ * name -- The Naming Table
+ */
+
+#define HB_OT_TAG_name HB_TAG('n','a','m','e')
+
+
+struct NameRecord
+{
+ static int cmp (const NameRecord *a, const NameRecord *b)
+ {
+ int ret;
+ ret = b->platformID.cmp (a->platformID);
+ if (ret) return ret;
+ ret = b->encodingID.cmp (a->encodingID);
+ if (ret) return ret;
+ ret = b->languageID.cmp (a->languageID);
+ if (ret) return ret;
+ ret = b->nameID.cmp (a->nameID);
+ if (ret) return ret;
+ return 0;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+ TRACE_SANITIZE ();
+ /* We can check from base all the way up to the end of string... */
+ return c->check_struct (this) &&
+ c->check_range ((char *) base, (unsigned int) length + offset);
+ }
+
+ USHORT platformID; /* Platform ID. */
+ USHORT encodingID; /* Platform-specific encoding ID. */
+ USHORT languageID; /* Language ID. */
+ USHORT nameID; /* Name ID. */
+ USHORT length; /* String length (in bytes). */
+ USHORT offset; /* String offset from start of storage area (in bytes). */
+ public:
+ DEFINE_SIZE_STATIC (12);
+};
+
+struct name
+{
+ static const hb_tag_t Tag = HB_OT_TAG_name;
+
+ inline unsigned int get_name (unsigned int platform_id,
+ unsigned int encoding_id,
+ unsigned int language_id,
+ unsigned int name_id,
+ void *buffer,
+ unsigned int buffer_length) const
+ {
+ NameRecord key;
+ key.platformID.set (platform_id);
+ key.encodingID.set (encoding_id);
+ key.languageID.set (language_id);
+ key.nameID.set (name_id);
+ NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), (hb_compare_func_t) NameRecord::cmp);
+
+ if (!match)
+ return 0;
+
+ unsigned int length = MIN (buffer_length, (unsigned int) match->length);
+ memcpy (buffer, (char *) this + stringOffset + match->offset, length);
+ return length;
+ }
+
+ inline bool sanitize_records (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE ();
+ char *string_pool = (char *) this + stringOffset;
+ unsigned int _count = count;
+ for (unsigned int i = 0; i < _count; i++)
+ if (!nameRecord[i].sanitize (c, string_pool)) return false;
+ return true;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE ();
+ return c->check_struct (this) &&
+ likely (format == 0 || format == 1) &&
+ c->check_array (nameRecord, nameRecord[0].static_size, count) &&
+ sanitize_records (c);
+ }
+
+ /* We only implement format 0 for now. */
+ private:
+ USHORT format; /* Format selector (=0/1). */
+ USHORT count; /* Number of name records. */
+ Offset stringOffset; /* Offset to start of string storage (from start of table). */
+ NameRecord nameRecord[VAR]; /* The name records where count is the number of records. */
+ public:
+ DEFINE_SIZE_ARRAY (6, nameRecord);
+};
+
+
+
+#endif /* HB_OT_NAME_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.h b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
index 523fc84..5aa8716 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.h
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,34 +24,33 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_H
-#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_H
+#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
+#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
-#include "hb-private.h"
+#include "hb-private.hh"
-HB_BEGIN_DECLS
/* == Start of generated table == */
/*
* The following table is generated by running:
*
- * ./gen-arabic-joining-table.py < ArabicShaping.txt
+ * ./gen-arabic-table.py ArabicShaping.txt
*
- * on the ArabicShaping.txt file with the header:
+ * on files with these headers:
*
* # ArabicShaping-6.1.0.txt
- * # Date: 2010-11-09, 12:10:00 PST [KW]
+ * # Date: 2011-04-15, 23:16:00 GMT [KW]
*/
static const uint8_t joining_table[] =
{
- /* Arabic characters */
+ /* Arabic Characters */
JOINING_TYPE_U, /* 0600; ARABIC NUMBER SIGN; U; No_Joining_Group */
JOINING_TYPE_U, /* 0601; ARABIC SIGN SANAH; U; No_Joining_Group */
JOINING_TYPE_U, /* 0602; ARABIC FOOTNOTE MARKER; U; No_Joining_Group */
JOINING_TYPE_U, /* 0603; ARABIC SIGN SAFHA; U; No_Joining_Group */
- JOINING_TYPE_X, /* 0604 */
+ JOINING_TYPE_U, /* 0604; ARABIC SIGN SAMVAT; U; No_Joining_Group */
JOINING_TYPE_X, /* 0605 */
JOINING_TYPE_X, /* 0606 */
JOINING_TYPE_X, /* 0607 */
@@ -79,36 +78,36 @@ static const uint8_t joining_table[] =
JOINING_TYPE_X, /* 061D */
JOINING_TYPE_X, /* 061E */
JOINING_TYPE_X, /* 061F */
- JOINING_TYPE_D, /* 0620; YEH WITH RING; D; YEH */
+ JOINING_TYPE_D, /* 0620; DOTLESS YEH WITH SEPARATE RING BELOW; D; YEH */
JOINING_TYPE_U, /* 0621; HAMZA; U; No_Joining_Group */
- JOINING_TYPE_R, /* 0622; MADDA ON ALEF; R; ALEF */
- JOINING_TYPE_R, /* 0623; HAMZA ON ALEF; R; ALEF */
- JOINING_TYPE_R, /* 0624; HAMZA ON WAW; R; WAW */
- JOINING_TYPE_R, /* 0625; HAMZA UNDER ALEF; R; ALEF */
- JOINING_TYPE_D, /* 0626; HAMZA ON YEH; D; YEH */
+ JOINING_TYPE_R, /* 0622; ALEF WITH MADDA ABOVE; R; ALEF */
+ JOINING_TYPE_R, /* 0623; ALEF WITH HAMZA ABOVE; R; ALEF */
+ JOINING_TYPE_R, /* 0624; WAW WITH HAMZA ABOVE; R; WAW */
+ JOINING_TYPE_R, /* 0625; ALEF WITH HAMZA BELOW; R; ALEF */
+ JOINING_TYPE_D, /* 0626; DOTLESS YEH WITH HAMZA ABOVE; D; YEH */
JOINING_TYPE_R, /* 0627; ALEF; R; ALEF */
JOINING_TYPE_D, /* 0628; BEH; D; BEH */
JOINING_TYPE_R, /* 0629; TEH MARBUTA; R; TEH MARBUTA */
- JOINING_TYPE_D, /* 062A; TEH; D; BEH */
- JOINING_TYPE_D, /* 062B; THEH; D; BEH */
- JOINING_TYPE_D, /* 062C; JEEM; D; HAH */
+ JOINING_TYPE_D, /* 062A; DOTLESS BEH WITH 2 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 062B; DOTLESS BEH WITH 3 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 062C; HAH WITH DOT BELOW; D; HAH */
JOINING_TYPE_D, /* 062D; HAH; D; HAH */
- JOINING_TYPE_D, /* 062E; KHAH; D; HAH */
+ JOINING_TYPE_D, /* 062E; HAH WITH DOT ABOVE; D; HAH */
JOINING_TYPE_R, /* 062F; DAL; R; DAL */
- JOINING_TYPE_R, /* 0630; THAL; R; DAL */
+ JOINING_TYPE_R, /* 0630; DAL WITH DOT ABOVE; R; DAL */
JOINING_TYPE_R, /* 0631; REH; R; REH */
- JOINING_TYPE_R, /* 0632; ZAIN; R; REH */
+ JOINING_TYPE_R, /* 0632; REH WITH DOT ABOVE; R; REH */
JOINING_TYPE_D, /* 0633; SEEN; D; SEEN */
- JOINING_TYPE_D, /* 0634; SHEEN; D; SEEN */
+ JOINING_TYPE_D, /* 0634; SEEN WITH 3 DOTS ABOVE; D; SEEN */
JOINING_TYPE_D, /* 0635; SAD; D; SAD */
- JOINING_TYPE_D, /* 0636; DAD; D; SAD */
+ JOINING_TYPE_D, /* 0636; SAD WITH DOT ABOVE; D; SAD */
JOINING_TYPE_D, /* 0637; TAH; D; TAH */
- JOINING_TYPE_D, /* 0638; ZAH; D; TAH */
+ JOINING_TYPE_D, /* 0638; TAH WITH DOT ABOVE; D; TAH */
JOINING_TYPE_D, /* 0639; AIN; D; AIN */
- JOINING_TYPE_D, /* 063A; GHAIN; D; AIN */
+ JOINING_TYPE_D, /* 063A; AIN WITH DOT ABOVE; D; AIN */
JOINING_TYPE_D, /* 063B; KEHEH WITH 2 DOTS ABOVE; D; GAF */
JOINING_TYPE_D, /* 063C; KEHEH WITH 3 DOTS BELOW; D; GAF */
- JOINING_TYPE_D, /* 063D; FARSI YEH WITH INVERTED V; D; FARSI YEH */
+ JOINING_TYPE_D, /* 063D; FARSI YEH WITH INVERTED V ABOVE; D; FARSI YEH */
JOINING_TYPE_D, /* 063E; FARSI YEH WITH 2 DOTS ABOVE; D; FARSI YEH */
JOINING_TYPE_D, /* 063F; FARSI YEH WITH 3 DOTS ABOVE; D; FARSI YEH */
JOINING_TYPE_C, /* 0640; TATWEEL; C; No_Joining_Group */
@@ -120,7 +119,7 @@ static const uint8_t joining_table[] =
JOINING_TYPE_D, /* 0646; NOON; D; NOON */
JOINING_TYPE_D, /* 0647; HEH; D; HEH */
JOINING_TYPE_R, /* 0648; WAW; R; WAW */
- JOINING_TYPE_D, /* 0649; ALEF MAKSURA; D; YEH */
+ JOINING_TYPE_D, /* 0649; DOTLESS YEH; D; YEH */
JOINING_TYPE_D, /* 064A; YEH; D; YEH */
JOINING_TYPE_X, /* 064B */
JOINING_TYPE_X, /* 064C */
@@ -160,44 +159,44 @@ static const uint8_t joining_table[] =
JOINING_TYPE_D, /* 066E; DOTLESS BEH; D; BEH */
JOINING_TYPE_D, /* 066F; DOTLESS QAF; D; QAF */
JOINING_TYPE_X, /* 0670 */
- JOINING_TYPE_R, /* 0671; HAMZAT WASL ON ALEF; R; ALEF */
- JOINING_TYPE_R, /* 0672; WAVY HAMZA ON ALEF; R; ALEF */
- JOINING_TYPE_R, /* 0673; WAVY HAMZA UNDER ALEF; R; ALEF */
+ JOINING_TYPE_R, /* 0671; ALEF WITH WASLA ABOVE; R; ALEF */
+ JOINING_TYPE_R, /* 0672; ALEF WITH WAVY HAMZA ABOVE; R; ALEF */
+ JOINING_TYPE_R, /* 0673; ALEF WITH WAVY HAMZA BELOW; R; ALEF */
JOINING_TYPE_U, /* 0674; HIGH HAMZA; U; No_Joining_Group */
JOINING_TYPE_R, /* 0675; HIGH HAMZA ALEF; R; ALEF */
JOINING_TYPE_R, /* 0676; HIGH HAMZA WAW; R; WAW */
- JOINING_TYPE_R, /* 0677; HIGH HAMZA WAW WITH DAMMA; R; WAW */
- JOINING_TYPE_D, /* 0678; HIGH HAMZA YEH; D; YEH */
- JOINING_TYPE_D, /* 0679; TEH WITH SMALL TAH; D; BEH */
- JOINING_TYPE_D, /* 067A; TEH WITH 2 DOTS VERTICAL ABOVE; D; BEH */
- JOINING_TYPE_D, /* 067B; BEH WITH 2 DOTS VERTICAL BELOW; D; BEH */
- JOINING_TYPE_D, /* 067C; TEH WITH RING; D; BEH */
- JOINING_TYPE_D, /* 067D; TEH WITH 3 DOTS ABOVE DOWNWARD; D; BEH */
- JOINING_TYPE_D, /* 067E; TEH WITH 3 DOTS BELOW; D; BEH */
- JOINING_TYPE_D, /* 067F; TEH WITH 4 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 0680; BEH WITH 4 DOTS BELOW; D; BEH */
- JOINING_TYPE_D, /* 0681; HAMZA ON HAH; D; HAH */
- JOINING_TYPE_D, /* 0682; HAH WITH 2 DOTS VERTICAL ABOVE; D; HAH */
- JOINING_TYPE_D, /* 0683; HAH WITH MIDDLE 2 DOTS; D; HAH */
- JOINING_TYPE_D, /* 0684; HAH WITH MIDDLE 2 DOTS VERTICAL; D; HAH */
+ JOINING_TYPE_R, /* 0677; HIGH HAMZA WAW WITH DAMMA ABOVE; R; WAW */
+ JOINING_TYPE_D, /* 0678; HIGH HAMZA DOTLESS YEH; D; YEH */
+ JOINING_TYPE_D, /* 0679; DOTLESS BEH WITH TAH ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 067A; DOTLESS BEH WITH VERTICAL 2 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 067B; DOTLESS BEH WITH VERTICAL 2 DOTS BELOW; D; BEH */
+ JOINING_TYPE_D, /* 067C; DOTLESS BEH WITH ATTACHED RING BELOW AND 2 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 067D; DOTLESS BEH WITH INVERTED 3 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 067E; DOTLESS BEH WITH 3 DOTS BELOW; D; BEH */
+ JOINING_TYPE_D, /* 067F; DOTLESS BEH WITH 4 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 0680; DOTLESS BEH WITH 4 DOTS BELOW; D; BEH */
+ JOINING_TYPE_D, /* 0681; HAH WITH HAMZA ABOVE; D; HAH */
+ JOINING_TYPE_D, /* 0682; HAH WITH VERTICAL 2 DOTS ABOVE; D; HAH */
+ JOINING_TYPE_D, /* 0683; HAH WITH 2 DOTS BELOW; D; HAH */
+ JOINING_TYPE_D, /* 0684; HAH WITH VERTICAL 2 DOTS BELOW; D; HAH */
JOINING_TYPE_D, /* 0685; HAH WITH 3 DOTS ABOVE; D; HAH */
- JOINING_TYPE_D, /* 0686; HAH WITH MIDDLE 3 DOTS DOWNWARD; D; HAH */
- JOINING_TYPE_D, /* 0687; HAH WITH MIDDLE 4 DOTS; D; HAH */
- JOINING_TYPE_R, /* 0688; DAL WITH SMALL TAH; R; DAL */
- JOINING_TYPE_R, /* 0689; DAL WITH RING; R; DAL */
+ JOINING_TYPE_D, /* 0686; HAH WITH 3 DOTS BELOW; D; HAH */
+ JOINING_TYPE_D, /* 0687; HAH WITH 4 DOTS BELOW; D; HAH */
+ JOINING_TYPE_R, /* 0688; DAL WITH TAH ABOVE; R; DAL */
+ JOINING_TYPE_R, /* 0689; DAL WITH ATTACHED RING BELOW; R; DAL */
JOINING_TYPE_R, /* 068A; DAL WITH DOT BELOW; R; DAL */
- JOINING_TYPE_R, /* 068B; DAL WITH DOT BELOW AND SMALL TAH; R; DAL */
+ JOINING_TYPE_R, /* 068B; DAL WITH DOT BELOW AND TAH ABOVE; R; DAL */
JOINING_TYPE_R, /* 068C; DAL WITH 2 DOTS ABOVE; R; DAL */
JOINING_TYPE_R, /* 068D; DAL WITH 2 DOTS BELOW; R; DAL */
JOINING_TYPE_R, /* 068E; DAL WITH 3 DOTS ABOVE; R; DAL */
- JOINING_TYPE_R, /* 068F; DAL WITH 3 DOTS ABOVE DOWNWARD; R; DAL */
+ JOINING_TYPE_R, /* 068F; DAL WITH INVERTED 3 DOTS ABOVE; R; DAL */
JOINING_TYPE_R, /* 0690; DAL WITH 4 DOTS ABOVE; R; DAL */
- JOINING_TYPE_R, /* 0691; REH WITH SMALL TAH; R; REH */
- JOINING_TYPE_R, /* 0692; REH WITH SMALL V; R; REH */
- JOINING_TYPE_R, /* 0693; REH WITH RING; R; REH */
+ JOINING_TYPE_R, /* 0691; REH WITH TAH ABOVE; R; REH */
+ JOINING_TYPE_R, /* 0692; REH WITH V ABOVE; R; REH */
+ JOINING_TYPE_R, /* 0693; REH WITH ATTACHED RING BELOW; R; REH */
JOINING_TYPE_R, /* 0694; REH WITH DOT BELOW; R; REH */
- JOINING_TYPE_R, /* 0695; REH WITH SMALL V BELOW; R; REH */
- JOINING_TYPE_R, /* 0696; REH WITH DOT BELOW AND DOT ABOVE; R; REH */
+ JOINING_TYPE_R, /* 0695; REH WITH V BELOW; R; REH */
+ JOINING_TYPE_R, /* 0696; REH WITH DOT BELOW AND DOT WITHIN; R; REH */
JOINING_TYPE_R, /* 0697; REH WITH 2 DOTS ABOVE; R; REH */
JOINING_TYPE_R, /* 0698; REH WITH 3 DOTS ABOVE; R; REH */
JOINING_TYPE_R, /* 0699; REH WITH 4 DOTS ABOVE; R; REH */
@@ -209,58 +208,58 @@ static const uint8_t joining_table[] =
JOINING_TYPE_D, /* 069F; TAH WITH 3 DOTS ABOVE; D; TAH */
JOINING_TYPE_D, /* 06A0; AIN WITH 3 DOTS ABOVE; D; AIN */
JOINING_TYPE_D, /* 06A1; DOTLESS FEH; D; FEH */
- JOINING_TYPE_D, /* 06A2; FEH WITH DOT MOVED BELOW; D; FEH */
+ JOINING_TYPE_D, /* 06A2; DOTLESS FEH WITH DOT BELOW; D; FEH */
JOINING_TYPE_D, /* 06A3; FEH WITH DOT BELOW; D; FEH */
- JOINING_TYPE_D, /* 06A4; FEH WITH 3 DOTS ABOVE; D; FEH */
- JOINING_TYPE_D, /* 06A5; FEH WITH 3 DOTS BELOW; D; FEH */
- JOINING_TYPE_D, /* 06A6; FEH WITH 4 DOTS ABOVE; D; FEH */
- JOINING_TYPE_D, /* 06A7; QAF WITH DOT ABOVE; D; QAF */
- JOINING_TYPE_D, /* 06A8; QAF WITH 3 DOTS ABOVE; D; QAF */
+ JOINING_TYPE_D, /* 06A4; DOTLESS FEH WITH 3 DOTS ABOVE; D; FEH */
+ JOINING_TYPE_D, /* 06A5; DOTLESS FEH WITH 3 DOTS BELOW; D; FEH */
+ JOINING_TYPE_D, /* 06A6; DOTLESS FEH WITH 4 DOTS ABOVE; D; FEH */
+ JOINING_TYPE_D, /* 06A7; DOTLESS QAF WITH DOT ABOVE; D; QAF */
+ JOINING_TYPE_D, /* 06A8; DOTLESS QAF WITH 3 DOTS ABOVE; D; QAF */
JOINING_TYPE_D, /* 06A9; KEHEH; D; GAF */
JOINING_TYPE_D, /* 06AA; SWASH KAF; D; SWASH KAF */
- JOINING_TYPE_D, /* 06AB; KAF WITH RING; D; GAF */
+ JOINING_TYPE_D, /* 06AB; KEHEH WITH ATTACHED RING BELOW; D; GAF */
JOINING_TYPE_D, /* 06AC; KAF WITH DOT ABOVE; D; KAF */
JOINING_TYPE_D, /* 06AD; KAF WITH 3 DOTS ABOVE; D; KAF */
JOINING_TYPE_D, /* 06AE; KAF WITH 3 DOTS BELOW; D; KAF */
JOINING_TYPE_D, /* 06AF; GAF; D; GAF */
- JOINING_TYPE_D, /* 06B0; GAF WITH RING; D; GAF */
+ JOINING_TYPE_D, /* 06B0; GAF WITH ATTACHED RING BELOW; D; GAF */
JOINING_TYPE_D, /* 06B1; GAF WITH 2 DOTS ABOVE; D; GAF */
JOINING_TYPE_D, /* 06B2; GAF WITH 2 DOTS BELOW; D; GAF */
- JOINING_TYPE_D, /* 06B3; GAF WITH 2 DOTS VERTICAL BELOW; D; GAF */
+ JOINING_TYPE_D, /* 06B3; GAF WITH VERTICAL 2 DOTS BELOW; D; GAF */
JOINING_TYPE_D, /* 06B4; GAF WITH 3 DOTS ABOVE; D; GAF */
- JOINING_TYPE_D, /* 06B5; LAM WITH SMALL V; D; LAM */
+ JOINING_TYPE_D, /* 06B5; LAM WITH V ABOVE; D; LAM */
JOINING_TYPE_D, /* 06B6; LAM WITH DOT ABOVE; D; LAM */
JOINING_TYPE_D, /* 06B7; LAM WITH 3 DOTS ABOVE; D; LAM */
JOINING_TYPE_D, /* 06B8; LAM WITH 3 DOTS BELOW; D; LAM */
JOINING_TYPE_D, /* 06B9; NOON WITH DOT BELOW; D; NOON */
JOINING_TYPE_D, /* 06BA; DOTLESS NOON; D; NOON */
- JOINING_TYPE_D, /* 06BB; DOTLESS NOON WITH SMALL TAH; D; NOON */
- JOINING_TYPE_D, /* 06BC; NOON WITH RING; D; NOON */
+ JOINING_TYPE_D, /* 06BB; DOTLESS NOON WITH TAH ABOVE; D; NOON */
+ JOINING_TYPE_D, /* 06BC; NOON WITH ATTACHED RING BELOW; D; NOON */
JOINING_TYPE_D, /* 06BD; NYA; D; NYA */
JOINING_TYPE_D, /* 06BE; KNOTTED HEH; D; KNOTTED HEH */
- JOINING_TYPE_D, /* 06BF; HAH WITH MIDDLE 3 DOTS DOWNWARD AND DOT ABOVE; D; HAH */
- JOINING_TYPE_R, /* 06C0; HAMZA ON HEH; R; TEH MARBUTA */
+ JOINING_TYPE_D, /* 06BF; HAH WITH 3 DOTS BELOW AND DOT ABOVE; D; HAH */
+ JOINING_TYPE_R, /* 06C0; DOTLESS TEH MARBUTA WITH HAMZA ABOVE; R; TEH MARBUTA */
JOINING_TYPE_D, /* 06C1; HEH GOAL; D; HEH GOAL */
- JOINING_TYPE_D, /* 06C2; HAMZA ON HEH GOAL; D; HEH GOAL */
+ JOINING_TYPE_D, /* 06C2; HEH GOAL WITH HAMZA ABOVE; D; HEH GOAL */
JOINING_TYPE_R, /* 06C3; TEH MARBUTA GOAL; R; TEH MARBUTA GOAL */
- JOINING_TYPE_R, /* 06C4; WAW WITH RING; R; WAW */
+ JOINING_TYPE_R, /* 06C4; WAW WITH ATTACHED RING WITHIN; R; WAW */
JOINING_TYPE_R, /* 06C5; WAW WITH BAR; R; WAW */
- JOINING_TYPE_R, /* 06C6; WAW WITH SMALL V; R; WAW */
- JOINING_TYPE_R, /* 06C7; WAW WITH DAMMA; R; WAW */
+ JOINING_TYPE_R, /* 06C6; WAW WITH V ABOVE; R; WAW */
+ JOINING_TYPE_R, /* 06C7; WAW WITH DAMMA ABOVE; R; WAW */
JOINING_TYPE_R, /* 06C8; WAW WITH ALEF ABOVE; R; WAW */
- JOINING_TYPE_R, /* 06C9; WAW WITH INVERTED SMALL V; R; WAW */
+ JOINING_TYPE_R, /* 06C9; WAW WITH INVERTED V ABOVE; R; WAW */
JOINING_TYPE_R, /* 06CA; WAW WITH 2 DOTS ABOVE; R; WAW */
JOINING_TYPE_R, /* 06CB; WAW WITH 3 DOTS ABOVE; R; WAW */
JOINING_TYPE_D, /* 06CC; FARSI YEH; D; FARSI YEH */
JOINING_TYPE_R, /* 06CD; YEH WITH TAIL; R; YEH WITH TAIL */
- JOINING_TYPE_D, /* 06CE; FARSI YEH WITH SMALL V; D; FARSI YEH */
+ JOINING_TYPE_D, /* 06CE; FARSI YEH WITH V ABOVE; D; FARSI YEH */
JOINING_TYPE_R, /* 06CF; WAW WITH DOT ABOVE; R; WAW */
- JOINING_TYPE_D, /* 06D0; YEH WITH 2 DOTS VERTICAL BELOW; D; YEH */
- JOINING_TYPE_D, /* 06D1; YEH WITH 3 DOTS BELOW; D; YEH */
+ JOINING_TYPE_D, /* 06D0; DOTLESS YEH WITH VERTICAL 2 DOTS BELOW; D; YEH */
+ JOINING_TYPE_D, /* 06D1; DOTLESS YEH WITH 3 DOTS BELOW; D; YEH */
JOINING_TYPE_R, /* 06D2; YEH BARREE; R; YEH BARREE */
- JOINING_TYPE_R, /* 06D3; HAMZA ON YEH BARREE; R; YEH BARREE */
+ JOINING_TYPE_R, /* 06D3; YEH BARREE WITH HAMZA ABOVE; R; YEH BARREE */
JOINING_TYPE_X, /* 06D4 */
- JOINING_TYPE_R, /* 06D5; AE; R; TEH MARBUTA */
+ JOINING_TYPE_R, /* 06D5; DOTLESS TEH MARBUTA; R; TEH MARBUTA */
JOINING_TYPE_X, /* 06D6 */
JOINING_TYPE_X, /* 06D7 */
JOINING_TYPE_X, /* 06D8 */
@@ -285,8 +284,8 @@ static const uint8_t joining_table[] =
JOINING_TYPE_X, /* 06EB */
JOINING_TYPE_X, /* 06EC */
JOINING_TYPE_X, /* 06ED */
- JOINING_TYPE_R, /* 06EE; DAL WITH INVERTED V; R; DAL */
- JOINING_TYPE_R, /* 06EF; REH WITH INVERTED V; R; REH */
+ JOINING_TYPE_R, /* 06EE; DAL WITH INVERTED V ABOVE; R; DAL */
+ JOINING_TYPE_R, /* 06EF; REH WITH INVERTED V ABOVE; R; REH */
JOINING_TYPE_X, /* 06F0 */
JOINING_TYPE_X, /* 06F1 */
JOINING_TYPE_X, /* 06F2 */
@@ -298,13 +297,13 @@ static const uint8_t joining_table[] =
JOINING_TYPE_X, /* 06F8 */
JOINING_TYPE_X, /* 06F9 */
JOINING_TYPE_D, /* 06FA; SEEN WITH DOT BELOW AND 3 DOTS ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 06FB; DAD WITH DOT BELOW; D; SAD */
- JOINING_TYPE_D, /* 06FC; GHAIN WITH DOT BELOW; D; AIN */
+ JOINING_TYPE_D, /* 06FB; SAD WITH DOT BELOW AND DOT ABOVE; D; SAD */
+ JOINING_TYPE_D, /* 06FC; AIN WITH DOT BELOW AND DOT ABOVE; D; AIN */
JOINING_TYPE_X, /* 06FD */
JOINING_TYPE_X, /* 06FE */
- JOINING_TYPE_D, /* 06FF; HEH WITH INVERTED V; D; KNOTTED HEH */
+ JOINING_TYPE_D, /* 06FF; KNOTTED HEH WITH INVERTED V ABOVE; D; KNOTTED HEH */
- /* Syriac characters */
+ /* Syriac Characters */
JOINING_TYPE_X, /* 0700 */
JOINING_TYPE_X, /* 0701 */
@@ -387,55 +386,55 @@ static const uint8_t joining_table[] =
JOINING_TYPE_D, /* 074E; SOGDIAN KHAPH; D; KHAPH */
JOINING_TYPE_D, /* 074F; SOGDIAN FE; D; FE */
- /* Arabic supplement characters */
+ /* Arabic Supplement Characters */
- JOINING_TYPE_D, /* 0750; BEH WITH 3 DOTS HORIZONTALLY BELOW; D; BEH */
- JOINING_TYPE_D, /* 0751; BEH WITH DOT BELOW AND 3 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 0752; BEH WITH 3 DOTS POINTING UPWARDS BELOW; D; BEH */
- JOINING_TYPE_D, /* 0753; BEH WITH 3 DOTS POINTING UPWARDS BELOW AND 2 DOTS ABOVE; D; BEH */
- JOINING_TYPE_D, /* 0754; BEH WITH 2 DOTS BELOW AND DOT ABOVE; D; BEH */
- JOINING_TYPE_D, /* 0755; BEH WITH INVERTED SMALL V BELOW; D; BEH */
- JOINING_TYPE_D, /* 0756; BEH WITH SMALL V; D; BEH */
+ JOINING_TYPE_D, /* 0750; DOTLESS BEH WITH HORIZONTAL 3 DOTS BELOW; D; BEH */
+ JOINING_TYPE_D, /* 0751; BEH WITH 3 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 0752; DOTLESS BEH WITH INVERTED 3 DOTS BELOW; D; BEH */
+ JOINING_TYPE_D, /* 0753; DOTLESS BEH WITH INVERTED 3 DOTS BELOW AND 2 DOTS ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 0754; DOTLESS BEH WITH 2 DOTS BELOW AND DOT ABOVE; D; BEH */
+ JOINING_TYPE_D, /* 0755; DOTLESS BEH WITH INVERTED V BELOW; D; BEH */
+ JOINING_TYPE_D, /* 0756; DOTLESS BEH WITH V ABOVE; D; BEH */
JOINING_TYPE_D, /* 0757; HAH WITH 2 DOTS ABOVE; D; HAH */
- JOINING_TYPE_D, /* 0758; HAH WITH 3 DOTS POINTING UPWARDS BELOW; D; HAH */
- JOINING_TYPE_R, /* 0759; DAL WITH 2 DOTS VERTICALLY BELOW AND SMALL TAH; R; DAL */
- JOINING_TYPE_R, /* 075A; DAL WITH INVERTED SMALL V BELOW; R; DAL */
- JOINING_TYPE_R, /* 075B; REH WITH STROKE; R; REH */
+ JOINING_TYPE_D, /* 0758; HAH WITH INVERTED 3 DOTS BELOW; D; HAH */
+ JOINING_TYPE_R, /* 0759; DAL WITH VERTICAL 2 DOTS BELOW AND TAH ABOVE; R; DAL */
+ JOINING_TYPE_R, /* 075A; DAL WITH INVERTED V BELOW; R; DAL */
+ JOINING_TYPE_R, /* 075B; REH WITH BAR; R; REH */
JOINING_TYPE_D, /* 075C; SEEN WITH 4 DOTS ABOVE; D; SEEN */
JOINING_TYPE_D, /* 075D; AIN WITH 2 DOTS ABOVE; D; AIN */
- JOINING_TYPE_D, /* 075E; AIN WITH 3 DOTS POINTING DOWNWARDS ABOVE; D; AIN */
- JOINING_TYPE_D, /* 075F; AIN WITH 2 DOTS VERTICALLY ABOVE; D; AIN */
- JOINING_TYPE_D, /* 0760; FEH WITH 2 DOTS BELOW; D; FEH */
- JOINING_TYPE_D, /* 0761; FEH WITH 3 DOTS POINTING UPWARDS BELOW; D; FEH */
+ JOINING_TYPE_D, /* 075E; AIN WITH INVERTED 3 DOTS ABOVE; D; AIN */
+ JOINING_TYPE_D, /* 075F; AIN WITH VERTICAL 2 DOTS ABOVE; D; AIN */
+ JOINING_TYPE_D, /* 0760; DOTLESS FEH WITH 2 DOTS BELOW; D; FEH */
+ JOINING_TYPE_D, /* 0761; DOTLESS FEH WITH INVERTED 3 DOTS BELOW; D; FEH */
JOINING_TYPE_D, /* 0762; KEHEH WITH DOT ABOVE; D; GAF */
JOINING_TYPE_D, /* 0763; KEHEH WITH 3 DOTS ABOVE; D; GAF */
- JOINING_TYPE_D, /* 0764; KEHEH WITH 3 DOTS POINTING UPWARDS BELOW; D; GAF */
+ JOINING_TYPE_D, /* 0764; KEHEH WITH INVERTED 3 DOTS BELOW; D; GAF */
JOINING_TYPE_D, /* 0765; MEEM WITH DOT ABOVE; D; MEEM */
JOINING_TYPE_D, /* 0766; MEEM WITH DOT BELOW; D; MEEM */
JOINING_TYPE_D, /* 0767; NOON WITH 2 DOTS BELOW; D; NOON */
- JOINING_TYPE_D, /* 0768; NOON WITH SMALL TAH; D; NOON */
- JOINING_TYPE_D, /* 0769; NOON WITH SMALL V; D; NOON */
+ JOINING_TYPE_D, /* 0768; NOON WITH TAH ABOVE; D; NOON */
+ JOINING_TYPE_D, /* 0769; NOON WITH V ABOVE; D; NOON */
JOINING_TYPE_D, /* 076A; LAM WITH BAR; D; LAM */
- JOINING_TYPE_R, /* 076B; REH WITH 2 DOTS VERTICALLY ABOVE; R; REH */
+ JOINING_TYPE_R, /* 076B; REH WITH VERTICAL 2 DOTS ABOVE; R; REH */
JOINING_TYPE_R, /* 076C; REH WITH HAMZA ABOVE; R; REH */
- JOINING_TYPE_D, /* 076D; SEEN WITH 2 DOTS VERTICALLY ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 076E; HAH WITH SMALL TAH BELOW; D; HAH */
- JOINING_TYPE_D, /* 076F; HAH WITH SMALL TAH AND 2 DOTS; D; HAH */
- JOINING_TYPE_D, /* 0770; SEEN WITH SMALL TAH AND 2 DOTS; D; SEEN */
- JOINING_TYPE_R, /* 0771; REH WITH SMALL TAH AND 2 DOTS; R; REH */
- JOINING_TYPE_D, /* 0772; HAH WITH SMALL TAH ABOVE; D; HAH */
+ JOINING_TYPE_D, /* 076D; SEEN WITH VERTICAL 2 DOTS ABOVE; D; SEEN */
+ JOINING_TYPE_D, /* 076E; HAH WITH TAH BELOW; D; HAH */
+ JOINING_TYPE_D, /* 076F; HAH WITH TAH AND 2 DOTS BELOW; D; HAH */
+ JOINING_TYPE_D, /* 0770; SEEN WITH 2 DOTS AND TAH ABOVE; D; SEEN */
+ JOINING_TYPE_R, /* 0771; REH WITH 2 DOTS AND TAH ABOVE; R; REH */
+ JOINING_TYPE_D, /* 0772; HAH WITH TAH ABOVE; D; HAH */
JOINING_TYPE_R, /* 0773; ALEF WITH DIGIT TWO ABOVE; R; ALEF */
JOINING_TYPE_R, /* 0774; ALEF WITH DIGIT THREE ABOVE; R; ALEF */
JOINING_TYPE_D, /* 0775; FARSI YEH WITH DIGIT TWO ABOVE; D; FARSI YEH */
JOINING_TYPE_D, /* 0776; FARSI YEH WITH DIGIT THREE ABOVE; D; FARSI YEH */
- JOINING_TYPE_D, /* 0777; YEH WITH DIGIT FOUR BELOW; D; YEH */
+ JOINING_TYPE_D, /* 0777; DOTLESS YEH WITH DIGIT FOUR BELOW; D; YEH */
JOINING_TYPE_R, /* 0778; WAW WITH DIGIT TWO ABOVE; R; WAW */
JOINING_TYPE_R, /* 0779; WAW WITH DIGIT THREE ABOVE; R; WAW */
- JOINING_TYPE_D, /* 077A; YEH BARREE WITH DIGIT TWO ABOVE; D; BURUSHASKI YEH BARREE */
- JOINING_TYPE_D, /* 077B; YEH BARREE WITH DIGIT THREE ABOVE; D; BURUSHASKI YEH BARREE */
+ JOINING_TYPE_D, /* 077A; BURUSHASKI YEH BARREE WITH DIGIT TWO ABOVE; D; BURUSHASKI YEH BARREE */
+ JOINING_TYPE_D, /* 077B; BURUSHASKI YEH BARREE WITH DIGIT THREE ABOVE; D; BURUSHASKI YEH BARREE */
JOINING_TYPE_D, /* 077C; HAH WITH DIGIT FOUR BELOW; D; HAH */
JOINING_TYPE_D, /* 077D; SEEN WITH DIGIT FOUR ABOVE; D; SEEN */
- JOINING_TYPE_D, /* 077E; SEEN WITH INVERTED V; D; SEEN */
+ JOINING_TYPE_D, /* 077E; SEEN WITH INVERTED V ABOVE; D; SEEN */
JOINING_TYPE_D, /* 077F; KAF WITH 2 DOTS ABOVE; D; KAF */
/* N'Ko Characters */
@@ -661,14 +660,99 @@ static const uint8_t joining_table[] =
JOINING_TYPE_U, /* 0857; MANDAIC KAD; U; No_Joining_Group */
JOINING_TYPE_U, /* 0858; MANDAIC AIN; U; No_Joining_Group */
- JOINING_TYPE_X /* dummy */
+ /* Arabic Extended-A Characters */
+
+ JOINING_TYPE_X, /* 0859 */
+ JOINING_TYPE_X, /* 085A */
+ JOINING_TYPE_X, /* 085B */
+ JOINING_TYPE_X, /* 085C */
+ JOINING_TYPE_X, /* 085D */
+ JOINING_TYPE_X, /* 085E */
+ JOINING_TYPE_X, /* 085F */
+ JOINING_TYPE_X, /* 0860 */
+ JOINING_TYPE_X, /* 0861 */
+ JOINING_TYPE_X, /* 0862 */
+ JOINING_TYPE_X, /* 0863 */
+ JOINING_TYPE_X, /* 0864 */
+ JOINING_TYPE_X, /* 0865 */
+ JOINING_TYPE_X, /* 0866 */
+ JOINING_TYPE_X, /* 0867 */
+ JOINING_TYPE_X, /* 0868 */
+ JOINING_TYPE_X, /* 0869 */
+ JOINING_TYPE_X, /* 086A */
+ JOINING_TYPE_X, /* 086B */
+ JOINING_TYPE_X, /* 086C */
+ JOINING_TYPE_X, /* 086D */
+ JOINING_TYPE_X, /* 086E */
+ JOINING_TYPE_X, /* 086F */
+ JOINING_TYPE_X, /* 0870 */
+ JOINING_TYPE_X, /* 0871 */
+ JOINING_TYPE_X, /* 0872 */
+ JOINING_TYPE_X, /* 0873 */
+ JOINING_TYPE_X, /* 0874 */
+ JOINING_TYPE_X, /* 0875 */
+ JOINING_TYPE_X, /* 0876 */
+ JOINING_TYPE_X, /* 0877 */
+ JOINING_TYPE_X, /* 0878 */
+ JOINING_TYPE_X, /* 0879 */
+ JOINING_TYPE_X, /* 087A */
+ JOINING_TYPE_X, /* 087B */
+ JOINING_TYPE_X, /* 087C */
+ JOINING_TYPE_X, /* 087D */
+ JOINING_TYPE_X, /* 087E */
+ JOINING_TYPE_X, /* 087F */
+ JOINING_TYPE_X, /* 0880 */
+ JOINING_TYPE_X, /* 0881 */
+ JOINING_TYPE_X, /* 0882 */
+ JOINING_TYPE_X, /* 0883 */
+ JOINING_TYPE_X, /* 0884 */
+ JOINING_TYPE_X, /* 0885 */
+ JOINING_TYPE_X, /* 0886 */
+ JOINING_TYPE_X, /* 0887 */
+ JOINING_TYPE_X, /* 0888 */
+ JOINING_TYPE_X, /* 0889 */
+ JOINING_TYPE_X, /* 088A */
+ JOINING_TYPE_X, /* 088B */
+ JOINING_TYPE_X, /* 088C */
+ JOINING_TYPE_X, /* 088D */
+ JOINING_TYPE_X, /* 088E */
+ JOINING_TYPE_X, /* 088F */
+ JOINING_TYPE_X, /* 0890 */
+ JOINING_TYPE_X, /* 0891 */
+ JOINING_TYPE_X, /* 0892 */
+ JOINING_TYPE_X, /* 0893 */
+ JOINING_TYPE_X, /* 0894 */
+ JOINING_TYPE_X, /* 0895 */
+ JOINING_TYPE_X, /* 0896 */
+ JOINING_TYPE_X, /* 0897 */
+ JOINING_TYPE_X, /* 0898 */
+ JOINING_TYPE_X, /* 0899 */
+ JOINING_TYPE_X, /* 089A */
+ JOINING_TYPE_X, /* 089B */
+ JOINING_TYPE_X, /* 089C */
+ JOINING_TYPE_X, /* 089D */
+ JOINING_TYPE_X, /* 089E */
+ JOINING_TYPE_X, /* 089F */
+ JOINING_TYPE_D, /* 08A0; DOTLESS BEH WITH V BELOW; D; BEH */
+ JOINING_TYPE_X, /* 08A1 */
+ JOINING_TYPE_D, /* 08A2; HAH WITH DOT BELOW AND 2 DOTS ABOVE; D; HAH */
+ JOINING_TYPE_D, /* 08A3; TAH WITH 2 DOTS ABOVE; D; TAH */
+ JOINING_TYPE_D, /* 08A4; DOTLESS FEH WITH DOT BELOW AND 3 DOTS ABOVE; D; FEH */
+ JOINING_TYPE_D, /* 08A5; QAF WITH DOT BELOW; D; QAF */
+ JOINING_TYPE_D, /* 08A6; LAM WITH DOUBLE BAR; D; LAM */
+ JOINING_TYPE_D, /* 08A7; MEEM WITH 3 DOTS ABOVE; D; MEEM */
+ JOINING_TYPE_D, /* 08A8; YEH WITH HAMZA ABOVE; D; YEH */
+ JOINING_TYPE_D, /* 08A9; YEH WITH DOT ABOVE; D; YEH */
+ JOINING_TYPE_R, /* 08AA; REH WITH LOOP; R; REH */
+ JOINING_TYPE_R, /* 08AB; WAW WITH DOT WITHIN; R; WAW */
+ JOINING_TYPE_R, /* 08AC; ROHINGYA YEH; R; ROHINGYA YEH */
+
};
#define JOINING_TABLE_FIRST 0x0600
-#define JOINING_TABLE_LAST 0x0858
+#define JOINING_TABLE_LAST 0x08AC
/* == End of generated table == */
-HB_END_DECLS
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_H */
+#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
index 77a9c82..2b863ef 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2010 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -26,11 +26,10 @@
#include "hb-ot-shape-complex-private.hh"
-HB_BEGIN_DECLS
/* buffer var allocations */
-#define arabic_shaping_action() var2.u32 /* arabic shaping action */
+#define arabic_shaping_action() complex_var_temporary_u16() /* arabic shaping action */
/*
@@ -55,31 +54,31 @@ enum {
* Joining types:
*/
-#include "hb-ot-shape-complex-arabic-table.h"
+#include "hb-ot-shape-complex-arabic-table.hh"
-static unsigned int get_joining_type (hb_codepoint_t u, hb_category_t gen_cat)
+static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
{
/* TODO Macroize the magic bit operations */
- if (likely (JOINING_TABLE_FIRST <= u && u <= JOINING_TABLE_LAST)) {
+ if (likely (hb_in_range<hb_codepoint_t> (u, JOINING_TABLE_FIRST, JOINING_TABLE_LAST))) {
unsigned int j_type = joining_table[u - JOINING_TABLE_FIRST];
if (likely (j_type != JOINING_TYPE_X))
return j_type;
}
/* Mongolian joining data is not in ArabicJoining.txt yet */
- if (unlikely (0x1800 <= u && u <= 0x18AF))
+ if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1800, 0x18AF)))
{
/* All letters, SIBE SYLLABLE BOUNDARY MARKER, and NIRUGU are D */
- if (gen_cat == HB_CATEGORY_OTHER_LETTER || u == 0x1807 || u == 0x180A)
+ if (gen_cat == HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER || u == 0x1807 || u == 0x180A)
return JOINING_TYPE_D;
}
- if (unlikely ((u & ~(0x200C^0x200D)) == 0x200C)) {
+ if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x200C, 0x200D))) {
return u == 0x200C ? JOINING_TYPE_U : JOINING_TYPE_C;
}
- return ((1<<gen_cat) & ((1<<HB_CATEGORY_NON_SPACING_MARK)|(1<<HB_CATEGORY_ENCLOSING_MARK)|(1<<HB_CATEGORY_FORMAT))) ?
+ return (FLAG(gen_cat) & (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))) ?
JOINING_TYPE_T : JOINING_TYPE_U;
}
@@ -121,8 +120,7 @@ enum {
static const struct arabic_state_table_entry {
uint8_t prev_action;
uint8_t curr_action;
- uint8_t next_state;
- uint8_t padding;
+ uint16_t next_state;
} arabic_state_table[][NUM_STATE_MACHINE_COLS] =
{
/* jt_U, jt_R, jt_D, jg_ALAPH, jg_DALATH_RISH */
@@ -152,47 +150,82 @@ static const struct arabic_state_table_entry {
void
-_hb_ot_shape_complex_collect_features_arabic (hb_ot_shape_plan_t *plan, const hb_segment_properties_t *props)
+_hb_ot_shape_complex_collect_features_arabic (hb_ot_map_builder_t *map, const hb_segment_properties_t *props)
{
+ /* For Language forms (in ArabicOT speak), we do the iso/fina/medi/init together,
+ * then rlig and calt each in their own stage. This makes IranNastaliq's ALLAH
+ * ligature work correctly. It's unfortunate though...
+ *
+ * This also makes Arial Bold in Windows7 work. See:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=644184
+ *
+ * TODO: Add test cases for these two.
+ */
+
+ map->add_bool_feature (HB_TAG('c','c','m','p'));
+ map->add_bool_feature (HB_TAG('l','o','c','l'));
+
+ map->add_gsub_pause (NULL, NULL);
+
unsigned int num_features = props->script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
for (unsigned int i = 0; i < num_features; i++)
- plan->map.add_bool_feature (arabic_syriac_features[i], false);
+ map->add_bool_feature (arabic_syriac_features[i], false);
+
+ map->add_gsub_pause (NULL, NULL);
+
+ map->add_bool_feature (HB_TAG('r','l','i','g'));
+ map->add_gsub_pause (NULL, NULL);
+
+ map->add_bool_feature (HB_TAG('c','a','l','t'));
+ map->add_gsub_pause (NULL, NULL);
+
+ /* ArabicOT spec enables 'cswh' for Arabic where as for basic shaper it's disabled by default. */
+ map->add_bool_feature (HB_TAG('c','s','w','h'));
+}
+
+bool
+_hb_ot_shape_complex_prefer_decomposed_arabic (void)
+{
+ return FALSE;
}
void
-_hb_ot_shape_complex_setup_masks_arabic (hb_ot_shape_context_t *c)
+_hb_ot_shape_complex_setup_masks_arabic (hb_ot_map_t *map, hb_buffer_t *buffer)
{
- unsigned int count = c->buffer->len;
+ unsigned int count = buffer->len;
unsigned int prev = 0, state = 0;
+ HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
+
for (unsigned int i = 0; i < count; i++)
{
- unsigned int this_type = get_joining_type (c->buffer->info[i].codepoint, (hb_category_t) c->buffer->info[i].general_category());
+ unsigned int this_type = get_joining_type (buffer->info[i].codepoint, (hb_unicode_general_category_t) buffer->info[i].general_category());
if (unlikely (this_type == JOINING_TYPE_T)) {
- c->buffer->info[i].arabic_shaping_action() = NONE;
+ buffer->info[i].arabic_shaping_action() = NONE;
continue;
}
const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
if (entry->prev_action != NONE)
- c->buffer->info[prev].arabic_shaping_action() = entry->prev_action;
+ buffer->info[prev].arabic_shaping_action() = entry->prev_action;
- c->buffer->info[i].arabic_shaping_action() = entry->curr_action;
+ buffer->info[i].arabic_shaping_action() = entry->curr_action;
prev = i;
state = entry->next_state;
}
hb_mask_t mask_array[TOTAL_NUM_FEATURES + 1] = {0};
- unsigned int num_masks = c->buffer->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
+ unsigned int num_masks = buffer->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
for (unsigned int i = 0; i < num_masks; i++)
- mask_array[i] = c->plan->map.get_1_mask (arabic_syriac_features[i]);
+ mask_array[i] = map->get_1_mask (arabic_syriac_features[i]);
for (unsigned int i = 0; i < count; i++)
- c->buffer->info[i].mask |= mask_array[c->buffer->info[i].arabic_shaping_action()];
+ buffer->info[i].mask |= mask_array[buffer->info[i].arabic_shaping_action()];
+
+ HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
}
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
new file mode 100644
index 0000000..5c42355
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh
@@ -0,0 +1,304 @@
+
+#line 1 "hb-ot-shape-complex-indic-machine.rl"
+/*
+ * Copyright © 2011 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_INDIC_MACHINE_HH
+#define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
+
+#include "hb-private.hh"
+
+HB_BEGIN_DECLS
+
+
+#line 38 "hb-ot-shape-complex-indic-machine.hh.tmp"
+static const unsigned char _indic_syllable_machine_trans_keys[] = {
+ 0u, 0u, 5u, 5u, 1u, 2u, 1u, 2u, 5u, 5u, 1u, 5u, 5u, 5u, 1u, 2u,
+ 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u,
+ 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u,
+ 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u,
+ 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u, 0u, 12u,
+ 0u, 12u, 0
+};
+
+static const char _indic_syllable_machine_key_spans[] = {
+ 0, 1, 2, 2, 1, 5, 1, 2,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13
+};
+
+static const short _indic_syllable_machine_index_offsets[] = {
+ 0, 0, 2, 5, 8, 10, 16, 18,
+ 21, 35, 49, 63, 77, 91, 105, 119,
+ 133, 147, 161, 175, 189, 203, 217, 231,
+ 245, 259, 273, 287, 301, 315, 329, 343,
+ 357, 371, 385, 399, 413, 427, 441, 455,
+ 469
+};
+
+static const char _indic_syllable_machine_indicies[] = {
+ 0, 1, 2, 2, 1, 3, 3,
+ 1, 4, 1, 2, 2, 1, 1, 0,
+ 1, 5, 1, 6, 6, 1, 7, 6,
+ 8, 9, 1, 1, 1, 1, 1, 1,
+ 1, 1, 10, 1, 11, 12, 13, 14,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 15, 1, 16, 17, 18, 19, 20, 21,
+ 22, 22, 23, 24, 25, 26, 27, 1,
+ 16, 17, 18, 19, 20, 28, 22, 22,
+ 23, 24, 25, 26, 27, 1, 29, 30,
+ 31, 32, 33, 1, 34, 35, 36, 37,
+ 38, 1, 39, 1, 29, 30, 31, 32,
+ 1, 1, 34, 35, 36, 37, 38, 1,
+ 39, 1, 29, 30, 31, 32, 1, 1,
+ 1, 1, 36, 37, 38, 1, 39, 1,
+ 29, 30, 31, 32, 40, 2, 1, 1,
+ 36, 37, 38, 1, 39, 1, 29, 30,
+ 31, 32, 1, 2, 1, 1, 36, 37,
+ 38, 1, 39, 1, 29, 30, 31, 32,
+ 1, 1, 1, 1, 1, 1, 38, 1,
+ 39, 1, 29, 30, 31, 32, 1, 1,
+ 1, 1, 1, 1, 41, 1, 39, 1,
+ 29, 30, 31, 32, 1, 1, 1, 1,
+ 1, 1, 1, 1, 39, 1, 42, 43,
+ 44, 45, 46, 4, 47, 47, 48, 49,
+ 50, 1, 51, 1, 42, 43, 44, 45,
+ 1, 4, 47, 47, 48, 49, 50, 1,
+ 51, 1, 42, 43, 44, 45, 1, 1,
+ 1, 1, 48, 49, 50, 1, 51, 1,
+ 42, 43, 44, 45, 52, 3, 1, 1,
+ 48, 49, 50, 1, 51, 1, 42, 43,
+ 44, 45, 1, 3, 1, 1, 48, 49,
+ 50, 1, 51, 1, 42, 43, 44, 45,
+ 1, 1, 1, 1, 1, 1, 50, 1,
+ 51, 1, 42, 43, 44, 45, 1, 1,
+ 1, 1, 1, 1, 53, 1, 51, 1,
+ 42, 43, 44, 45, 1, 1, 1, 1,
+ 1, 1, 1, 1, 51, 1, 16, 17,
+ 18, 19, 1, 21, 22, 22, 23, 24,
+ 25, 26, 27, 1, 16, 6, 6, 19,
+ 1, 1, 54, 54, 1, 24, 25, 1,
+ 27, 1, 16, 6, 6, 19, 1, 1,
+ 1, 1, 1, 24, 25, 1, 27, 1,
+ 16, 17, 18, 19, 1, 1, 1, 1,
+ 1, 1, 25, 1, 27, 1, 16, 17,
+ 18, 19, 1, 1, 1, 1, 1, 1,
+ 55, 1, 27, 1, 16, 17, 18, 19,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 27, 1, 16, 17, 18, 19, 56, 57,
+ 1, 1, 23, 24, 25, 1, 27, 1,
+ 16, 17, 18, 19, 1, 57, 1, 1,
+ 23, 24, 25, 1, 27, 1, 16, 17,
+ 18, 19, 1, 1, 1, 1, 23, 24,
+ 25, 1, 27, 1, 16, 17, 18, 19,
+ 1, 58, 1, 1, 23, 24, 25, 1,
+ 27, 1, 16, 17, 18, 19, 1, 1,
+ 59, 59, 1, 24, 25, 1, 27, 1,
+ 16, 17, 18, 19, 1, 1, 1, 1,
+ 1, 24, 25, 1, 27, 1, 16, 6,
+ 6, 9, 1, 1, 54, 54, 1, 24,
+ 25, 1, 10, 1, 0
+};
+
+static const char _indic_syllable_machine_trans_targs[] = {
+ 2, 0, 14, 22, 3, 7, 10, 9,
+ 11, 12, 20, 9, 10, 11, 12, 20,
+ 9, 10, 11, 12, 28, 29, 6, 34,
+ 31, 32, 37, 20, 40, 9, 10, 11,
+ 12, 13, 1, 5, 15, 17, 18, 20,
+ 16, 19, 9, 10, 11, 12, 21, 4,
+ 23, 25, 26, 20, 24, 27, 30, 33,
+ 35, 36, 38, 39
+};
+
+static const char _indic_syllable_machine_trans_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 3, 3, 3,
+ 3, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 4, 4, 4, 4, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+static const char _indic_syllable_machine_eof_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 2, 3, 3, 3, 3,
+ 3, 3, 3, 3, 4, 4, 4, 4,
+ 4, 4, 4, 4, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2
+};
+
+static const int indic_syllable_machine_start = 8;
+static const int indic_syllable_machine_first_final = 8;
+static const int indic_syllable_machine_error = 0;
+
+static const int indic_syllable_machine_en_main = 8;
+
+
+#line 38 "hb-ot-shape-complex-indic-machine.rl"
+
+
+
+#line 83 "hb-ot-shape-complex-indic-machine.rl"
+
+
+
+static void
+set_cluster (hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ unsigned int cluster = buffer->info[start].cluster;
+
+ for (unsigned int i = start + 1; i < end; i++)
+ cluster = MIN (cluster, buffer->info[i].cluster);
+ for (unsigned int i = start; i < end; i++)
+ buffer->info[i].cluster = cluster;
+}
+
+static void
+find_syllables (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array)
+{
+ unsigned int p, pe, eof;
+ int cs;
+
+#line 194 "hb-ot-shape-complex-indic-machine.hh.tmp"
+ {
+ cs = indic_syllable_machine_start;
+ }
+
+#line 106 "hb-ot-shape-complex-indic-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int last = 0;
+
+#line 207 "hb-ot-shape-complex-indic-machine.hh.tmp"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _keys = _indic_syllable_machine_trans_keys + (cs<<1);
+ _inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
+
+ _slen = _indic_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( buffer->info[p].indic_category()) &&
+ ( buffer->info[p].indic_category()) <= _keys[1] ?
+ ( buffer->info[p].indic_category()) - _keys[0] : _slen ];
+
+ cs = _indic_syllable_machine_trans_targs[_trans];
+
+ if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _indic_syllable_machine_trans_actions[_trans] ) {
+ case 2:
+#line 62 "hb-ot-shape-complex-indic-machine.rl"
+ { found_consonant_syllable (map, buffer, mask_array, last, p); }
+#line 67 "hb-ot-shape-complex-indic-machine.rl"
+ { set_cluster (buffer, p, last); last = p; }
+ break;
+ case 3:
+#line 63 "hb-ot-shape-complex-indic-machine.rl"
+ { found_vowel_syllable (map, buffer, mask_array, last, p); }
+#line 67 "hb-ot-shape-complex-indic-machine.rl"
+ { set_cluster (buffer, p, last); last = p; }
+ break;
+ case 4:
+#line 64 "hb-ot-shape-complex-indic-machine.rl"
+ { found_standalone_cluster (map, buffer, mask_array, last, p); }
+#line 67 "hb-ot-shape-complex-indic-machine.rl"
+ { set_cluster (buffer, p, last); last = p; }
+ break;
+ case 1:
+#line 65 "hb-ot-shape-complex-indic-machine.rl"
+ { found_non_indic (map, buffer, mask_array, last, p); }
+#line 67 "hb-ot-shape-complex-indic-machine.rl"
+ { set_cluster (buffer, p, last); last = p; }
+ break;
+#line 256 "hb-ot-shape-complex-indic-machine.hh.tmp"
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ switch ( _indic_syllable_machine_eof_actions[cs] ) {
+ case 2:
+#line 62 "hb-ot-shape-complex-indic-machine.rl"
+ { found_consonant_syllable (map, buffer, mask_array, last, p); }
+#line 67 "hb-ot-shape-complex-indic-machine.rl"
+ { set_cluster (buffer, p, last); last = p; }
+ break;
+ case 3:
+#line 63 "hb-ot-shape-complex-indic-machine.rl"
+ { found_vowel_syllable (map, buffer, mask_array, last, p); }
+#line 67 "hb-ot-shape-complex-indic-machine.rl"
+ { set_cluster (buffer, p, last); last = p; }
+ break;
+ case 4:
+#line 64 "hb-ot-shape-complex-indic-machine.rl"
+ { found_standalone_cluster (map, buffer, mask_array, last, p); }
+#line 67 "hb-ot-shape-complex-indic-machine.rl"
+ { set_cluster (buffer, p, last); last = p; }
+ break;
+ case 1:
+#line 65 "hb-ot-shape-complex-indic-machine.rl"
+ { found_non_indic (map, buffer, mask_array, last, p); }
+#line 67 "hb-ot-shape-complex-indic-machine.rl"
+ { set_cluster (buffer, p, last); last = p; }
+ break;
+#line 292 "hb-ot-shape-complex-indic-machine.hh.tmp"
+ }
+ }
+
+ _out: {}
+ }
+
+#line 114 "hb-ot-shape-complex-indic-machine.rl"
+
+}
+
+HB_END_DECLS
+
+#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.rl b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.rl
new file mode 100644
index 0000000..53dc20d
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.rl
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2011 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_INDIC_MACHINE_HH
+#define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
+
+#include "hb-private.hh"
+
+HB_BEGIN_DECLS
+
+%%{
+ machine indic_syllable_machine;
+ alphtype unsigned char;
+ write data;
+}%%
+
+%%{
+
+# Same order as enum indic_category_t. Not sure how to avoid duplication.
+X = 0;
+C = 1;
+Ra = 2;
+V = 3;
+N = 4;
+H = 5;
+ZWNJ = 6;
+ZWJ = 7;
+M = 8;
+SM = 9;
+VD = 10;
+A = 11;
+NBSP = 12;
+
+c = C | Ra;
+z = ZWJ|ZWNJ;
+matra_group = M N? H?;
+syllable_tail = SM? (VD VD?)?;
+
+action found_consonant_syllable { found_consonant_syllable (map, buffer, mask_array, last, p); }
+action found_vowel_syllable { found_vowel_syllable (map, buffer, mask_array, last, p); }
+action found_standalone_cluster { found_standalone_cluster (map, buffer, mask_array, last, p); }
+action found_non_indic { found_non_indic (map, buffer, mask_array, last, p); }
+
+action next_syllable { set_cluster (buffer, p, last); last = p; }
+
+consonant_syllable = (c.N? (z.H|H.z?))* c.N? A? (H.z? | matra_group*)? syllable_tail %(found_consonant_syllable);
+vowel_syllable = (Ra H)? V N? (z.H.c | ZWJ.c)? matra_group* syllable_tail %(found_vowel_syllable);
+standalone_cluster = (Ra H)? NBSP N? (z? H c)? matra_group* syllable_tail %(found_standalone_cluster);
+non_indic = X %(found_non_indic);
+
+syllable =
+ consonant_syllable
+ | vowel_syllable
+ | standalone_cluster
+ | non_indic
+ ;
+
+main := (syllable %(next_syllable))**;
+
+}%%
+
+
+static void
+set_cluster (hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ unsigned int cluster = buffer->info[start].cluster;
+
+ for (unsigned int i = start + 1; i < end; i++)
+ cluster = MIN (cluster, buffer->info[i].cluster);
+ for (unsigned int i = start; i < end; i++)
+ buffer->info[i].cluster = cluster;
+}
+
+static void
+find_syllables (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array)
+{
+ unsigned int p, pe, eof;
+ int cs;
+ %%{
+ write init;
+ getkey buffer->info[p].indic_category();
+ }%%
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int last = 0;
+ %%{
+ write exec;
+ }%%
+}
+
+HB_END_DECLS
+
+#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh
new file mode 100644
index 0000000..5077e8a
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.hh
@@ -0,0 +1,830 @@
+/*
+ * Copyright © 2011 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_INDIC_TABLE_HH
+#define HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH
+
+#include "hb-private.hh"
+
+
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt
+ *
+ * on files with these headers:
+ *
+ * # IndicSyllabicCategory-6.0.0.txt
+ * # Date: 2010-05-25, 11:45:00 PDT [KW]
+ * # IndicMatraCategory-6.0.0.txt
+ * # Date: 2010-07-14, 15:03:00 PDT [KW]
+ * # Blocks-6.0.0.txt
+ * # Date: 2010-06-04, 11:12:00 PDT [KW]
+ */
+
+
+#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 9 chars; Avagraha */
+#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 31 chars; Bindu */
+#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 116 chars; Consonant */
+#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 2 chars; Consonant_Dead */
+#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 16 chars; Consonant_Final */
+#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 1 chars; Consonant_Head_Letter */
+#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 12 chars; Consonant_Medial */
+#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 4 chars; Consonant_Placeholder */
+#define ISC_CR INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA /* 5 chars; Consonant_Repha */
+#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 9 chars; Consonant_Subjoined */
+#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
+#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 11 chars; Nukta */
+#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
+#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 1 chars; Register_Shifter */
+#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 3 chars; Tone_Letter */
+#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 16 chars; Tone_Mark */
+#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 29 chars; Virama */
+#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 19 chars; Visarga */
+#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 5 chars; Vowel */
+#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 161 chars; Vowel_Dependent */
+#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 53 chars; Vowel_Independent */
+
+#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 60 chars; Bottom */
+#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */
+#define IMC_I INDIC_MATRA_CATEGORY_INVISIBLE /* 4 chars; Invisible */
+#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 25 chars; Left */
+#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 8 chars; Left_And_Right */
+#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
+#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 2 chars; Overstruck */
+#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 70 chars; Right */
+#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 74 chars; Top */
+#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 5 chars; Top_And_Bottom */
+#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
+#define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 4 chars; Top_And_Left */
+#define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 2 chars; Top_And_Left_And_Right */
+#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 7 chars; Top_And_Right */
+#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 5 chars; Visual_Order_Left */
+
+#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
+
+
+static const INDIC_TABLE_ELEMENT_TYPE indic_table[4080] = {
+
+
+#define indic_offset_0x0900 0
+
+
+ /* Devanagari (0900..097F) */
+
+ /* 0900 */ _(Bi,x), _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 0918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0920 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0928 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,x), _(A,x), _(M,R), _(M,L),
+ /* 0940 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T),
+ /* 0948 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(M,L), _(M,R),
+ /* 0950 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(M,B),
+ /* 0958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0968 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0970 */ _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0978 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+
+ /* Bengali (0980..09FF) */
+
+ /* 0980 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
+ /* 0990 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 0998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 09A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 09A8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 09B0 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
+ /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L),
+ /* 09C0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
+ /* 09C8 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,B), _(CD,x), _(x,x),
+ /* 09D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
+ /* 09D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
+ /* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 09E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Gurmukhi (0A00..0A7F) */
+
+ /* 0A00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0A08 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
+ /* 0A10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 0A18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0A28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0A30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x),
+ /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(x,x), _(M,R), _(M,L),
+ /* 0A40 */ _(M,R), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T),
+ /* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x),
+ /* 0A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x),
+ /* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0A68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0A70 */ _(Bi,x), _(x,x), _(CP,x), _(CP,x), _(x,x), _(CM,x), _(x,x), _(x,x),
+ /* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Gujarati (0A80..0AFF) */
+
+ /* 0A80 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x),
+ /* 0A90 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 0A98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0AA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0AA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0AB0 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
+ /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,L),
+ /* 0AC0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(x,x), _(M,T),
+ /* 0AC8 */ _(M,T), _(M,TR), _(x,x), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x),
+ /* 0AD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0AD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0AE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0AF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Oriya (0B00..0B7F) */
+
+ /* 0B00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
+ /* 0B10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 0B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0B28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0B30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
+ /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T),
+ /* 0B40 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
+ /* 0B48 */ _(M,TL), _(x,x), _(x,x), _(M,LR),_(M,TLR), _(V,B), _(x,x), _(x,x),
+ /* 0B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,TR),
+ /* 0B58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
+ /* 0B60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0B68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0B70 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Tamil (0B80..0BFF) */
+
+ /* 0B80 */ _(x,x), _(x,x), _(Bi,x), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0B88 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(VI,x),
+ /* 0B90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(x,x), _(x,x),
+ /* 0B98 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x), _(C,x),
+ /* 0BA0 */ _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
+ /* 0BA8 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
+ /* 0BB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0BB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R),
+ /* 0BC0 */ _(M,T), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L),
+ /* 0BC8 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(x,x), _(x,x),
+ /* 0BD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
+ /* 0BD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0BE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0BE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0BF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Telugu (0C00..0C7F) */
+
+ /* 0C00 */ _(x,x), _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
+ /* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0C28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
+ /* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(A,x), _(M,T), _(M,T),
+ /* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T),
+ /* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x),
+ /* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x),
+ /* 0C58 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0C68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0C78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Kannada (0C80..0CFF) */
+
+ /* 0C80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
+ /* 0C90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 0C98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0CA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0CA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0CB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
+ /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,x), _(A,x), _(M,R), _(M,T),
+ /* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR),
+ /* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x),
+ /* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x),
+ /* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(x,x),
+ /* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0CE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0CF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Malayalam (0D00..0D7F) */
+
+ /* 0D00 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
+ /* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0D20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0D28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0D30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0D38 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(A,x), _(M,R), _(M,R),
+ /* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L),
+ /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(CR,x), _(x,x),
+ /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
+ /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0D68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0D78 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x),
+
+ /* Sinhala (0D80..0DFF) */
+
+ /* 0D80 */ _(x,x), _(x,x), _(Bi,x), _(Vs,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x),
+ /* 0D98 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0DA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0DA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0DB0 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0DB8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(x,x),
+ /* 0DC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
+ /* 0DC8 */ _(x,x), _(x,x), _(V,T), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
+ /* 0DD0 */ _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), _(x,x), _(M,B), _(x,x),
+ /* 0DD8 */ _(M,R), _(M,L), _(M,TL), _(M,L), _(M,LR), _(M,LR), _(M,LR), _(M,R),
+ /* 0DE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0DE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0DF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Thai (0E00..0E7F) */
+
+ /* 0E00 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0E08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0E10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0E18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0E20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0E28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
+ /* 0E30 */ _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T), _(M,T),
+ /* 0E38 */ _(M,B), _(M,B), _(V,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0E40 */_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL), _(M,R), _(x,x), _(M,T),
+ /* 0E48 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(Bi,x), _(V,T), _(x,x),
+ /* 0E50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0E58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0E60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0E68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0E70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0E78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Lao (0E80..0EFF) */
+
+ /* 0E80 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(C,x),
+ /* 0E88 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(C,x), _(x,x), _(x,x),
+ /* 0E90 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0E98 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0EA0 */ _(x,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x),
+ /* 0EA8 */ _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x),
+ /* 0EB0 */ _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T), _(M,T),
+ /* 0EB8 */ _(M,B), _(M,B), _(x,x), _(M,T), _(CM,x), _(CM,x), _(x,x), _(x,x),
+ /* 0EC0 */_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL),_(M,VOL), _(x,x), _(x,x), _(x,x),
+ /* 0EC8 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(Bi,x), _(x,x), _(x,x),
+ /* 0ED0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0ED8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(x,x),
+ /* 0EE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0EE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0EF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0EF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Tibetan (0F00..0FFF) */
+
+ /* 0F00 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0F08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0F10 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0F18 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0F20 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0F28 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0F30 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0F38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0F40 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0F48 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0F50 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0F58 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0F60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 0F68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
+ /* 0F70 */ _(x,x), _(M,B), _(M,T), _(M,TB), _(M,B), _(M,B), _(M,TB), _(M,TB),
+ /* 0F78 */ _(M,TB), _(M,TB), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,x), _(Vs,x),
+ /* 0F80 */ _(M,T), _(M,TB), _(Bi,x), _(Bi,x), _(V,B), _(A,x), _(x,x), _(x,x),
+ /* 0F88 */_(CHL,x),_(CHL,x),_(CHL,x),_(CHL,x),_(CHL,x), _(CS,x), _(CS,x), _(CS,x),
+ /* 0F90 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
+ /* 0F98 */ _(x,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
+ /* 0FA0 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
+ /* 0FA8 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
+ /* 0FB0 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x),
+ /* 0FB8 */ _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(CS,x), _(x,x), _(x,x), _(x,x),
+ /* 0FC0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0FC8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0FD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0FD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0FE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0FE8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0FF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 0FF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Myanmar (1000..109F) */
+
+ /* 1000 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1008 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1010 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1020 */ _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 1028 */ _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), _(M,T), _(M,T), _(M,B),
+ /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,x), _(TM,x),
+ /* 1038 */ _(Vs,x), _(V,I), _(V,T), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(C,x),
+ /* 1040 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1048 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R),
+ /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,x), _(CM,x),
+ /* 1060 */ _(CM,x), _(C,x), _(M,R), _(TM,x), _(TM,x), _(C,x), _(C,x), _(M,R),
+ /* 1068 */ _(M,R), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(C,x),
+ /* 1070 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(C,x), _(C,x), _(C,x),
+ /* 1078 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1080 */ _(C,x), _(C,x), _(CM,x), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,x),
+ /* 1088 */ _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(TM,x), _(C,x), _(TM,x),
+ /* 1090 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1098 */ _(x,x), _(x,x), _(TM,x), _(TM,x), _(M,R), _(M,T), _(x,x), _(x,x),
+
+#define indic_offset_0x1700 1952
+
+
+ /* Tagalog (1700..171F) */
+
+ /* 1700 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1708 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x),
+ /* 1710 */ _(C,x), _(C,x), _(M,T), _(M,B), _(V,B), _(x,x), _(x,x), _(x,x),
+ /* 1718 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Hanunoo (1720..173F) */
+
+ /* 1720 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1728 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1730 */ _(C,x), _(C,x), _(M,T), _(M,B), _(V,B), _(x,x), _(x,x), _(x,x),
+ /* 1738 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Buhid (1740..175F) */
+
+ /* 1740 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1748 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1750 */ _(C,x), _(C,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1758 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Tagbanwa (1760..177F) */
+
+ /* 1760 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1768 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x),
+ /* 1770 */ _(C,x), _(x,x), _(M,T), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1778 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Khmer (1780..17FF) */
+
+ /* 1780 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1788 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1790 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1798 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 17A0 */ _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(M,R), _(M,T),
+ /* 17B8 */ _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,TL),_(M,TLR),
+ /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,x), _(Vs,x),
+ /* 17C8 */ _(M,R), _(RS,x), _(RS,x), _(x,x), _(CR,x), _(x,x), _(x,x), _(x,x),
+ /* 17D0 */ _(x,x), _(V,T), _(V,I), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(x,x), _(x,x), _(x,x),
+ /* 17E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 17E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 17F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 17F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0x1900 2208
+
+
+ /* Limbu (1900..194F) */
+
+ /* 1900 */ _(CP,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1908 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
+ /* 1920 */ _(M,T), _(M,T), _(M,B), _(M,R), _(M,R), _(M,TR), _(M,TR), _(M,T),
+ /* 1928 */ _(M,T), _(CS,x), _(CS,x), _(CS,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1930 */ _(CF,x), _(CF,x), _(Bi,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
+ /* 1938 */ _(CF,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1940 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1948 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Tai Le (1950..197F) */
+
+ /* 1950 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1960 */ _(C,x), _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x),
+ /* 1968 */ _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(x,x), _(x,x),
+ /* 1970 */ _(TL,x), _(TL,x), _(TL,x), _(TL,x), _(TL,x), _(x,x), _(x,x), _(x,x),
+ /* 1978 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* New Tai Lue (1980..19DF) */
+
+ /* 1980 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1988 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 19A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 19A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 19B0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,L), _(M,L), _(M,L),
+ /* 19B8 */ _(M,R), _(M,R), _(M,L), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R),
+ /* 19C0 */ _(M,R), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
+ /* 19C8 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 19D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 19D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* FILLER (19E0..19FF) */
+
+ /* 19E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 19E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 19F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 19F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Buginese (1A00..1A1F) */
+
+ /* 1A00 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1A08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1A10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T),
+ /* 1A18 */ _(M,B), _(M,L), _(M,R), _(M,L), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Tai Tham (1A20..1AAF) */
+
+ /* 1A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1A38 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1A40 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1A48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 1A50 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(CM,x), _(CM,x), _(CF,x),
+ /* 1A58 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x),
+ /* 1A60 */ _(V,I), _(M,R), _(M,T), _(M,R), _(M,R), _(M,T), _(M,T), _(M,T),
+ /* 1A68 */ _(M,T), _(M,B), _(M,B), _(M,T), _(M,B), _(M,R), _(M,L), _(M,L),
+ /* 1A70 */ _(M,L), _(M,L), _(M,L), _(M,T), _(M,T), _(TM,x), _(TM,x), _(TM,x),
+ /* 1A78 */ _(TM,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1A80 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1A88 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1A90 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1A98 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1AA0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1AA8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0x1b00 2640
+
+
+ /* Balinese (1B00..1B7F) */
+
+ /* 1B00 */ _(Bi,x), _(Bi,x), _(Bi,x), _(CR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 1B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 1B10 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1B28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1B30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,T), _(M,T),
+ /* 1B38 */ _(M,B), _(M,B), _(M,B), _(M,BR), _(M,TB),_(M,TBR), _(M,L), _(M,L),
+ /* 1B40 */ _(M,LR), _(M,LR), _(M,T), _(M,TR), _(V,R), _(C,x), _(C,x), _(C,x),
+ /* 1B48 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1B58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1B60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1B68 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1B70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Sundanese (1B80..1BBF) */
+
+ /* 1B80 */ _(Bi,x), _(CR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 1B88 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1B90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1B98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1BA0 */ _(C,x), _(CS,x), _(CS,x), _(CS,x), _(M,T), _(M,B), _(M,L), _(M,R),
+ /* 1BA8 */ _(M,T), _(M,T), _(V,R), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
+ /* 1BB0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1BB8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Batak (1BC0..1BFF) */
+
+ /* 1BC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1BC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1BD0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1BD8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1BE0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(N,x), _(M,x),
+ /* 1BE8 */ _(M,x), _(M,x), _(M,x), _(M,x), _(M,x), _(M,x), _(M,x), _(M,x),
+ /* 1BF0 */ _(CF,x), _(CF,x), _(V,R), _(V,R), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Lepcha (1C00..1C4F) */
+
+ /* 1C00 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1C08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1C10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 1C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CS,x), _(CS,x), _(M,R), _(M,L),
+ /* 1C28 */ _(M,L), _(M,TL), _(M,R), _(M,R), _(M,B), _(CF,x), _(CF,x), _(CF,x),
+ /* 1C30 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(Bi,x), _(Bi,x), _(x,x), _(N,x),
+ /* 1C38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1C40 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 1C48 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(C,x),
+
+#define indic_offset_0xa800 2976
+
+
+ /* Syloti Nagri (A800..A82F) */
+
+ /* A800 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(V,T), _(C,x),
+ /* A808 */ _(C,x), _(C,x), _(C,x), _(Bi,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A810 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A818 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A820 */ _(C,x), _(C,x), _(C,x), _(M,R), _(M,R), _(M,B), _(M,T), _(M,R),
+ /* A828 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* FILLER (A830..A83F) */
+
+ /* A830 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A838 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Phags-pa (A840..A87F) */
+
+ /* A840 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A848 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A850 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A858 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Vo,x), _(Vo,x),
+ /* A860 */ _(Vo,x), _(Vo,x), _(C,x), _(C,x), _(C,x), _(C,x), _(Vo,x), _(CS,x),
+ /* A868 */ _(CS,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A870 */ _(C,x), _(CS,x), _(C,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A878 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Saurashtra (A880..A8DF) */
+
+ /* A880 */ _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* A888 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* A890 */ _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A898 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A8A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A8A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A8B0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(CF,x), _(M,R), _(M,R), _(M,R),
+ /* A8B8 */ _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R), _(M,R),
+ /* A8C0 */ _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x), _(x,x),
+ /* A8C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A8D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A8D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* FILLER (A8E0..A8FF) */
+
+ /* A8E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A8E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A8F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Kayah Li (A900..A92F) */
+
+ /* A900 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A908 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A910 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A920 */ _(C,x), _(C,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x), _(Vo,x),
+ /* A928 */ _(Vo,x), _(Vo,x), _(Vo,x), _(TM,x), _(TM,x), _(TM,x), _(x,x), _(x,x),
+
+ /* Rejang (A930..A95F) */
+
+ /* A930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A938 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A940 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,B),
+ /* A948 */ _(M,B), _(M,B), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B), _(CF,x),
+ /* A950 */ _(CF,x), _(CF,x), _(CF,x), _(V,R), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A958 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* FILLER (A960..A97F) */
+
+ /* A960 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A968 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A970 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A978 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Javanese (A980..A9DF) */
+
+ /* A980 */ _(Bi,x), _(Bi,x), _(CR,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* A988 */ _(VI,x), _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(C,x),
+ /* A990 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A9A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A9A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* A9B0 */ _(C,x), _(C,x), _(C,x), _(N,x), _(M,R), _(M,R), _(M,T), _(M,T),
+ /* A9B8 */ _(M,B), _(M,B), _(M,L), _(M,L), _(M,T), _(CS,x), _(CM,x), _(CM,x),
+ /* A9C0 */ _(V,BR), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A9C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A9D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A9D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* FILLER (A9E0..A9FF) */
+
+ /* A9E0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A9E8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A9F0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* A9F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Cham (AA00..AA5F) */
+
+ /* AA00 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x),
+ /* AA08 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AA10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AA18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AA20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AA28 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,T), _(M,L),
+ /* AA30 */ _(M,L), _(M,T), _(M,B), _(CM,x), _(CM,x), _(CM,x), _(CM,x), _(x,x),
+ /* AA38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* AA40 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
+ /* AA48 */ _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(x,x), _(x,x),
+ /* AA50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* AA58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Myanmar Extended-A (AA60..AA7F) */
+
+ /* AA60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AA68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Tai Viet (AA80..AADF) */
+
+ /* AA80 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AA88 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AA90 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AA98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AAA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AAA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* AAB0 */ _(M,T), _(M,R), _(M,T), _(M,T), _(M,B),_(M,VOL),_(M,VOL), _(M,T),
+ /* AAB8 */ _(M,T),_(M,VOL), _(M,R),_(M,VOL),_(M,VOL), _(M,R), _(M,T), _(TM,x),
+ /* AAC0 */ _(TL,x), _(TM,x), _(TL,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* AAC8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* AAD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* AAD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0xabc0 3712
+
+
+ /* Meetei Mayek (ABC0..ABFF) */
+
+ /* ABC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* ABC8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* ABD0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* ABD8 */ _(C,x), _(C,x), _(C,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x), _(CF,x),
+ /* ABE0 */ _(CF,x), _(CF,x), _(CF,x), _(M,R), _(M,R), _(M,T), _(M,R), _(M,R),
+ /* ABE8 */ _(M,B), _(M,R), _(M,R), _(x,x), _(TM,x), _(V,B), _(x,x), _(x,x),
+ /* ABF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* ABF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0x10a00 3776
+
+
+ /* Kharoshthi (10A00..10A5F) */
+
+ /* 10A00 */ _(C,x), _(M,O), _(M,B), _(M,B), _(x,x), _(M,T), _(M,O), _(x,x),
+ /* 10A08 */ _(x,x), _(x,x), _(x,x), _(x,x), _(M,B), _(x,x), _(Bi,x), _(Vs,x),
+ /* 10A10 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
+ /* 10A18 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 10A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 10A28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 10A30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 10A38 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(V,I),
+ /* 10A40 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 10A48 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 10A50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 10A58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_0x11000 3872
+
+
+ /* Brahmi (11000..1107F) */
+
+ /* 11000 */ _(Bi,x), _(Bi,x), _(Vs,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11008 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11010 */ _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11020 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11028 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11030 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11038 */ _(M,T), _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,B),
+ /* 11040 */ _(M,B), _(M,B), _(M,T), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x),
+ /* 11048 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11050 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11058 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11060 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11068 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 11078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+ /* Kaithi (11080..110CF) */
+
+ /* 11080 */ _(Bi,x), _(Bi,x), _(Vs,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
+ /* 11088 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
+ /* 11090 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 11098 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 110A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 110A8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
+ /* 110B0 */ _(M,R), _(M,L), _(M,R), _(M,B), _(M,B), _(M,T), _(M,T), _(M,R),
+ /* 110B8 */ _(M,R), _(V,B), _(N,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 110C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+ /* 110C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
+
+#define indic_offset_total 4080
+
+};
+
+static INDIC_TABLE_ELEMENT_TYPE
+get_indic_categories (hb_codepoint_t u)
+{
+ if (0x0900 <= u && u <= 0x10A0) return indic_table[u - 0x0900 + indic_offset_0x0900];
+ if (0x1700 <= u && u <= 0x1800) return indic_table[u - 0x1700 + indic_offset_0x1700];
+ if (0x1900 <= u && u <= 0x1AB0) return indic_table[u - 0x1900 + indic_offset_0x1900];
+ if (0x1B00 <= u && u <= 0x1C50) return indic_table[u - 0x1B00 + indic_offset_0x1b00];
+ if (0xA800 <= u && u <= 0xAAE0) return indic_table[u - 0xA800 + indic_offset_0xa800];
+ if (0xABC0 <= u && u <= 0xAC00) return indic_table[u - 0xABC0 + indic_offset_0xabc0];
+ if (0x10A00 <= u && u <= 0x10A60) return indic_table[u - 0x10A00 + indic_offset_0x10a00];
+ if (0x11000 <= u && u <= 0x110D0) return indic_table[u - 0x11000 + indic_offset_0x11000];
+ if (unlikely (u == 0x00A0)) return _(CP,x);
+ if (unlikely (u == 0x25CC)) return _(CP,x);
+ return _(x,x);
+}
+
+#undef _
+
+#undef ISC_A
+#undef ISC_Bi
+#undef ISC_C
+#undef ISC_CD
+#undef ISC_CF
+#undef ISC_CHL
+#undef ISC_CM
+#undef ISC_CP
+#undef ISC_CR
+#undef ISC_CS
+#undef ISC_ML
+#undef ISC_N
+#undef ISC_x
+#undef ISC_RS
+#undef ISC_TL
+#undef ISC_TM
+#undef ISC_V
+#undef ISC_Vs
+#undef ISC_Vo
+#undef ISC_M
+#undef ISC_VI
+
+#undef IMC_B
+#undef IMC_BR
+#undef IMC_I
+#undef IMC_L
+#undef IMC_LR
+#undef IMC_x
+#undef IMC_O
+#undef IMC_R
+#undef IMC_T
+#undef IMC_TB
+#undef IMC_TBR
+#undef IMC_TL
+#undef IMC_TLR
+#undef IMC_TR
+#undef IMC_VOL
+
+
+/* == End of generated table == */
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_INDIC_TABLE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
new file mode 100644
index 0000000..9f50ef2
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc
@@ -0,0 +1,765 @@
+/*
+ * Copyright © 2011 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-private.hh"
+
+
+
+/* buffer var allocations */
+#define indic_category() complex_var_persistent_u8_0() /* indic_category_t */
+#define indic_position() complex_var_persistent_u8_1() /* indic_matra_category_t */
+
+#define INDIC_TABLE_ELEMENT_TYPE uint8_t
+
+/* Cateories used in the OpenType spec:
+ * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx
+ */
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum indic_category_t {
+ OT_X = 0,
+ OT_C,
+ OT_Ra, /* Not explicitly listed in the OT spec, but used in the grammar. */
+ OT_V,
+ OT_N,
+ OT_H,
+ OT_ZWNJ,
+ OT_ZWJ,
+ OT_M,
+ OT_SM,
+ OT_VD,
+ OT_A,
+ OT_NBSP
+};
+
+/* Visual positions in a syllable from left to right. */
+enum indic_position_t {
+ POS_PRE,
+ POS_BASE,
+ POS_ABOVE,
+ POS_BELOW,
+ POS_POST
+};
+
+/* Categories used in IndicSyllabicCategory.txt from UCD */
+/* The assignments are guesswork */
+enum indic_syllabic_category_t {
+ INDIC_SYLLABIC_CATEGORY_OTHER = OT_X,
+
+ INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_X,
+ INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_C,
+ INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA = OT_C,
+ INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
+ INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
+ INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_X,
+ INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
+ INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_X,
+ INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
+ INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM,
+ INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V,
+ INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M,
+ INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V
+};
+
+/* Categories used in IndicSMatraCategory.txt from UCD */
+enum indic_matra_category_t {
+ INDIC_MATRA_CATEGORY_NOT_APPLICABLE = POS_BASE,
+
+ INDIC_MATRA_CATEGORY_LEFT = POS_PRE,
+ INDIC_MATRA_CATEGORY_TOP = POS_ABOVE,
+ INDIC_MATRA_CATEGORY_BOTTOM = POS_BELOW,
+ INDIC_MATRA_CATEGORY_RIGHT = POS_POST,
+
+ /* We don't really care much about these since we decompose them
+ * in the generic pre-shaping layer. They will only be used if
+ * the font does not cover the decomposition. In which case, we
+ * define these as aliases to the place we want the split-matra
+ * glyph to show up. Quite arbitrary. */
+ INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_BOTTOM,
+ INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_LEFT,
+ INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM = INDIC_MATRA_CATEGORY_BOTTOM,
+ INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_BOTTOM,
+ INDIC_MATRA_CATEGORY_TOP_AND_LEFT = INDIC_MATRA_CATEGORY_LEFT,
+ INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_LEFT,
+ INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
+
+ INDIC_MATRA_CATEGORY_INVISIBLE = INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
+ INDIC_MATRA_CATEGORY_OVERSTRUCK = INDIC_MATRA_CATEGORY_NOT_APPLICABLE,
+ INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = INDIC_MATRA_CATEGORY_NOT_APPLICABLE
+};
+
+/* Note: We use ASSERT_STATIC_EXPR_ZERO() instead of ASSERT_STATIC_EXPR() and the comma operation
+ * because gcc fails to optimize the latter and fills the table in at runtime. */
+#define INDIC_COMBINE_CATEGORIES(S,M) \
+ (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || (S == INDIC_SYLLABIC_CATEGORY_VIRAMA || S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT)) + \
+ ASSERT_STATIC_EXPR_ZERO (S < 16 && M < 16) + \
+ ((M << 4) | S))
+
+#include "hb-ot-shape-complex-indic-table.hh"
+
+/* XXX
+ * This is a hack for now. We should:
+ * 1. Move this data into the main Indic table,
+ * and/or
+ * 2. Probe font lookups to determine consonant positions.
+ */
+static const struct consonant_position_t {
+ hb_codepoint_t u;
+ indic_position_t position;
+} consonant_positions[] = {
+ {0x0930, POS_BELOW},
+ {0x09AC, POS_BELOW},
+ {0x09AF, POS_POST},
+ {0x09B0, POS_BELOW},
+ {0x09F0, POS_BELOW},
+ {0x0A2F, POS_POST},
+ {0x0A30, POS_BELOW},
+ {0x0A35, POS_BELOW},
+ {0x0A39, POS_BELOW},
+ {0x0AB0, POS_BELOW},
+ {0x0B24, POS_BELOW},
+ {0x0B28, POS_BELOW},
+ {0x0B2C, POS_BELOW},
+ {0x0B2D, POS_BELOW},
+ {0x0B2E, POS_BELOW},
+ {0x0B2F, POS_POST},
+ {0x0B30, POS_BELOW},
+ {0x0B32, POS_BELOW},
+ {0x0B33, POS_BELOW},
+ {0x0B5F, POS_POST},
+ {0x0B71, POS_BELOW},
+ {0x0C15, POS_BELOW},
+ {0x0C16, POS_BELOW},
+ {0x0C17, POS_BELOW},
+ {0x0C18, POS_BELOW},
+ {0x0C19, POS_BELOW},
+ {0x0C1A, POS_BELOW},
+ {0x0C1B, POS_BELOW},
+ {0x0C1C, POS_BELOW},
+ {0x0C1D, POS_BELOW},
+ {0x0C1E, POS_BELOW},
+ {0x0C1F, POS_BELOW},
+ {0x0C20, POS_BELOW},
+ {0x0C21, POS_BELOW},
+ {0x0C22, POS_BELOW},
+ {0x0C23, POS_BELOW},
+ {0x0C24, POS_BELOW},
+ {0x0C25, POS_BELOW},
+ {0x0C26, POS_BELOW},
+ {0x0C27, POS_BELOW},
+ {0x0C28, POS_BELOW},
+ {0x0C2A, POS_BELOW},
+ {0x0C2B, POS_BELOW},
+ {0x0C2C, POS_BELOW},
+ {0x0C2D, POS_BELOW},
+ {0x0C2E, POS_BELOW},
+ {0x0C2F, POS_BELOW},
+ {0x0C30, POS_BELOW},
+ {0x0C32, POS_BELOW},
+ {0x0C33, POS_BELOW},
+ {0x0C35, POS_BELOW},
+ {0x0C36, POS_BELOW},
+ {0x0C37, POS_BELOW},
+ {0x0C38, POS_BELOW},
+ {0x0C39, POS_BELOW},
+ {0x0C95, POS_BELOW},
+ {0x0C96, POS_BELOW},
+ {0x0C97, POS_BELOW},
+ {0x0C98, POS_BELOW},
+ {0x0C99, POS_BELOW},
+ {0x0C9A, POS_BELOW},
+ {0x0C9B, POS_BELOW},
+ {0x0C9C, POS_BELOW},
+ {0x0C9D, POS_BELOW},
+ {0x0C9E, POS_BELOW},
+ {0x0C9F, POS_BELOW},
+ {0x0CA0, POS_BELOW},
+ {0x0CA1, POS_BELOW},
+ {0x0CA2, POS_BELOW},
+ {0x0CA3, POS_BELOW},
+ {0x0CA4, POS_BELOW},
+ {0x0CA5, POS_BELOW},
+ {0x0CA6, POS_BELOW},
+ {0x0CA7, POS_BELOW},
+ {0x0CA8, POS_BELOW},
+ {0x0CAA, POS_BELOW},
+ {0x0CAB, POS_BELOW},
+ {0x0CAC, POS_BELOW},
+ {0x0CAD, POS_BELOW},
+ {0x0CAE, POS_BELOW},
+ {0x0CAF, POS_BELOW},
+ {0x0CB0, POS_BELOW},
+ {0x0CB2, POS_BELOW},
+ {0x0CB3, POS_BELOW},
+ {0x0CB5, POS_BELOW},
+ {0x0CB6, POS_BELOW},
+ {0x0CB7, POS_BELOW},
+ {0x0CB8, POS_BELOW},
+ {0x0CB9, POS_BELOW},
+ {0x0CDE, POS_BELOW},
+ {0x0D2F, POS_POST},
+ {0x0D30, POS_POST},
+ {0x0D32, POS_BELOW},
+ {0x0D35, POS_POST},
+};
+
+/* XXX
+ * This is a hack for now. We should move this data into the main Indic table.
+ */
+static const hb_codepoint_t ra_chars[] = {
+ 0x0930, /* Devanagari */
+ 0x09B0, /* Bengali */
+ 0x09F0, /* Bengali */
+//0x09F1, /* Bengali */
+//0x0A30, /* Gurmukhi */
+ 0x0AB0, /* Gujarati */
+ 0x0B30, /* Oriya */
+//0x0BB0, /* Tamil */
+//0x0C30, /* Telugu */
+ 0x0CB0, /* Kannada */
+//0x0D30, /* Malayalam */
+};
+
+static int
+compare_codepoint (const void *pa, const void *pb)
+{
+ hb_codepoint_t a = * (hb_codepoint_t *) pa;
+ hb_codepoint_t b = * (hb_codepoint_t *) pb;
+
+ return a < b ? -1 : a == b ? 0 : +1;
+}
+
+static indic_position_t
+consonant_position (hb_codepoint_t u)
+{
+ consonant_position_t *record;
+
+ record = (consonant_position_t *) bsearch (&u, consonant_positions,
+ ARRAY_LENGTH (consonant_positions),
+ sizeof (consonant_positions[0]),
+ compare_codepoint);
+
+ return record ? record->position : POS_BASE;
+}
+
+static bool
+is_ra (hb_codepoint_t u)
+{
+ return !!bsearch (&u, ra_chars,
+ ARRAY_LENGTH (ra_chars),
+ sizeof (ra_chars[0]),
+ compare_codepoint);
+}
+
+static bool
+is_joiner (const hb_glyph_info_t &info)
+{
+ return !!(FLAG (info.indic_category()) & (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ)));
+}
+
+static bool
+is_consonant (const hb_glyph_info_t &info)
+{
+ return !!(FLAG (info.indic_category()) & (FLAG (OT_C) | FLAG (OT_Ra)));
+}
+
+static const struct {
+ hb_tag_t tag;
+ hb_bool_t is_global;
+} indic_basic_features[] =
+{
+ {HB_TAG('n','u','k','t'), true},
+ {HB_TAG('a','k','h','n'), false},
+ {HB_TAG('r','p','h','f'), false},
+ {HB_TAG('r','k','r','f'), false},
+ {HB_TAG('p','r','e','f'), false},
+ {HB_TAG('b','l','w','f'), false},
+ {HB_TAG('h','a','l','f'), false},
+ {HB_TAG('v','a','t','u'), true},
+ {HB_TAG('p','s','t','f'), false},
+ {HB_TAG('c','j','c','t'), false},
+};
+
+/* Same order as the indic_basic_features array */
+enum {
+ _NUKT,
+ AKHN,
+ RPHF,
+ RKRF,
+ PREF,
+ BLWF,
+ HALF,
+ _VATU,
+ PSTF,
+ CJCT
+};
+
+static const hb_tag_t indic_other_features[] =
+{
+ HB_TAG('p','r','e','s'),
+ HB_TAG('a','b','v','s'),
+ HB_TAG('b','l','w','s'),
+ HB_TAG('p','s','t','s'),
+ HB_TAG('h','a','l','n'),
+
+ HB_TAG('d','i','s','t'),
+ HB_TAG('a','b','v','m'),
+ HB_TAG('b','l','w','m'),
+};
+
+
+static void
+initial_reordering (const hb_ot_map_t *map,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ void *user_data HB_UNUSED);
+static void
+final_reordering (const hb_ot_map_t *map,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ void *user_data HB_UNUSED);
+
+void
+_hb_ot_shape_complex_collect_features_indic (hb_ot_map_builder_t *map, const hb_segment_properties_t *props)
+{
+ map->add_bool_feature (HB_TAG('l','o','c','l'));
+ /* The Indic specs do not require ccmp, but we apply it here since if
+ * there is a use of it, it's typically at the beginning. */
+ map->add_bool_feature (HB_TAG('c','c','m','p'));
+
+ map->add_gsub_pause (initial_reordering, NULL);
+
+ for (unsigned int i = 0; i < ARRAY_LENGTH (indic_basic_features); i++)
+ map->add_bool_feature (indic_basic_features[i].tag, indic_basic_features[i].is_global);
+
+ map->add_gsub_pause (final_reordering, NULL);
+
+ for (unsigned int i = 0; i < ARRAY_LENGTH (indic_other_features); i++)
+ map->add_bool_feature (indic_other_features[i], true);
+}
+
+
+bool
+_hb_ot_shape_complex_prefer_decomposed_indic (void)
+{
+ /* We want split matras decomposed by the common shaping logic. */
+ return TRUE;
+}
+
+
+void
+_hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map, hb_buffer_t *buffer)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, indic_category);
+ HB_BUFFER_ALLOCATE_VAR (buffer, indic_position);
+
+ /* We cannot setup masks here. We save information about characters
+ * and setup masks later on in a pause-callback. */
+
+ unsigned int count = buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ unsigned int type = get_indic_categories (buffer->info[i].codepoint);
+
+ buffer->info[i].indic_category() = type & 0x0F;
+ buffer->info[i].indic_position() = type >> 4;
+
+ if (buffer->info[i].indic_category() == OT_C) {
+ buffer->info[i].indic_position() = consonant_position (buffer->info[i].codepoint);
+ if (is_ra (buffer->info[i].codepoint))
+ buffer->info[i].indic_category() = OT_Ra;
+ } else if (buffer->info[i].codepoint == 0x200C)
+ buffer->info[i].indic_category() = OT_ZWNJ;
+ else if (buffer->info[i].codepoint == 0x200D)
+ buffer->info[i].indic_category() = OT_ZWJ;
+ }
+}
+
+static int
+compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
+{
+ int a = pa->indic_position();
+ int b = pb->indic_position();
+
+ return a < b ? -1 : a == b ? 0 : +1;
+}
+
+static void
+found_consonant_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
+ unsigned int start, unsigned int end)
+{
+ unsigned int i;
+ hb_glyph_info_t *info = buffer->info;
+
+ /* Comments from:
+ * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx */
+
+ /* 1. Find base consonant:
+ *
+ * The shaping engine finds the base consonant of the syllable, using the
+ * following algorithm: starting from the end of the syllable, move backwards
+ * until a consonant is found that does not have a below-base or post-base
+ * form (post-base forms have to follow below-base forms), or that is not a
+ * pre-base reordering Ra, or arrive at the first consonant. The consonant
+ * stopped at will be the base.
+ *
+ * o If the syllable starts with Ra + Halant (in a script that has Reph)
+ * and has more than one consonant, Ra is excluded from candidates for
+ * base consonants.
+ */
+
+ unsigned int base = end;
+
+ /* -> starting from the end of the syllable, move backwards */
+ i = end;
+ unsigned int limit = start;
+ if (info[start].indic_category() == OT_Ra && start + 2 <= end) {
+ limit += 2;
+ base = start;
+ };
+ do {
+ i--;
+ /* -> until a consonant is found */
+ if (is_consonant (info[i]))
+ {
+ /* -> that does not have a below-base or post-base form
+ * (post-base forms have to follow below-base forms), */
+ if (info[i].indic_position() != POS_BELOW &&
+ info[i].indic_position() != POS_POST)
+ {
+ base = i;
+ break;
+ }
+
+ /* -> or that is not a pre-base reordering Ra,
+ *
+ * TODO
+ */
+
+ /* -> o If the syllable starts with Ra + Halant (in a script that has Reph)
+ * and has more than one consonant, Ra is excluded from candidates for
+ * base consonants.
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * We do this by adjusting limit accordingly before entering the loop.
+ */
+
+ /* -> or arrive at the first consonant. The consonant stopped at will
+ * be the base. */
+ base = i;
+ }
+ else
+ if (is_joiner (info[i]))
+ break;
+ } while (i > limit);
+ if (base < start)
+ base = start; /* Just in case... */
+
+
+ /* 2. Decompose and reorder Matras:
+ *
+ * Each matra and any syllable modifier sign in the cluster are moved to the
+ * appropriate position relative to the consonant(s) in the cluster. The
+ * shaping engine decomposes two- or three-part matras into their constituent
+ * parts before any repositioning. Matra characters are classified by which
+ * consonant in a conjunct they have affinity for and are reordered to the
+ * following positions:
+ *
+ * o Before first half form in the syllable
+ * o After subjoined consonants
+ * o After post-form consonant
+ * o After main consonant (for above marks)
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * The normalize() routine has already decomposed matras for us, so we don't
+ * need to worry about that.
+ */
+
+
+ /* 3. Reorder marks to canonical order:
+ *
+ * Adjacent nukta and halant or nukta and vedic sign are always repositioned
+ * if necessary, so that the nukta is first.
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * We don't need to do this: the normalize() routine already did this for us.
+ */
+
+
+ /* Reorder characters */
+
+ for (i = start; i < base; i++)
+ info[i].indic_position() = POS_PRE;
+ info[base].indic_position() = POS_BASE;
+
+
+ /* Handle beginning Ra */
+ if (start + 3 <= end &&
+ info[start].indic_category() == OT_Ra &&
+ info[start + 1].indic_category() == OT_H &&
+ !is_joiner (info[start + 2]))
+ {
+ info[start].indic_position() = POS_POST;
+ info[start].mask = mask_array[RPHF];
+ }
+
+ /* For old-style Indic script tags, move the first post-base Halant after
+ * last consonant. */
+ if ((map->get_chosen_script (0) & 0x000000FF) != '2') {
+ /* We should only do this for Indic scripts which have a version two I guess. */
+ for (i = base + 1; i < end; i++)
+ if (info[i].indic_category() == OT_H) {
+ unsigned int j;
+ for (j = end - 1; j > i; j--)
+ if ((FLAG (info[j].indic_category()) & (FLAG (OT_C) | FLAG (OT_Ra))))
+ break;
+ if (j > i) {
+ /* Move Halant to after last consonant. */
+ hb_glyph_info_t t = info[i];
+ memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0]));
+ info[j] = t;
+ }
+ break;
+ }
+ }
+
+ /* Attach ZWJ, ZWNJ, nukta, and halant to previous char to move with them. */
+ for (i = start + 1; i < end; i++)
+ if ((FLAG (info[i].indic_category()) &
+ (FLAG (OT_ZWNJ) | FLAG (OT_ZWJ) | FLAG (OT_N) | FLAG (OT_H))))
+ info[i].indic_position() = info[i - 1].indic_position();
+
+ /* We do bubble-sort, skip malicious clusters attempts */
+ if (end - start > 20)
+ return;
+
+ /* Sit tight, rock 'n roll! */
+ hb_bubble_sort (info + start, end - start, compare_indic_order);
+
+ /* Setup masks now */
+
+ {
+ hb_mask_t mask;
+
+ /* Pre-base */
+ mask = mask_array[HALF] | mask_array[AKHN] | mask_array[CJCT];
+ for (i = start; i < base; i++)
+ info[i].mask |= mask;
+ /* Base */
+ mask = mask_array[AKHN] | mask_array[CJCT];
+ info[base].mask |= mask;
+ /* Post-base */
+ mask = mask_array[BLWF] | mask_array[PSTF] | mask_array[CJCT];
+ for (i = base + 1; i < end; i++)
+ info[i].mask |= mask;
+ }
+
+ /* Apply ZWJ/ZWNJ effects */
+ for (i = start + 1; i < end; i++)
+ if (is_joiner (info[i])) {
+ bool non_joiner = info[i].indic_category() == OT_ZWNJ;
+ unsigned int j = i;
+
+ do {
+ j--;
+
+ /* Reading the Unicode and OpenType specs, I think the following line
+ * is correct, but this is not what the test suite expects currently.
+ * The test suite has been drinking, not me... But disable while
+ * investigating.
+ */
+ //info[j].mask &= !mask_array[CJCT];
+ if (non_joiner)
+ info[j].mask &= !mask_array[HALF];
+
+ } while (j > start && !is_consonant (info[j]));
+ }
+}
+
+
+static void
+found_vowel_syllable (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
+ unsigned int start, unsigned int end)
+{
+ /* TODO
+ * Not clear to me how this should work. Do the matras move to before the
+ * independent vowel? No idea.
+ */
+}
+
+static void
+found_standalone_cluster (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
+ unsigned int start, unsigned int end)
+{
+ /* TODO
+ * Easiest thing to do here is to convert the NBSP to consonant and
+ * call found_consonant_syllable.
+ */
+}
+
+static void
+found_non_indic (const hb_ot_map_t *map, hb_buffer_t *buffer, hb_mask_t *mask_array,
+ unsigned int start, unsigned int end)
+{
+ /* Nothing to do right now. If we ever switch to using the output
+ * buffer in the reordering process, we'd need to next_glyph() here. */
+}
+
+#include "hb-ot-shape-complex-indic-machine.hh"
+
+static void
+remove_joiners (hb_buffer_t *buffer)
+{
+ /* For now we remove joiners. However, Uniscbire seems to keep them
+ * and output a zero-width space glyph for them. It is not clear to
+ * me how that is supposed to interact with GSUB. */
+
+ buffer->clear_output ();
+ unsigned int count = buffer->len;
+ for (buffer->idx = 0; buffer->idx < count;)
+ if (unlikely (is_joiner (buffer->info[buffer->idx])))
+ buffer->skip_glyph ();
+ else
+ buffer->next_glyph ();
+
+ buffer->swap_buffers ();
+}
+
+static void
+initial_reordering (const hb_ot_map_t *map,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ void *user_data HB_UNUSED)
+{
+ hb_mask_t mask_array[ARRAY_LENGTH (indic_basic_features)] = {0};
+ unsigned int num_masks = ARRAY_LENGTH (indic_basic_features);
+ for (unsigned int i = 0; i < num_masks; i++)
+ mask_array[i] = map->get_1_mask (indic_basic_features[i].tag);
+
+ find_syllables (map, buffer, mask_array);
+
+ remove_joiners (buffer);
+}
+
+static void
+final_reordering (const hb_ot_map_t *map,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ void *user_data HB_UNUSED)
+{
+ /* 4. Final reordering:
+ *
+ * After the localized forms and basic shaping forms GSUB features have been
+ * applied (see below), the shaping engine performs some final glyph
+ * reordering before applying all the remaining font features to the entire
+ * cluster.
+ *
+ * o Reorder matras:
+ *
+ * If a pre-base matra character had been reordered before applying basic
+ * features, the glyph can be moved closer to the main consonant based on
+ * whether half-forms had been formed. Actual position for the matra is
+ * defined as “after last standalone halant glyph, after initial matra
+ * position and before the main consonant”. If ZWJ or ZWNJ follow this
+ * halant, position is moved after it.
+ *
+ * o Reorder reph:
+ *
+ * Reph’s original position is always at the beginning of the syllable,
+ * (i.e. it is not reordered at the character reordering stage). However,
+ * it will be reordered according to the basic-forms shaping results.
+ * Possible positions for reph, depending on the script, are; after main,
+ * before post-base consonant forms, and after post-base consonant forms.
+ *
+ * 1. If reph should be positioned after post-base consonant forms,
+ * proceed to step 5.
+ *
+ * 2. If the reph repositioning class is not after post-base: target
+ * position is after the first explicit halant glyph between the
+ * first post-reph consonant and last main consonant. If ZWJ or ZWNJ
+ * are following this halant, position is moved after it. If such
+ * position is found, this is the target position. Otherwise,
+ * proceed to the next step.
+ *
+ * Note: in old-implementation fonts, where classifications were
+ * fixed in shaping engine, there was no case where reph position
+ * will be found on this step.
+ *
+ * 3. If reph should be repositioned after the main consonant: from the
+ * first consonant not ligated with main, or find the first
+ * consonant that is not a potential pre-base reordering Ra.
+ *
+ *
+ * 4. If reph should be positioned before post-base consonant, find
+ * first post-base classified consonant not ligated with main. If no
+ * consonant is found, the target position should be before the
+ * first matra, syllable modifier sign or vedic sign.
+ *
+ * 5. If no consonant is found in steps 3 or 4, move reph to a position
+ * immediately before the first post-base matra, syllable modifier
+ * sign or vedic sign that has a reordering class after the intended
+ * reph position. For example, if the reordering position for reph
+ * is post-main, it will skip above-base matras that also have a
+ * post-main position.
+ *
+ * 6. Otherwise, reorder reph to the end of the syllable.
+ *
+ * o Reorder pre-base reordering consonants:
+ *
+ * If a pre-base reordering consonant is found, reorder it according to
+ * the following rules:
+ *
+ * 1. Only reorder a glyph produced by substitution during application
+ * of the feature. (Note that a font may shape a Ra consonant with
+ * the feature generally but block it in certain contexts.)
+ *
+ * 2. Try to find a target position the same way as for pre-base matra.
+ * If it is found, reorder pre-base consonant glyph.
+ *
+ * 3. If position is not found, reorder immediately before main
+ * consonant.
+ */
+
+ /* TODO */
+
+
+
+ HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
+ HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
+}
+
+
+
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-misc.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-misc.cc
new file mode 100644
index 0000000..230704f
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-misc.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2010 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-private.hh"
+
+
+/* TODO Add kana, hangul, and other small sahpers here */
+
+/* When adding trivial shapers, eg. kana, hangul, etc, we can either
+ * add a full shaper enum value for them, or switch on the script in
+ * the default complex shaper. The former is faster, so I think that's
+ * what we would do, and hence the default complex shaper shall remain
+ * empty.
+ */
+
+void
+_hb_ot_shape_complex_collect_features_default (hb_ot_map_builder_t *map, const hb_segment_properties_t *props)
+{
+}
+
+bool
+_hb_ot_shape_complex_prefer_decomposed_default (void)
+{
+ return FALSE;
+}
+
+void
+_hb_ot_shape_complex_setup_masks_default (hb_ot_map_t *map, hb_buffer_t *buffer)
+{
+}
+
+
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
index fed167d..8b775fb 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2010,2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -27,26 +27,114 @@
#ifndef HB_OT_SHAPE_COMPLEX_PRIVATE_HH
#define HB_OT_SHAPE_COMPLEX_PRIVATE_HH
-#include "hb-private.h"
+#include "hb-private.hh"
-#include "hb-ot-shape-private.hh"
+#include "hb-ot-map-private.hh"
-HB_BEGIN_DECLS
+/* buffer var allocations, used during the entire shaping process */
+#define general_category() var1.u8[0] /* unicode general_category (hb_unicode_general_category_t) */
+#define combining_class() var1.u8[1] /* unicode combining_class (uint8_t) */
+
+/* buffer var allocations, used by complex shapers */
+#define complex_var_persistent_u8_0() var2.u8[0]
+#define complex_var_persistent_u8_1() var2.u8[1]
+#define complex_var_persistent_u16() var2.u16[0]
+#define complex_var_temporary_u8_0() var2.u8[2]
+#define complex_var_temporary_u8_1() var2.u8[3]
+#define complex_var_temporary_u16() var2.u16[1]
+
+
+#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
+ HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
+ HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
+ HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
+ /* ^--- Add new shapers here */
+
+enum hb_ot_complex_shaper_t {
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) hb_ot_complex_shaper_##name,
+ HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+ /* Just here to avoid enum trailing comma: */
+ hb_ot_complex_shaper_generic = hb_ot_complex_shaper_default
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
+};
+
static inline hb_ot_complex_shaper_t
hb_ot_shape_complex_categorize (const hb_segment_properties_t *props)
{
- switch ((int) props->script) {
+ switch ((int) props->script)
+ {
+ default:
+ return hb_ot_complex_shaper_default;
+
case HB_SCRIPT_ARABIC:
- case HB_SCRIPT_NKO:
- case HB_SCRIPT_SYRIAC:
case HB_SCRIPT_MANDAIC:
case HB_SCRIPT_MONGOLIAN:
+ case HB_SCRIPT_NKO:
+ case HB_SCRIPT_SYRIAC:
return hb_ot_complex_shaper_arabic;
- default:
- return hb_ot_complex_shaper_none;
+#if 0
+ /* Note:
+ *
+ * These disabled scripts are listed in ucd/IndicSyllabicCategory.txt, but according
+ * to Martin Hosken do not require complex shaping.
+ *
+ * TODO We currently keep data for these scripts in our indic table. Need to fix the
+ * generator to not do that.
+ */
+
+ /* Simple? */
+ case HB_SCRIPT_BATAK:
+ case HB_SCRIPT_BRAHMI:
+ case HB_SCRIPT_HANUNOO:
+ case HB_SCRIPT_MEETEI_MAYEK:
+ case HB_SCRIPT_SAURASHTRA:
+
+ /* Simple */
+ case HB_SCRIPT_KAYAH_LI:
+ case HB_SCRIPT_LAO:
+ case HB_SCRIPT_LIMBU:
+ case HB_SCRIPT_PHAGS_PA:
+ case HB_SCRIPT_SYLOTI_NAGRI:
+ case HB_SCRIPT_TAGALOG:
+ case HB_SCRIPT_TAGBANWA:
+ case HB_SCRIPT_TAI_LE:
+ case HB_SCRIPT_TAI_VIET:
+ case HB_SCRIPT_THAI:
+ case HB_SCRIPT_TIBETAN:
+
+ /* May need Indic treatment in the future? */
+ case HB_SCRIPT_MYANMAR:
+#endif
+
+ case HB_SCRIPT_BALINESE:
+ case HB_SCRIPT_BENGALI:
+ case HB_SCRIPT_BUGINESE:
+ case HB_SCRIPT_BUHID:
+ case HB_SCRIPT_CHAM:
+ case HB_SCRIPT_DEVANAGARI:
+ case HB_SCRIPT_GUJARATI:
+ case HB_SCRIPT_GURMUKHI:
+ case HB_SCRIPT_JAVANESE:
+ case HB_SCRIPT_KAITHI:
+ case HB_SCRIPT_KANNADA:
+ case HB_SCRIPT_KHAROSHTHI:
+ case HB_SCRIPT_KHMER:
+ case HB_SCRIPT_LEPCHA:
+ case HB_SCRIPT_MALAYALAM:
+ case HB_SCRIPT_NEW_TAI_LUE:
+ case HB_SCRIPT_ORIYA:
+ case HB_SCRIPT_REJANG:
+ case HB_SCRIPT_SINHALA:
+ case HB_SCRIPT_SUNDANESE:
+ case HB_SCRIPT_TAI_THAM:
+ case HB_SCRIPT_TAMIL:
+ case HB_SCRIPT_TELUGU:
+ return hb_ot_complex_shaper_indic;
+
+ /* ^--- Add new shapers here */
}
}
@@ -57,18 +145,53 @@ hb_ot_shape_complex_categorize (const hb_segment_properties_t *props)
*
* Called during shape_plan().
*
- * Shapers should use plan->map to add their features.
+ * Shapers should use map to add their features and callbacks.
*/
-HB_INTERNAL void _hb_ot_shape_complex_collect_features_arabic (hb_ot_shape_plan_t *plan, const hb_segment_properties_t *props);
+typedef void hb_ot_shape_complex_collect_features_func_t (hb_ot_map_builder_t *map, const hb_segment_properties_t *props);
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
+ HB_INTERNAL hb_ot_shape_complex_collect_features_func_t _hb_ot_shape_complex_collect_features_##name;
+ HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
static inline void
-hb_ot_shape_complex_collect_features (hb_ot_shape_plan_t *plan,
+hb_ot_shape_complex_collect_features (hb_ot_complex_shaper_t shaper,
+ hb_ot_map_builder_t *map,
const hb_segment_properties_t *props)
{
- switch (plan->shaper) {
- case hb_ot_complex_shaper_arabic: _hb_ot_shape_complex_collect_features_arabic (plan, props); return;
- case hb_ot_complex_shaper_none: default: return;
+ switch (shaper) {
+ default:
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
+ case hb_ot_complex_shaper_##name: _hb_ot_shape_complex_collect_features_##name (map, props); return;
+ HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
+ }
+}
+
+
+/*
+ * prefer_decomposed()
+ *
+ * Called during shape_execute().
+ *
+ * Shapers should return TRUE if it prefers decomposed (NFD) input rather than precomposed (NFC).
+ */
+
+typedef bool hb_ot_shape_complex_prefer_decomposed_func_t (void);
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
+ HB_INTERNAL hb_ot_shape_complex_prefer_decomposed_func_t _hb_ot_shape_complex_prefer_decomposed_##name;
+ HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
+
+static inline bool
+hb_ot_shape_complex_prefer_decomposed (hb_ot_complex_shaper_t shaper)
+{
+ switch (shaper) {
+ default:
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
+ case hb_ot_complex_shaper_##name: return _hb_ot_shape_complex_prefer_decomposed_##name ();
+ HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
}
}
@@ -77,21 +200,29 @@ hb_ot_shape_complex_collect_features (hb_ot_shape_plan_t *plan,
*
* Called during shape_execute().
*
- * Shapers should use c->plan.map to get feature masks and set on buffer.
+ * Shapers should use map to get feature masks and set on buffer.
*/
-HB_INTERNAL void _hb_ot_shape_complex_setup_masks_arabic (hb_ot_shape_context_t *c);
+typedef void hb_ot_shape_complex_setup_masks_func_t (hb_ot_map_t *map, hb_buffer_t *buffer);
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
+ HB_INTERNAL hb_ot_shape_complex_setup_masks_func_t _hb_ot_shape_complex_setup_masks_##name;
+ HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
static inline void
-hb_ot_shape_complex_setup_masks (hb_ot_shape_context_t *c)
+hb_ot_shape_complex_setup_masks (hb_ot_complex_shaper_t shaper,
+ hb_ot_map_t *map,
+ hb_buffer_t *buffer)
{
- switch (c->plan->shaper) {
- case hb_ot_complex_shaper_arabic: _hb_ot_shape_complex_setup_masks_arabic (c); return;
- case hb_ot_complex_shaper_none: default: return;
+ switch (shaper) {
+ default:
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) \
+ case hb_ot_complex_shaper_##name: _hb_ot_shape_complex_setup_masks_##name (map, buffer); return;
+ HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
}
}
-HB_END_DECLS
#endif /* HB_OT_SHAPE_COMPLEX_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
new file mode 100644
index 0000000..eb9f32a
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
@@ -0,0 +1,286 @@
+/*
+ * Copyright © 2011 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-private.hh"
+#include "hb-ot-shape-complex-private.hh"
+
+
+/*
+ * HIGHLEVEL DESIGN:
+ *
+ * This file exports one main function: _hb_ot_shape_normalize().
+ *
+ * This function closely reflects the Unicode Normalization Algorithm,
+ * yet it's different. The shaper an either prefer decomposed (NFD) or
+ * composed (NFC).
+ *
+ * In general what happens is that: each grapheme is decomposed in a chain
+ * of 1:2 decompositions, marks reordered, and then recomposed if desired,
+ * so far it's like Unicode Normalization. However, the decomposition and
+ * recomposition only happens if the font supports the resulting characters.
+ *
+ * The goals are:
+ *
+ * - Try to render all canonically equivalent strings similarly. To really
+ * achieve this we have to always do the full decomposition and then
+ * selectively recompose from there. It's kinda too expensive though, so
+ * we skip some cases. For example, if composed is desired, we simply
+ * don't touch 1-character clusters that are supported by the font, even
+ * though their NFC may be different.
+ *
+ * - When a font has a precomposed character for a sequence but the 'ccmp'
+ * feature in the font is not adequate, use the precomposed character
+ * which typically has better mark positioning.
+ *
+ * - When a font does not support a combining mark, but supports it precomposed
+ * with previous base. This needs the itemizer to have this knowledge too.
+ * We need ot provide assistance to the itemizer.
+ *
+ * - When a font does not support a character but supports its decomposition,
+ * well, use the decomposition.
+ *
+ * - The Indic shaper requests decomposed output. This will handle splitting
+ * matra for the Indic shaper.
+ */
+
+static void
+output_glyph (hb_ot_shape_context_t *c,
+ hb_codepoint_t glyph)
+{
+ hb_buffer_t *buffer = c->buffer;
+
+ buffer->output_glyph (glyph);
+ hb_glyph_info_set_unicode_props (&buffer->out_info[buffer->out_len - 1], buffer->unicode);
+}
+
+static bool
+decompose (hb_ot_shape_context_t *c,
+ bool shortest,
+ hb_codepoint_t ab)
+{
+ hb_codepoint_t a, b, glyph;
+
+ if (!hb_unicode_decompose (c->buffer->unicode, ab, &a, &b) ||
+ (b && !hb_font_get_glyph (c->font, b, 0, &glyph)))
+ return FALSE;
+
+ bool has_a = hb_font_get_glyph (c->font, a, 0, &glyph);
+ if (shortest && has_a) {
+ /* Output a and b */
+ output_glyph (c, a);
+ if (b)
+ output_glyph (c, b);
+ return TRUE;
+ }
+
+ if (decompose (c, shortest, a)) {
+ if (b)
+ output_glyph (c, b);
+ return TRUE;
+ }
+
+ if (has_a) {
+ output_glyph (c, a);
+ if (b)
+ output_glyph (c, b);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+decompose_current_glyph (hb_ot_shape_context_t *c,
+ bool shortest)
+{
+ if (decompose (c, shortest, c->buffer->info[c->buffer->idx].codepoint))
+ c->buffer->skip_glyph ();
+ else
+ c->buffer->next_glyph ();
+}
+
+static void
+decompose_single_char_cluster (hb_ot_shape_context_t *c,
+ bool will_recompose)
+{
+ hb_codepoint_t glyph;
+
+ /* If recomposing and font supports this, we're good to go */
+ if (will_recompose && hb_font_get_glyph (c->font, c->buffer->info[c->buffer->idx].codepoint, 0, &glyph)) {
+ c->buffer->next_glyph ();
+ return;
+ }
+
+ decompose_current_glyph (c, will_recompose);
+}
+
+static void
+decompose_multi_char_cluster (hb_ot_shape_context_t *c,
+ unsigned int end)
+{
+ /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
+ for (unsigned int i = c->buffer->idx; i < end; i++)
+ if (unlikely (is_variation_selector (c->buffer->info[i].codepoint))) {
+ while (c->buffer->idx < end)
+ c->buffer->next_glyph ();
+ return;
+ }
+
+ while (c->buffer->idx < end)
+ decompose_current_glyph (c, FALSE);
+}
+
+static int
+compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
+{
+ unsigned int a = pa->combining_class();
+ unsigned int b = pb->combining_class();
+
+ return a < b ? -1 : a == b ? 0 : +1;
+}
+
+void
+_hb_ot_shape_normalize (hb_ot_shape_context_t *c)
+{
+ hb_buffer_t *buffer = c->buffer;
+ bool recompose = !hb_ot_shape_complex_prefer_decomposed (c->plan->shaper);
+ bool has_multichar_clusters = FALSE;
+ unsigned int count;
+
+ /* We do a fairly straightforward yet custom normalization process in three
+ * separate rounds: decompose, reorder, recompose (if desired). Currently
+ * this makes two buffer swaps. We can make it faster by moving the last
+ * two rounds into the inner loop for the first round, but it's more readable
+ * this way. */
+
+
+ /* First round, decompose */
+
+ buffer->clear_output ();
+ count = buffer->len;
+ for (buffer->idx = 0; buffer->idx < count;)
+ {
+ unsigned int end;
+ for (end = buffer->idx + 1; end < count; end++)
+ if (buffer->info[buffer->idx].cluster != buffer->info[end].cluster)
+ break;
+
+ if (buffer->idx + 1 == end)
+ decompose_single_char_cluster (c, recompose);
+ else {
+ decompose_multi_char_cluster (c, end);
+ has_multichar_clusters = TRUE;
+ }
+ }
+ buffer->swap_buffers ();
+
+
+ /* Technically speaking, two characters with ccc=0 may combine. But all
+ * those cases are in languages that the indic module handles (which expects
+ * decomposed), or in Hangul jamo, which again, we want decomposed anyway.
+ * So we don't bother combining across cluster boundaries. This is a huge
+ * performance saver if the compose() callback is slow.
+ *
+ * TODO: Am I right about Hangul? If I am, we should add a Hangul module
+ * that requests decomposed. If for Hangul we end up wanting composed, we
+ * can do that in the Hangul module.
+ */
+
+ if (!has_multichar_clusters)
+ return; /* Done! */
+
+
+ /* Second round, reorder (inplace) */
+
+ count = buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (buffer->info[i].combining_class() == 0)
+ continue;
+
+ unsigned int end;
+ for (end = i + 1; end < count; end++)
+ if (buffer->info[end].combining_class() == 0)
+ break;
+
+ /* We are going to do a bubble-sort. Only do this if the
+ * sequence is short. Doing it on long sequences can result
+ * in an O(n^2) DoS. */
+ if (end - i > 10) {
+ i = end;
+ continue;
+ }
+
+ hb_bubble_sort (buffer->info + i, end - i, compare_combining_class);
+
+ i = end;
+ }
+
+
+ if (!recompose)
+ return;
+
+ /* Third round, recompose */
+
+ /* As noted in the comment earlier, we don't try to combine
+ * ccc=0 chars with their previous Starter. */
+
+ buffer->clear_output ();
+ count = buffer->len;
+ unsigned int starter = 0;
+ buffer->next_glyph ();
+ while (buffer->idx < count)
+ {
+ if (buffer->info[buffer->idx].combining_class() == 0) {
+ starter = buffer->out_len;
+ buffer->next_glyph ();
+ continue;
+ }
+
+ hb_codepoint_t composed, glyph;
+ if ((buffer->out_info[buffer->out_len - 1].combining_class() >=
+ buffer->info[buffer->idx].combining_class()) ||
+ !hb_unicode_compose (c->buffer->unicode,
+ buffer->out_info[starter].codepoint,
+ buffer->info[buffer->idx].codepoint,
+ &composed) ||
+ !hb_font_get_glyph (c->font, composed, 0, &glyph))
+ {
+ /* Blocked, or doesn't compose. */
+ buffer->next_glyph ();
+ continue;
+ }
+
+ /* Composes. Modify starter and carry on. */
+ buffer->out_info[starter].codepoint = composed;
+ hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode);
+
+ buffer->skip_glyph ();
+ }
+ buffer->swap_buffers ();
+
+}
+
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
index deaec97..c49c2b0 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-private.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2010 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -27,30 +27,49 @@
#ifndef HB_OT_SHAPE_PRIVATE_HH
#define HB_OT_SHAPE_PRIVATE_HH
-#include "hb-private.h"
+#include "hb-private.hh"
#include "hb-ot-shape.h"
#include "hb-ot-map-private.hh"
+#include "hb-ot-shape-complex-private.hh"
-HB_BEGIN_DECLS
-/* buffer var allocations */
-#define general_category() var1.u8[0] /* unicode general_category (hb_category_t) */
-#define combining_class() var1.u8[1] /* unicode combining_class (uint8_t) */
+enum hb_ot_complex_shaper_t;
+struct hb_ot_shape_plan_t
+{
+ friend struct hb_ot_shape_planner_t;
-enum hb_ot_complex_shaper_t {
- hb_ot_complex_shaper_none,
- hb_ot_complex_shaper_arabic
-};
+ hb_ot_map_t map;
+ hb_ot_complex_shaper_t shaper;
+ hb_ot_shape_plan_t (void) : map () {}
+ ~hb_ot_shape_plan_t (void) { map.finish (); }
-struct hb_ot_shape_plan_t
+ private:
+ NO_COPY (hb_ot_shape_plan_t);
+};
+
+struct hb_ot_shape_planner_t
{
- hb_ot_map_t map;
+ hb_ot_map_builder_t map;
hb_ot_complex_shaper_t shaper;
+
+ hb_ot_shape_planner_t (void) : map () {}
+ ~hb_ot_shape_planner_t (void) { map.finish (); }
+
+ inline void compile (hb_face_t *face,
+ const hb_segment_properties_t *props,
+ struct hb_ot_shape_plan_t &plan)
+ {
+ plan.shaper = shaper;
+ map.compile (face, props, plan.map);
+ }
+
+ private:
+ NO_COPY (hb_ot_shape_planner_t);
};
@@ -71,6 +90,40 @@ struct hb_ot_shape_context_t
};
-HB_END_DECLS
+static inline hb_bool_t
+is_variation_selector (hb_codepoint_t unicode)
+{
+ return unlikely ((unicode >= 0x180B && unicode <= 0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
+ (unicode >= 0xFE00 && unicode <= 0xFE0F) || /* VARIATION SELECTOR-1..16 */
+ (unicode >= 0xE0100 && unicode <= 0xE01EF)); /* VARIATION SELECTOR-17..256 */
+}
+
+static inline unsigned int
+_hb_unicode_modified_combining_class (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode)
+{
+ int c = hb_unicode_combining_class (ufuncs, unicode);
+
+ /* Modify the combining-class to suit Arabic better. See:
+ * http://unicode.org/faq/normalization.html#8
+ * http://unicode.org/faq/normalization.html#9
+ */
+ if (unlikely (hb_in_range<int> (c, 27, 33)))
+ c = c == 33 ? 27 : c + 1;
+
+ return c;
+}
+
+static inline void
+hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
+{
+ info->general_category() = hb_unicode_general_category (unicode, info->codepoint);
+ info->combining_class() = _hb_unicode_modified_combining_class (unicode, info->codepoint);
+}
+
+HB_INTERNAL void _hb_set_unicode_props (hb_buffer_t *buffer);
+
+HB_INTERNAL void _hb_ot_shape_normalize (hb_ot_shape_context_t *c);
+
#endif /* HB_OT_SHAPE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.cc b/third_party/harfbuzz-ng/src/hb-ot-shape.cc
index 92c3925..4275afc 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape.cc
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2009,2010 Red Hat, Inc.
- * Copyright (C) 2010 Google, Inc.
+ * Copyright © 2009,2010 Red Hat, Inc.
+ * Copyright © 2010,2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -29,53 +29,81 @@
#include "hb-ot-shape-private.hh"
#include "hb-ot-shape-complex-private.hh"
-HB_BEGIN_DECLS
+#include "hb-font-private.hh"
-/* XXX vertical */
-hb_tag_t default_features[] = {
- HB_TAG('c','a','l','t'),
+
+hb_tag_t common_features[] = {
HB_TAG('c','c','m','p'),
+ HB_TAG('l','o','c','l'),
+ HB_TAG('m','a','r','k'),
+ HB_TAG('m','k','m','k'),
+ HB_TAG('r','l','i','g'),
+};
+
+hb_tag_t horizontal_features[] = {
+ HB_TAG('c','a','l','t'),
HB_TAG('c','l','i','g'),
- HB_TAG('c','s','w','h'),
HB_TAG('c','u','r','s'),
HB_TAG('k','e','r','n'),
HB_TAG('l','i','g','a'),
- HB_TAG('l','o','c','l'),
- HB_TAG('m','a','r','k'),
- HB_TAG('m','k','m','k'),
- HB_TAG('r','l','i','g')
+};
+
+/* Note:
+ * Technically speaking, vrt2 and vert are mutually exclusive.
+ * According to the spec, valt and vpal are also mutually exclusive.
+ * But we apply them all for now.
+ */
+hb_tag_t vertical_features[] = {
+ HB_TAG('v','a','l','t'),
+ HB_TAG('v','e','r','t'),
+ HB_TAG('v','k','r','n'),
+ HB_TAG('v','p','a','l'),
+ HB_TAG('v','r','t','2'),
};
static void
-hb_ot_shape_collect_features (hb_ot_shape_plan_t *plan,
+hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
const hb_segment_properties_t *props,
- const hb_feature_t *user_features,
- unsigned int num_user_features)
+ const hb_feature_t *user_features,
+ unsigned int num_user_features)
{
switch (props->direction) {
case HB_DIRECTION_LTR:
- plan->map.add_bool_feature (HB_TAG ('l','t','r','a'));
- plan->map.add_bool_feature (HB_TAG ('l','t','r','m'));
+ planner->map.add_bool_feature (HB_TAG ('l','t','r','a'));
+ planner->map.add_bool_feature (HB_TAG ('l','t','r','m'));
break;
case HB_DIRECTION_RTL:
- plan->map.add_bool_feature (HB_TAG ('r','t','l','a'));
- plan->map.add_bool_feature (HB_TAG ('r','t','l','m'), false);
+ planner->map.add_bool_feature (HB_TAG ('r','t','l','a'));
+ planner->map.add_bool_feature (HB_TAG ('r','t','l','m'), false);
break;
case HB_DIRECTION_TTB:
case HB_DIRECTION_BTT:
+ case HB_DIRECTION_INVALID:
default:
break;
}
- for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
- plan->map.add_bool_feature (default_features[i]);
+#define ADD_FEATURES(array) \
+ HB_STMT_START { \
+ for (unsigned int i = 0; i < ARRAY_LENGTH (array); i++) \
+ planner->map.add_bool_feature (array[i]); \
+ } HB_STMT_END
+
+ hb_ot_shape_complex_collect_features (planner->shaper, &planner->map, props);
+
+ ADD_FEATURES (common_features);
+
+ if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
+ ADD_FEATURES (horizontal_features);
+ else
+ ADD_FEATURES (vertical_features);
- hb_ot_shape_complex_collect_features (plan, props);
+#undef ADD_FEATURES
for (unsigned int i = 0; i < num_user_features; i++) {
const hb_feature_t *feature = &user_features[i];
- plan->map.add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
+ planner->map.add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
}
}
@@ -86,7 +114,7 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
hb_mask_t global_mask = c->plan->map.get_global_mask ();
c->buffer->reset_masks (global_mask);
- hb_ot_shape_complex_setup_masks (c); /* BUFFER: Clobbers var2 */
+ hb_ot_shape_complex_setup_masks (c->plan->shaper, &c->plan->map, c->buffer);
for (unsigned int i = 0; i < c->num_user_features; i++)
{
@@ -100,98 +128,54 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
}
-static void
-hb_ot_substitute_complex (hb_ot_shape_context_t *c)
-{
- if (!hb_ot_layout_has_substitution (c->face))
- return;
-
- c->plan->map.substitute (c->face, c->buffer);
-
- c->applied_substitute_complex = TRUE;
- return;
-}
-
-static void
-hb_ot_position_complex (hb_ot_shape_context_t *c)
-{
-
- if (!hb_ot_layout_has_positioning (c->face))
- return;
-
- c->plan->map.position (c->font, c->face, c->buffer);
-
- hb_ot_layout_position_finish (c->buffer);
-
- c->applied_position_complex = TRUE;
- return;
-}
-
-
/* Main shaper */
/* Prepare */
-static inline hb_bool_t
-is_variation_selector (hb_codepoint_t unicode)
-{
- return unlikely ((unicode >= 0x180B && unicode <= 0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
- (unicode >= 0xFE00 && unicode <= 0xFE0F) || /* VARIATION SELECTOR-1..16 */
- (unicode >= 0xE0100 && unicode <= 0xE01EF)); /* VARIATION SELECTOR-17..256 */
-}
-
-static void
-hb_set_unicode_props (hb_ot_shape_context_t *c)
+void
+_hb_set_unicode_props (hb_buffer_t *buffer)
{
- hb_unicode_get_general_category_func_t get_general_category = c->buffer->unicode->v.get_general_category;
- hb_unicode_get_combining_class_func_t get_combining_class = c->buffer->unicode->v.get_combining_class;
- hb_glyph_info_t *info = c->buffer->info;
-
- unsigned int count = c->buffer->len;
- for (unsigned int i = 1; i < count; i++) {
- info[i].general_category() = get_general_category (info[i].codepoint);
- info[i].combining_class() = get_combining_class (info[i].codepoint);
- }
+ unsigned int count = buffer->len;
+ for (unsigned int i = 1; i < count; i++)
+ hb_glyph_info_set_unicode_props (&buffer->info[i], buffer->unicode);
}
static void
-hb_form_clusters (hb_ot_shape_context_t *c)
+hb_form_clusters (hb_buffer_t *buffer)
{
- unsigned int count = c->buffer->len;
+ unsigned int count = buffer->len;
for (unsigned int i = 1; i < count; i++)
- if (c->buffer->info[i].general_category() == HB_CATEGORY_NON_SPACING_MARK)
- c->buffer->info[i].cluster = c->buffer->info[i - 1].cluster;
+ if (FLAG (buffer->info[i].general_category()) &
+ (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
+ buffer->info[i].cluster = buffer->info[i - 1].cluster;
}
static void
-hb_ensure_native_direction (hb_ot_shape_context_t *c)
+hb_ensure_native_direction (hb_buffer_t *buffer)
{
- hb_direction_t direction = c->buffer->props.direction;
-
- /* TODO vertical */
- if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
- direction != _hb_script_get_horizontal_direction (c->buffer->props.script))
+ hb_direction_t direction = buffer->props.direction;
+
+ /* TODO vertical:
+ * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
+ * Ogham fonts are supposed to be implemented BTT or not. Need to research that
+ * first. */
+ if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_horizontal_direction (buffer->props.script)) ||
+ (HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB))
{
- hb_buffer_reverse_clusters (c->buffer);
- c->buffer->props.direction = HB_DIRECTION_REVERSE (c->buffer->props.direction);
+ hb_buffer_reverse_clusters (buffer);
+ buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
}
}
-static void
-hb_reset_glyph_infos (hb_ot_shape_context_t *c)
-{
- unsigned int count = c->buffer->len;
- for (unsigned int i = 0; i < count; i++)
- c->buffer->info[i].var1.u32 = c->buffer->info[i].var2.u32 = 0;
-}
-
/* Substitute */
static void
hb_mirror_chars (hb_ot_shape_context_t *c)
{
- hb_unicode_get_mirroring_func_t get_mirroring = c->buffer->unicode->v.get_mirroring;
+ hb_unicode_funcs_t *unicode = c->buffer->unicode;
if (HB_DIRECTION_IS_FORWARD (c->target_direction))
return;
@@ -200,7 +184,7 @@ hb_mirror_chars (hb_ot_shape_context_t *c)
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++) {
- hb_codepoint_t codepoint = get_mirroring (c->buffer->info[i].codepoint);
+ hb_codepoint_t codepoint = hb_unicode_mirroring (unicode, c->buffer->info[i].codepoint);
if (likely (codepoint == c->buffer->info[i].codepoint))
c->buffer->info[i].mask |= rtlm_mask; /* XXX this should be moved to before setting user-feature masks */
else
@@ -210,31 +194,54 @@ hb_mirror_chars (hb_ot_shape_context_t *c)
static void
hb_map_glyphs (hb_font_t *font,
- hb_face_t *face,
hb_buffer_t *buffer)
{
+ hb_codepoint_t glyph;
+
if (unlikely (!buffer->len))
return;
buffer->clear_output ();
+
unsigned int count = buffer->len - 1;
- for (buffer->i = 0; buffer->i < count;) {
- if (unlikely (is_variation_selector (buffer->info[buffer->i + 1].codepoint))) {
- buffer->replace_glyph (hb_font_get_glyph (font, face, buffer->info[buffer->i].codepoint, buffer->info[buffer->i + 1].codepoint));
- buffer->i++;
+ for (buffer->idx = 0; buffer->idx < count;) {
+ if (unlikely (is_variation_selector (buffer->info[buffer->idx + 1].codepoint))) {
+ hb_font_get_glyph (font, buffer->info[buffer->idx].codepoint, buffer->info[buffer->idx + 1].codepoint, &glyph);
+ buffer->replace_glyph (glyph);
+ buffer->skip_glyph ();
} else {
- buffer->replace_glyph (hb_font_get_glyph (font, face, buffer->info[buffer->i].codepoint, 0));
+ hb_font_get_glyph (font, buffer->info[buffer->idx].codepoint, 0, &glyph);
+ buffer->replace_glyph (glyph);
}
}
- if (likely (buffer->i < buffer->len))
- buffer->replace_glyph (hb_font_get_glyph (font, face, buffer->info[buffer->i].codepoint, 0));
- buffer->swap ();
+ if (likely (buffer->idx < buffer->len)) {
+ hb_font_get_glyph (font, buffer->info[buffer->idx].codepoint, 0, &glyph);
+ buffer->replace_glyph (glyph);
+ }
+ buffer->swap_buffers ();
}
static void
hb_substitute_default (hb_ot_shape_context_t *c)
{
- hb_map_glyphs (c->font, c->face, c->buffer);
+ hb_ot_layout_substitute_start (c->buffer);
+
+ hb_mirror_chars (c);
+
+ hb_map_glyphs (c->font, c->buffer);
+}
+
+static void
+hb_ot_substitute_complex (hb_ot_shape_context_t *c)
+{
+ if (hb_ot_layout_has_substitution (c->face)) {
+ c->plan->map.substitute (c->face, c->buffer);
+ c->applied_substitute_complex = TRUE;
+ }
+
+ hb_ot_layout_substitute_finish (c->buffer);
+
+ return;
}
static void
@@ -249,14 +256,52 @@ hb_substitute_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED)
static void
hb_position_default (hb_ot_shape_context_t *c)
{
- hb_buffer_clear_positions (c->buffer);
+ hb_ot_layout_position_start (c->buffer);
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++) {
- hb_font_get_glyph_advance (c->font, c->face, c->buffer->info[i].codepoint,
- &c->buffer->pos[i].x_advance,
- &c->buffer->pos[i].y_advance);
+ hb_font_get_glyph_advance_for_direction (c->font, c->buffer->info[i].codepoint,
+ c->buffer->props.direction,
+ &c->buffer->pos[i].x_advance,
+ &c->buffer->pos[i].y_advance);
+ hb_font_subtract_glyph_origin_for_direction (c->font, c->buffer->info[i].codepoint,
+ c->buffer->props.direction,
+ &c->buffer->pos[i].x_offset,
+ &c->buffer->pos[i].y_offset);
+ }
+}
+
+static void
+hb_ot_position_complex (hb_ot_shape_context_t *c)
+{
+
+ if (hb_ot_layout_has_positioning (c->face))
+ {
+ /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */
+
+ unsigned int count = c->buffer->len;
+ for (unsigned int i = 0; i < count; i++) {
+ hb_font_add_glyph_origin_for_direction (c->font, c->buffer->info[i].codepoint,
+ HB_DIRECTION_LTR,
+ &c->buffer->pos[i].x_offset,
+ &c->buffer->pos[i].y_offset);
+ }
+
+ c->plan->map.position (c->font, c->buffer);
+
+ for (unsigned int i = 0; i < count; i++) {
+ hb_font_subtract_glyph_origin_for_direction (c->font, c->buffer->info[i].codepoint,
+ HB_DIRECTION_LTR,
+ &c->buffer->pos[i].x_offset,
+ &c->buffer->pos[i].y_offset);
+ }
+
+ c->applied_position_complex = TRUE;
}
+
+ hb_ot_layout_position_finish (c->buffer);
+
+ return;
}
static void
@@ -271,13 +316,23 @@ hb_truetype_kern (hb_ot_shape_context_t *c)
/* TODO Check for kern=0 */
unsigned int count = c->buffer->len;
for (unsigned int i = 1; i < count; i++) {
- hb_position_t kern, kern1, kern2;
- kern = hb_font_get_kerning (c->font, c->face, c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint);
- kern1 = kern >> 1;
- kern2 = kern - kern1;
+ hb_position_t x_kern, y_kern, kern1, kern2;
+ hb_font_get_glyph_kerning_for_direction (c->font,
+ c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint,
+ c->buffer->props.direction,
+ &x_kern, &y_kern);
+
+ kern1 = x_kern >> 1;
+ kern2 = x_kern - kern1;
c->buffer->pos[i - 1].x_advance += kern1;
c->buffer->pos[i].x_advance += kern2;
c->buffer->pos[i].x_offset += kern2;
+
+ kern1 = y_kern >> 1;
+ kern2 = y_kern - kern1;
+ c->buffer->pos[i - 1].y_advance += kern1;
+ c->buffer->pos[i].y_advance += kern2;
+ c->buffer->pos[i].y_offset += kern2;
}
}
@@ -293,24 +348,26 @@ hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
static void
hb_ot_shape_execute_internal (hb_ot_shape_context_t *c)
{
+ c->buffer->deallocate_var_all ();
+
/* Save the original direction, we use it later. */
c->target_direction = c->buffer->props.direction;
- hb_reset_glyph_infos (c); /* BUFFER: Clear buffer var1 and var2 */
+ HB_BUFFER_ALLOCATE_VAR (c->buffer, general_category);
+ HB_BUFFER_ALLOCATE_VAR (c->buffer, combining_class);
- hb_set_unicode_props (c); /* BUFFER: Set general_category and combining_class in var1 */
+ _hb_set_unicode_props (c->buffer); /* BUFFER: Set general_category and combining_class */
- hb_ensure_native_direction (c);
+ hb_form_clusters (c->buffer);
- hb_form_clusters (c);
+ hb_ensure_native_direction (c->buffer);
- hb_ot_shape_setup_masks (c); /* BUFFER: Clobbers var2 */
+ _hb_ot_shape_normalize (c);
+
+ hb_ot_shape_setup_masks (c);
/* SUBSTITUTE */
{
- /* Mirroring needs to see the original direction */
- hb_mirror_chars (c);
-
hb_substitute_default (c);
hb_ot_substitute_complex (c);
@@ -336,47 +393,56 @@ hb_ot_shape_execute_internal (hb_ot_shape_context_t *c)
hb_position_complex_fallback_visual (c);
}
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, combining_class);
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, general_category);
+
c->buffer->props.direction = c->target_direction;
+
+ c->buffer->deallocate_var_all ();
}
-void
+static void
hb_ot_shape_plan_internal (hb_ot_shape_plan_t *plan,
hb_face_t *face,
const hb_segment_properties_t *props,
const hb_feature_t *user_features,
unsigned int num_user_features)
{
- plan->shaper = hb_ot_shape_complex_categorize (props);
+ hb_ot_shape_planner_t planner;
- hb_ot_shape_collect_features (plan, props, user_features, num_user_features);
+ planner.shaper = hb_ot_shape_complex_categorize (props);
- plan->map.compile (face, props);
+ hb_ot_shape_collect_features (&planner, props, user_features, num_user_features);
+
+ planner.compile (face, props, *plan);
}
-void
+static void
hb_ot_shape_execute (hb_ot_shape_plan_t *plan,
hb_font_t *font,
- hb_face_t *face,
hb_buffer_t *buffer,
const hb_feature_t *user_features,
unsigned int num_user_features)
{
- hb_ot_shape_context_t c = {plan, font, face, buffer, user_features, num_user_features};
+ hb_ot_shape_context_t c = {plan, font, font->face, buffer, user_features, num_user_features};
hb_ot_shape_execute_internal (&c);
}
-void
-hb_ot_shape (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- const hb_feature_t *user_features,
- unsigned int num_user_features)
+hb_bool_t
+hb_ot_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options)
{
hb_ot_shape_plan_t plan;
- hb_ot_shape_plan_internal (&plan, face, &buffer->props, user_features, num_user_features);
- hb_ot_shape_execute (&plan, font, face, buffer, user_features, num_user_features);
+ buffer->guess_properties ();
+
+ hb_ot_shape_plan_internal (&plan, font->face, &buffer->props, features, num_features);
+ hb_ot_shape_execute (&plan, font, buffer, features, num_features);
+
+ return TRUE;
}
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.h b/third_party/harfbuzz-ng/src/hb-ot-shape.h
index c90e0fe..1897e84 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape.h
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright © 2010 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -27,18 +27,19 @@
#ifndef HB_OT_SHAPE_H
#define HB_OT_SHAPE_H
+#include "hb-common.h"
#include "hb-shape.h"
HB_BEGIN_DECLS
-void
+hb_bool_t
hb_ot_shape (hb_font_t *font,
- hb_face_t *face,
hb_buffer_t *buffer,
- const hb_feature_t *user_features,
- unsigned int num_user_features);
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options);
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-ot-tag.c b/third_party/harfbuzz-ng/src/hb-ot-tag.cc
index f3e0f1f..ac60e96 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-tag.c
+++ b/third_party/harfbuzz-ng/src/hb-ot-tag.cc
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -22,157 +23,135 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
-#include "hb-private.h"
+#include "hb-private.hh"
#include "hb-ot.h"
#include <string.h>
-HB_BEGIN_DECLS
+/* hb_script_t */
+
+static hb_tag_t
+hb_ot_old_tag_from_script (hb_script_t script)
+{
+ switch ((hb_tag_t) script) {
+ case HB_SCRIPT_INVALID: return HB_OT_TAG_DEFAULT_SCRIPT;
+
+ /* KATAKANA and HIRAGANA both map to 'kana' */
+ case HB_SCRIPT_HIRAGANA: return HB_TAG('k','a','n','a');
+
+ /* Spaces at the end are preserved, unlike ISO 15924 */
+ case HB_SCRIPT_LAO: return HB_TAG('l','a','o',' ');
+ case HB_SCRIPT_YI: return HB_TAG('y','i',' ',' ');
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_NKO: return HB_TAG('n','k','o',' ');
+ /* Unicode-5.1 additions */
+ case HB_SCRIPT_VAI: return HB_TAG('v','a','i',' ');
+ /* Unicode-5.2 additions */
+ /* Unicode-6.0 additions */
+ }
+
+ /* Else, just change first char to lowercase and return */
+ return ((hb_tag_t) script) | 0x20000000;
+}
+
+static hb_script_t
+hb_ot_old_tag_to_script (hb_tag_t tag)
+{
+ if (unlikely (tag == HB_OT_TAG_DEFAULT_SCRIPT))
+ return HB_SCRIPT_INVALID;
+
+ /* This side of the conversion is fully algorithmic. */
+
+ /* Any spaces at the end of the tag are replaced by repeating the last
+ * letter. Eg 'nko ' -> 'Nkoo' */
+ if (unlikely ((tag & 0x0000FF00) == 0x00002000))
+ tag |= (tag >> 8) & 0x0000FF00; /* Copy second letter to third */
+ if (unlikely ((tag & 0x000000FF) == 0x00000020))
+ tag |= (tag >> 8) & 0x000000FF; /* Copy third letter to fourth */
+
+ /* Change first char to uppercase and return */
+ return (hb_script_t) (tag & ~0x20000000);
+}
+
+static hb_tag_t
+hb_ot_new_tag_from_script (hb_script_t script)
+{
+ switch ((hb_tag_t) script) {
+ case HB_SCRIPT_BENGALI: return HB_TAG('b','n','g','2');
+ case HB_SCRIPT_DEVANAGARI: return HB_TAG('d','e','v','2');
+ case HB_SCRIPT_GUJARATI: return HB_TAG('g','j','r','2');
+ case HB_SCRIPT_GURMUKHI: return HB_TAG('g','u','r','2');
+ case HB_SCRIPT_KANNADA: return HB_TAG('k','n','d','2');
+ case HB_SCRIPT_MALAYALAM: return HB_TAG('m','l','m','2');
+ case HB_SCRIPT_ORIYA: return HB_TAG('o','r','y','2');
+ case HB_SCRIPT_TAMIL: return HB_TAG('t','m','l','2');
+ case HB_SCRIPT_TELUGU: return HB_TAG('t','e','l','2');
+ }
+
+ return HB_OT_TAG_DEFAULT_SCRIPT;
+}
+
+static hb_script_t
+hb_ot_new_tag_to_script (hb_tag_t tag)
+{
+ switch (tag) {
+ case HB_TAG('b','n','g','2'): return HB_SCRIPT_BENGALI;
+ case HB_TAG('d','e','v','2'): return HB_SCRIPT_DEVANAGARI;
+ case HB_TAG('g','j','r','2'): return HB_SCRIPT_GUJARATI;
+ case HB_TAG('g','u','r','2'): return HB_SCRIPT_GURMUKHI;
+ case HB_TAG('k','n','d','2'): return HB_SCRIPT_KANNADA;
+ case HB_TAG('m','l','m','2'): return HB_SCRIPT_MALAYALAM;
+ case HB_TAG('o','r','y','2'): return HB_SCRIPT_ORIYA;
+ case HB_TAG('t','m','l','2'): return HB_SCRIPT_TAMIL;
+ case HB_TAG('t','e','l','2'): return HB_SCRIPT_TELUGU;
+ }
+
+ return HB_SCRIPT_UNKNOWN;
+}
+
/*
* Complete list at:
- * http://www.microsoft.com/typography/otspec/scripttags.htm
+ * https://www.microsoft.com/typography/otspec/scripttags.htm
+ * https://www.microsoft.com/typography/otspec160/scripttagsProposed.htm
+ *
+ * Most of the script tags are the same as the ISO 15924 tag but lowercased.
+ * So we just do that, and handle the exceptional cases in a switch.
*/
-static const hb_tag_t ot_scripts[][3] = {
- {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_COMMON */
- {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_INHERITED */
- {HB_TAG('a','r','a','b')}, /* HB_SCRIPT_ARABIC */
- {HB_TAG('a','r','m','n')}, /* HB_SCRIPT_ARMENIAN */
- {HB_TAG('b','n','g','2'), HB_TAG('b','e','n','g')}, /* HB_SCRIPT_BENGALI */
- {HB_TAG('b','o','p','o')}, /* HB_SCRIPT_BOPOMOFO */
- {HB_TAG('c','h','e','r')}, /* HB_SCRIPT_CHEROKEE */
- {HB_TAG('c','o','p','t')}, /* HB_SCRIPT_COPTIC */
- {HB_TAG('c','y','r','l')}, /* HB_SCRIPT_CYRILLIC */
- {HB_TAG('d','s','r','t')}, /* HB_SCRIPT_DESERET */
- {HB_TAG('d','e','v','2'), HB_TAG('d','e','v','a')}, /* HB_SCRIPT_DEVANAGARI */
- {HB_TAG('e','t','h','i')}, /* HB_SCRIPT_ETHIOPIC */
- {HB_TAG('g','e','o','r')}, /* HB_SCRIPT_GEORGIAN */
- {HB_TAG('g','o','t','h')}, /* HB_SCRIPT_GOTHIC */
- {HB_TAG('g','r','e','k')}, /* HB_SCRIPT_GREEK */
- {HB_TAG('g','j','r','2'), HB_TAG('g','u','j','r')}, /* HB_SCRIPT_GUJARATI */
- {HB_TAG('g','u','r','2'), HB_TAG('g','u','r','u')}, /* HB_SCRIPT_GURMUKHI */
- {HB_TAG('h','a','n','i')}, /* HB_SCRIPT_HAN */
- {HB_TAG('h','a','n','g')}, /* HB_SCRIPT_HANGUL */
- {HB_TAG('h','e','b','r')}, /* HB_SCRIPT_HEBREW */
- {HB_TAG('k','a','n','a')}, /* HB_SCRIPT_HIRAGANA */
- {HB_TAG('k','n','d','2'), HB_TAG('k','n','d','a')}, /* HB_SCRIPT_KANNADA */
- {HB_TAG('k','a','n','a')}, /* HB_SCRIPT_KATAKANA */
- {HB_TAG('k','h','m','r')}, /* HB_SCRIPT_KHMER */
- {HB_TAG('l','a','o',' ')}, /* HB_SCRIPT_LAO */
- {HB_TAG('l','a','t','n')}, /* HB_SCRIPT_LATIN */
- {HB_TAG('m','l','m','2'), HB_TAG('m','l','y','m')}, /* HB_SCRIPT_MALAYALAM */
- {HB_TAG('m','o','n','g')}, /* HB_SCRIPT_MONGOLIAN */
- {HB_TAG('m','y','m','r')}, /* HB_SCRIPT_MYANMAR */
- {HB_TAG('o','g','a','m')}, /* HB_SCRIPT_OGHAM */
- {HB_TAG('i','t','a','l')}, /* HB_SCRIPT_OLD_ITALIC */
- {HB_TAG('o','r','y','2'), HB_TAG('o','r','y','a')}, /* HB_SCRIPT_ORIYA */
- {HB_TAG('r','u','n','r')}, /* HB_SCRIPT_RUNIC */
- {HB_TAG('s','i','n','h')}, /* HB_SCRIPT_SINHALA */
- {HB_TAG('s','y','r','c')}, /* HB_SCRIPT_SYRIAC */
- {HB_TAG('t','m','l','2'), HB_TAG('t','a','m','l')}, /* HB_SCRIPT_TAMIL */
- {HB_TAG('t','e','l','2'), HB_TAG('t','e','l','u')}, /* HB_SCRIPT_TELUGU */
- {HB_TAG('t','h','a','a')}, /* HB_SCRIPT_THAANA */
- {HB_TAG('t','h','a','i')}, /* HB_SCRIPT_THAI */
- {HB_TAG('t','i','b','t')}, /* HB_SCRIPT_TIBETAN */
- {HB_TAG('c','a','n','s')}, /* HB_SCRIPT_CANADIAN_ABORIGINAL */
- {HB_TAG('y','i',' ',' ')}, /* HB_SCRIPT_YI */
- {HB_TAG('t','g','l','g')}, /* HB_SCRIPT_TAGALOG */
- {HB_TAG('h','a','n','o')}, /* HB_SCRIPT_HANUNOO */
- {HB_TAG('b','u','h','d')}, /* HB_SCRIPT_BUHID */
- {HB_TAG('t','a','g','b')}, /* HB_SCRIPT_TAGBANWA */
-
- /* Unicode-4.0 additions */
- {HB_TAG('b','r','a','i')}, /* HB_SCRIPT_BRAILLE */
- {HB_TAG('c','p','r','t')}, /* HB_SCRIPT_CYPRIOT */
- {HB_TAG('l','i','m','b')}, /* HB_SCRIPT_LIMBU */
- {HB_TAG('o','s','m','a')}, /* HB_SCRIPT_OSMANYA */
- {HB_TAG('s','h','a','w')}, /* HB_SCRIPT_SHAVIAN */
- {HB_TAG('l','i','n','b')}, /* HB_SCRIPT_LINEAR_B */
- {HB_TAG('t','a','l','e')}, /* HB_SCRIPT_TAI_LE */
- {HB_TAG('u','g','a','r')}, /* HB_SCRIPT_UGARITIC */
-
- /* Unicode-4.1 additions */
- {HB_TAG('t','a','l','u')}, /* HB_SCRIPT_NEW_TAI_LUE */
- {HB_TAG('b','u','g','i')}, /* HB_SCRIPT_BUGINESE */
- {HB_TAG('g','l','a','g')}, /* HB_SCRIPT_GLAGOLITIC */
- {HB_TAG('t','f','n','g')}, /* HB_SCRIPT_TIFINAGH */
- {HB_TAG('s','y','l','o')}, /* HB_SCRIPT_SYLOTI_NAGRI */
- {HB_TAG('x','p','e','o')}, /* HB_SCRIPT_OLD_PERSIAN */
- {HB_TAG('k','h','a','r')}, /* HB_SCRIPT_KHAROSHTHI */
-
- /* Unicode-5.0 additions */
- {HB_TAG('D','F','L','T')}, /* HB_SCRIPT_UNKNOWN */
- {HB_TAG('b','a','l','i')}, /* HB_SCRIPT_BALINESE */
- {HB_TAG('x','s','u','x')}, /* HB_SCRIPT_CUNEIFORM */
- {HB_TAG('p','h','n','x')}, /* HB_SCRIPT_PHOENICIAN */
- {HB_TAG('p','h','a','g')}, /* HB_SCRIPT_PHAGS_PA */
- {HB_TAG('n','k','o',' ')}, /* HB_SCRIPT_NKO */
-
- /* Unicode-5.1 additions */
- {HB_TAG('k','a','l','i')}, /* HB_SCRIPT_KAYAH_LI */
- {HB_TAG('l','e','p','c')}, /* HB_SCRIPT_LEPCHA */
- {HB_TAG('r','j','n','g')}, /* HB_SCRIPT_REJANG */
- {HB_TAG('s','u','n','d')}, /* HB_SCRIPT_SUNDANESE */
- {HB_TAG('s','a','u','r')}, /* HB_SCRIPT_SAURASHTRA */
- {HB_TAG('c','h','a','m')}, /* HB_SCRIPT_CHAM */
- {HB_TAG('o','l','c','k')}, /* HB_SCRIPT_OL_CHIKI */
- {HB_TAG('v','a','i',' ')}, /* HB_SCRIPT_VAI */
- {HB_TAG('c','a','r','i')}, /* HB_SCRIPT_CARIAN */
- {HB_TAG('l','y','c','i')}, /* HB_SCRIPT_LYCIAN */
- {HB_TAG('l','y','d','i')}, /* HB_SCRIPT_LYDIAN */
-
- /* Unicode-5.2 additions */
- {HB_TAG('a','v','s','t')}, /* HB_SCRIPT_AVESTAN */
- {HB_TAG('b','a','m','u')}, /* HB_SCRIPT_BAMUM */
- {HB_TAG('e','g','y','p')}, /* HB_SCRIPT_EGYPTIAN_HIEROGLYPHS */
- {HB_TAG('a','r','m','i')}, /* HB_SCRIPT_IMPERIAL_ARAMAIC */
- {HB_TAG('p','h','l','i')}, /* HB_SCRIPT_INSCRIPTIONAL_PAHLAVI */
- {HB_TAG('p','r','t','i')}, /* HB_SCRIPT_INSCRIPTIONAL_PARTHIAN */
- {HB_TAG('j','a','v','a')}, /* HB_SCRIPT_JAVANESE */
- {HB_TAG('k','t','h','i')}, /* HB_SCRIPT_KAITHI */
- {HB_TAG('l','i','s','u')}, /* HB_SCRIPT_LISU */
- {HB_TAG('m','y','e','i')}, /* HB_SCRIPT_MEETEI_MAYEK */
- {HB_TAG('s','a','r','b')}, /* HB_SCRIPT_OLD_SOUTH_ARABIAN */
- {HB_TAG('o','r','k','h')}, /* HB_SCRIPT_OLD_TURKIC */
- {HB_TAG('s','a','m','r')}, /* HB_SCRIPT_SAMARITAN */
- {HB_TAG('l','a','n','a')}, /* HB_SCRIPT_TAI_THAM */
- {HB_TAG('t','a','v','t')}, /* HB_SCRIPT_TAI_VIET */
-
- /* Unicode-6.0 additions */
- {HB_TAG('b','a','t','k')}, /* HB_SCRIPT_BATAK */
- {HB_TAG('b','r','a','h')}, /* HB_SCRIPT_BRAHMI */
- {HB_TAG('m','a','n','d')} /* HB_SCRIPT_MANDAIC */
-};
-const hb_tag_t *
-hb_ot_tags_from_script (hb_script_t script)
+void
+hb_ot_tags_from_script (hb_script_t script,
+ hb_tag_t *script_tag_1,
+ hb_tag_t *script_tag_2)
{
- static const hb_tag_t def_tag[] = {HB_OT_TAG_DEFAULT_SCRIPT, HB_TAG_NONE};
+ hb_tag_t new_tag;
- if (unlikely ((unsigned int) script >= ARRAY_LENGTH (ot_scripts)))
- return def_tag;
+ *script_tag_2 = HB_OT_TAG_DEFAULT_SCRIPT;
+ *script_tag_1 = hb_ot_old_tag_from_script (script);
- return ot_scripts[script];
+ new_tag = hb_ot_new_tag_from_script (script);
+ if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT)) {
+ *script_tag_2 = *script_tag_1;
+ *script_tag_1 = new_tag;
+ }
}
hb_script_t
hb_ot_tag_to_script (hb_tag_t tag)
{
- int i;
+ if (unlikely ((tag & 0x000000FF) == '2'))
+ return hb_ot_new_tag_to_script (tag);
- for (i = 0; i < ARRAY_LENGTH (ot_scripts); i++) {
- const hb_tag_t *p;
- for (p = ot_scripts[i]; *p; p++)
- if (tag == *p)
- return i;
- }
-
- return HB_SCRIPT_UNKNOWN;
+ return hb_ot_old_tag_to_script (tag);
}
+
+/* hb_language_t */
+
typedef struct {
char language[6];
hb_tag_t tag;
@@ -189,6 +168,7 @@ typedef struct {
* Many items still missing. Those are commented out at the end.
* Keep sorted for bsearch.
*/
+
static const LangTag ot_languages[] = {
{"aa", HB_TAG('A','F','R',' ')}, /* Afar */
{"ab", HB_TAG('A','B','K',' ')}, /* Abkhazian */
@@ -475,11 +455,6 @@ static const LangTag ot_languages[] = {
{"yi", HB_TAG('J','I','I',' ')}, /* Yiddish */
{"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */
{"yso", HB_TAG('N','I','S',' ')}, /* Nisi (China) */
- {"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */
- {"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */
- {"zh-mo", HB_TAG('Z','H','T',' ')}, /* Chinese (Macao) */
- {"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */
- {"zh-tw", HB_TAG('Z','H','T',' ')}, /* Chinese (Taiwan) */
{"zne", HB_TAG('Z','N','D',' ')}, /* Zande */
{"zu", HB_TAG('Z','U','L',' ')} /* Zulu */
@@ -595,6 +570,14 @@ static const LangTag ot_languages[] = {
/*{"??", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */
};
+static const LangTag ot_languages_zh[] = {
+ {"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */
+ {"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */
+ {"zh-mo", HB_TAG('Z','H','T',' ')}, /* Chinese (Macao) */
+ {"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */
+ {"zh-tw", HB_TAG('Z','H','T',' ')} /* Chinese (Taiwan) */
+};
+
static int
lang_compare_first_component (const char *a,
const char *b)
@@ -602,10 +585,10 @@ lang_compare_first_component (const char *a,
unsigned int da, db;
const char *p;
- p = strstr (a, "-");
+ p = strchr (a, '-');
da = p ? (unsigned int) (p - a) : strlen (a);
- p = strstr (b, "-");
+ p = strchr (b, '-');
db = p ? (unsigned int) (p - b) : strlen (b);
return strncmp (a, b, MAX (da, db));
@@ -616,67 +599,65 @@ lang_matches (const char *lang_str, const char *spec)
{
unsigned int len = strlen (spec);
- return lang_str && strncmp (lang_str, spec, len) == 0 &&
+ return strncmp (lang_str, spec, len) == 0 &&
(lang_str[len] == '\0' || lang_str[len] == '-');
}
hb_tag_t
hb_ot_tag_from_language (hb_language_t language)
{
- const char *lang_str;
- LangTag *lang_tag;
+ const char *lang_str, *s;
+ const LangTag *lang_tag;
- if (language == NULL)
+ if (language == HB_LANGUAGE_INVALID)
return HB_OT_TAG_DEFAULT_LANGUAGE;
lang_str = hb_language_to_string (language);
- if (0 == strcmp (lang_str, "x-hbot")) {
+ s = strstr (lang_str, "x-hbot");
+ if (s) {
char tag[4];
int i;
- lang_str += 6;
-#define IS_LETTER(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
-#define TO_UPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) + 'A' - 'a' : (c))
- for (i = 0; i < 4 && IS_LETTER (lang_str[i]); i++)
- tag[i] = TO_UPPER (lang_str[i]);
- for (; i < 4; i++)
- tag[i] = ' ';
- return HB_TAG_STR (tag);
+ s += 6;
+ for (i = 0; i < 4 && ISALPHA (s[i]); i++)
+ tag[i] = TOUPPER (s[i]);
+ if (i) {
+ for (; i < 4; i++)
+ tag[i] = ' ';
+ return HB_TAG_CHAR4 (tag);
+ }
}
- /* find a language matching in the first component */
- lang_tag = bsearch (lang_str, ot_languages,
- ARRAY_LENGTH (ot_languages), sizeof (LangTag),
- (hb_compare_func_t) lang_compare_first_component);
-
- /* we now need to find the best language matching */
+ /* Find a language matching in the first component */
+ lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
+ ARRAY_LENGTH (ot_languages), sizeof (LangTag),
+ (hb_compare_func_t) lang_compare_first_component);
if (lang_tag)
- {
- hb_bool_t found = FALSE;
+ return lang_tag->tag;
- /* go to the final one matching in the first component */
- while (lang_tag + 1 < ot_languages + ARRAY_LENGTH (ot_languages) &&
- lang_compare_first_component (lang_str, (lang_tag + 1)->language) == 0)
- lang_tag++;
+ /* Otherwise, check the Chinese ones */
+ if (0 == lang_compare_first_component (lang_str, "zh"))
+ {
+ unsigned int i;
- /* go back, find which one matches completely */
- while (lang_tag >= ot_languages &&
- lang_compare_first_component (lang_str, lang_tag->language) == 0)
+ for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++)
{
- if (lang_matches (lang_str, lang_tag->language)) {
- found = TRUE;
- break;
- }
-
- lang_tag--;
+ lang_tag = &ot_languages_zh[i];
+ if (lang_matches (lang_tag->language, lang_str))
+ return lang_tag->tag;
}
- if (!found)
- lang_tag = NULL;
+ /* Otherwise just return 'ZHS ' */
+ return HB_TAG('Z','H','S',' ');
}
- if (lang_tag)
- return lang_tag->tag;
+ s = strchr (lang_str, '-');
+ if (!s)
+ s = lang_str + strlen (lang_str);
+ if (s - lang_str == 3) {
+ /* Assume it's ISO-639-3 and upper-case and use it. */
+ return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000;
+ }
return HB_OT_TAG_DEFAULT_LANGUAGE;
}
@@ -685,19 +666,45 @@ hb_language_t
hb_ot_tag_to_language (hb_tag_t tag)
{
unsigned int i;
- unsigned char buf[11] = "x-hbot";
+
+ if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
+ return NULL;
for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
if (ot_languages[i].tag == tag)
- return hb_language_from_string (ot_languages[i].language);
-
- buf[6] = tag >> 24;
- buf[7] = (tag >> 16) & 0xFF;
- buf[8] = (tag >> 8) & 0xFF;
- buf[9] = tag & 0xFF;
- buf[10] = '\0';
- return hb_language_from_string ((char *) buf);
+ return hb_language_from_string (ot_languages[i].language, -1);
+
+ /* If tag starts with ZH, it's Chinese */
+ if ((tag & 0xFFFF0000) == 0x5A480000) {
+ switch (tag) {
+ case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */
+ default: {
+ /* Encode the tag... */
+ unsigned char buf[14] = "zh-x-hbot";
+ buf[9] = tag >> 24;
+ buf[10] = (tag >> 16) & 0xFF;
+ buf[11] = (tag >> 8) & 0xFF;
+ buf[12] = tag & 0xFF;
+ if (buf[12] == 0x20)
+ buf[12] = '\0';
+ buf[13] = '\0';
+ return hb_language_from_string ((char *) buf, -1);
+ }
+ }
+ }
+
+ /* Else return a custom language in the form of "x-hbotABCD" */
+ {
+ unsigned char buf[11] = "x-hbot";
+ buf[6] = tag >> 24;
+ buf[7] = (tag >> 16) & 0xFF;
+ buf[8] = (tag >> 8) & 0xFF;
+ buf[9] = tag & 0xFF;
+ if (buf[9] == 0x20)
+ buf[9] = '\0';
+ buf[10] = '\0';
+ return hb_language_from_string ((char *) buf, -1);
+ }
}
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-ot-tag.h b/third_party/harfbuzz-ng/src/hb-ot-tag.h
index 1eec69f..427a069 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-tag.h
+++ b/third_party/harfbuzz-ng/src/hb-ot-tag.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -28,7 +28,6 @@
#define HB_OT_TAG_H
#include "hb-common.h"
-#include "hb-language.h"
HB_BEGIN_DECLS
@@ -36,8 +35,10 @@ HB_BEGIN_DECLS
#define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T')
#define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't')
-const hb_tag_t *
-hb_ot_tags_from_script (hb_script_t script);
+void
+hb_ot_tags_from_script (hb_script_t script,
+ hb_tag_t *script_tag_1,
+ hb_tag_t *script_tag_2);
hb_script_t
hb_ot_tag_to_script (hb_tag_t tag);
diff --git a/third_party/harfbuzz-ng/src/hb-ot.h b/third_party/harfbuzz-ng/src/hb-ot.h
index 268711d..fd6dd58 100644
--- a/third_party/harfbuzz-ng/src/hb-ot.h
+++ b/third_party/harfbuzz-ng/src/hb-ot.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
diff --git a/third_party/harfbuzz-ng/src/hb-private.h b/third_party/harfbuzz-ng/src/hb-private.h
deleted file mode 100644
index 96b9464..0000000
--- a/third_party/harfbuzz-ng/src/hb-private.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2007,2008,2009 Red Hat, 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_PRIVATE_H
-#define HB_PRIVATE_H
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "hb-common.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-/* We only use these two for debug output. However, the debug code is
- * always seen by the compiler (and optimized out in non-debug builds.
- * If including these becomes a problem, we can start thinking about
- * someway around that. */
-#include <stdio.h>
-#include <errno.h>
-
-HB_BEGIN_DECLS
-
-
-/* Essentials */
-
-#ifndef NULL
-# define NULL ((void *) 0)
-#endif
-
-#undef FALSE
-#define FALSE 0
-
-#undef TRUE
-#define TRUE 1
-
-
-/* Basics */
-
-#undef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-#undef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
-#undef ARRAY_LENGTH
-#define ARRAY_LENGTH(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
-
-#define HB_STMT_START do
-#define HB_STMT_END while (0)
-
-#define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
-#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond))
-#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
-
-
-/* Misc */
-
-
-#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
-#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
-#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
-#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
-#else
-#define likely(expr) (expr)
-#define unlikely(expr) (expr)
-#endif
-
-#ifndef __GNUC__
-#undef __attribute__
-#define __attribute__(x)
-#endif
-
-#if __GNUC__ >= 3
-#define HB_PURE_FUNC __attribute__((pure))
-#define HB_CONST_FUNC __attribute__((const))
-#else
-#define HB_PURE_FUNC
-#define HB_CONST_FUNC
-#endif
-#if __GNUC__ >= 4
-#define HB_UNUSED __attribute__((unused))
-#else
-#define HB_UNUSED
-#endif
-
-#ifndef HB_INTERNAL
-# define HB_INTERNAL __attribute__((__visibility__("hidden")))
-#endif
-
-
-#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
-#define snprintf _snprintf
-#endif
-
-#ifdef _MSC_VER
-#undef inline
-#define inline __inline
-#endif
-
-#ifdef __STRICT_ANSI__
-#undef inline
-#define inline __inline__
-#endif
-
-
-#if __GNUC__ >= 3
-#define HB_FUNC __PRETTY_FUNCTION__
-#elif defined(_MSC_VER)
-#define HB_FUNC __FUNCSIG__
-#else
-#define HB_FUNC __func__
-#endif
-
-
-/* Return the number of 1 bits in mask. */
-static inline HB_CONST_FUNC unsigned int
-_hb_popcount32 (uint32_t mask)
-{
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
- return __builtin_popcount (mask);
-#else
- /* "HACKMEM 169" */
- register uint32_t y;
- y = (mask >> 1) &033333333333;
- y = mask - y - ((y >>1) & 033333333333);
- return (((y + (y >> 3)) & 030707070707) % 077);
-#endif
-}
-
-/* Returns the number of bits needed to store number */
-static inline HB_CONST_FUNC unsigned int
-_hb_bit_storage (unsigned int number)
-{
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
- return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
-#else
- register unsigned int n_bits = 0;
- while (number) {
- n_bits++;
- number >>= 1;
- }
- return n_bits;
-#endif
-}
-
-/* Returns the number of zero bits in the least significant side of number */
-static inline HB_CONST_FUNC unsigned int
-_hb_ctz (unsigned int number)
-{
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
- return likely (number) ? __builtin_ctz (number) : 0;
-#else
- register unsigned int n_bits = 0;
- if (unlikely (!number)) return 0;
- while (!(number & 1)) {
- n_bits++;
- number >>= 1;
- }
- return n_bits;
-#endif
-}
-
-/* Type of bsearch() / qsort() compare function */
-typedef int (*hb_compare_func_t) (const void *, const void *);
-
-
-/* We need external help for these */
-
-#ifdef HAVE_GLIB
-
-#include <glib.h>
-
-typedef int hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V) g_atomic_int_exchange_and_add (&(AI), V)
-#define hb_atomic_int_get(AI) g_atomic_int_get (&(AI))
-#define hb_atomic_int_set(AI, V) g_atomic_int_set (&(AI), V)
-
-typedef GStaticMutex hb_mutex_t;
-#define HB_MUTEX_INIT G_STATIC_MUTEX_INIT
-#define hb_mutex_init(M) g_static_mutex_init (&M)
-#define hb_mutex_lock(M) g_static_mutex_lock (&M)
-#define hb_mutex_trylock(M) g_static_mutex_trylock (&M)
-#define hb_mutex_unlock(M) g_static_mutex_unlock (&M)
-
-#else
-
-#ifdef _MSC_VER
-#pragma message(__LOC__"Could not find any system to define platform macros, library will NOT be thread-safe")
-#else
-#warning "Could not find any system to define platform macros, library will NOT be thread-safe"
-#endif
-
-typedef int hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V) ((AI) += (V), (AI) - (V))
-#define hb_atomic_int_get(AI) (AI)
-#define hb_atomic_int_set(AI, V) HB_STMT_START { (AI) = (V); } HB_STMT_END
-
-typedef int hb_mutex_t;
-#define HB_MUTEX_INIT 0
-#define hb_mutex_init(M) HB_STMT_START { (M) = 0; } HB_STMT_END
-#define hb_mutex_lock(M) HB_STMT_START { (M) = 1; } HB_STMT_END
-#define hb_mutex_trylock(M) ((M) = 1, 1)
-#define hb_mutex_unlock(M) HB_STMT_START { (M) = 0; } HB_STMT_END
-
-#endif
-
-
-/* Big-endian handling */
-
-#define hb_be_uint16(v) ((uint16_t) ((((const uint8_t *)&(v))[0] << 8) + (((const uint8_t *)&(v))[1])))
-
-#define hb_be_uint16_put(v,V) HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END
-#define hb_be_uint16_get(v) (uint16_t) ((v[0] << 8) + v[1])
-#define hb_be_uint16_cmp(a,b) (a[0] == b[0] && a[1] == b[1])
-
-#define hb_be_uint32_put(v,V) HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16); v[2] = (V>>8); v[3] = (V); } HB_STMT_END
-#define hb_be_uint32_get(v) (uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
-#define hb_be_uint32_cmp(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
-
-
-/* Debug */
-
-#ifndef HB_DEBUG
-#define HB_DEBUG 0
-#endif
-
-static inline hb_bool_t /* always returns TRUE */
-_hb_trace (const char *what,
- const char *function,
- const void *obj,
- unsigned int depth,
- unsigned int max_depth)
-{
- (void) ((depth < max_depth) && fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, depth, depth, function));
- return TRUE;
-}
-
-
-#include "hb-object-private.h"
-
-
-HB_END_DECLS
-
-#endif /* HB_PRIVATE_H */
diff --git a/third_party/harfbuzz-ng/src/hb-private.hh b/third_party/harfbuzz-ng/src/hb-private.hh
new file mode 100644
index 0000000..c757e2dc
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-private.hh
@@ -0,0 +1,632 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2011 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_PRIVATE_HH
+#define HB_PRIVATE_HH
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "hb-common.h"
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+
+/* We only use these two for debug output. However, the debug code is
+ * always seen by the compiler (and optimized out in non-debug builds.
+ * If including these becomes a problem, we can start thinking about
+ * someway around that. */
+#include <stdio.h>
+#include <errno.h>
+#include <stdarg.h>
+
+
+
+/* Essentials */
+
+#ifndef NULL
+# define NULL ((void *) 0)
+#endif
+
+#undef FALSE
+#define FALSE 0
+
+#undef TRUE
+#define TRUE 1
+
+
+/* Basics */
+
+
+#undef MIN
+template <typename Type> static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
+
+#undef MAX
+template <typename Type> static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
+
+
+#undef ARRAY_LENGTH
+#define ARRAY_LENGTH(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
+
+#define HB_STMT_START do
+#define HB_STMT_END while (0)
+
+#define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
+#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond))
+#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
+
+#define ASSERT_STATIC_EXPR(_cond) ((void) sizeof (char[(_cond) ? 1 : -1]))
+#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1]))
+
+
+/* Lets assert int types. Saves trouble down the road. */
+
+ASSERT_STATIC (sizeof (int8_t) == 1);
+ASSERT_STATIC (sizeof (uint8_t) == 1);
+ASSERT_STATIC (sizeof (int16_t) == 2);
+ASSERT_STATIC (sizeof (uint16_t) == 2);
+ASSERT_STATIC (sizeof (int32_t) == 4);
+ASSERT_STATIC (sizeof (uint32_t) == 4);
+ASSERT_STATIC (sizeof (int64_t) == 8);
+ASSERT_STATIC (sizeof (uint64_t) == 8);
+
+ASSERT_STATIC (sizeof (hb_codepoint_t) == 4);
+ASSERT_STATIC (sizeof (hb_position_t) == 4);
+ASSERT_STATIC (sizeof (hb_mask_t) == 4);
+ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
+
+/* Misc */
+
+
+#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
+#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
+#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
+#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
+#else
+#define likely(expr) (expr)
+#define unlikely(expr) (expr)
+#endif
+
+#ifndef __GNUC__
+#undef __attribute__
+#define __attribute__(x)
+#endif
+
+#if __GNUC__ >= 3
+#define HB_PURE_FUNC __attribute__((pure))
+#define HB_CONST_FUNC __attribute__((const))
+#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#else
+#define HB_PURE_FUNC
+#define HB_CONST_FUNC
+#define HB_PRINTF_FUNC(format_idx, arg_idx)
+#endif
+#if __GNUC__ >= 4
+#define HB_UNUSED __attribute__((unused))
+#else
+#define HB_UNUSED
+#endif
+
+#ifndef HB_INTERNAL
+# ifndef __MINGW32__
+# define HB_INTERNAL __attribute__((__visibility__("hidden")))
+# else
+# define HB_INTERNAL
+# endif
+#endif
+
+
+#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
+#define snprintf _snprintf
+#endif
+
+#ifdef _MSC_VER
+#undef inline
+#define inline __inline
+#endif
+
+#ifdef __STRICT_ANSI__
+#undef inline
+#define inline __inline__
+#endif
+
+
+#if __GNUC__ >= 3
+#define HB_FUNC __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+#define HB_FUNC __FUNCSIG__
+#else
+#define HB_FUNC __func__
+#endif
+
+
+/* Return the number of 1 bits in mask. */
+static inline HB_CONST_FUNC unsigned int
+_hb_popcount32 (uint32_t mask)
+{
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+ return __builtin_popcount (mask);
+#else
+ /* "HACKMEM 169" */
+ register uint32_t y;
+ y = (mask >> 1) &033333333333;
+ y = mask - y - ((y >>1) & 033333333333);
+ return (((y + (y >> 3)) & 030707070707) % 077);
+#endif
+}
+
+/* Returns the number of bits needed to store number */
+static inline HB_CONST_FUNC unsigned int
+_hb_bit_storage (unsigned int number)
+{
+#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
+ return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
+#else
+ register unsigned int n_bits = 0;
+ while (number) {
+ n_bits++;
+ number >>= 1;
+ }
+ return n_bits;
+#endif
+}
+
+/* Returns the number of zero bits in the least significant side of number */
+static inline HB_CONST_FUNC unsigned int
+_hb_ctz (unsigned int number)
+{
+#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
+ return likely (number) ? __builtin_ctz (number) : 0;
+#else
+ register unsigned int n_bits = 0;
+ if (unlikely (!number)) return 0;
+ while (!(number & 1)) {
+ n_bits++;
+ number >>= 1;
+ }
+ return n_bits;
+#endif
+}
+
+static inline bool
+_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
+{
+ return (size > 0) && (count >= ((unsigned int) -1) / size);
+}
+
+
+/* Type of bsearch() / qsort() compare function */
+typedef int (*hb_compare_func_t) (const void *, const void *);
+
+
+
+
+/* arrays and maps */
+
+
+template <typename Type, unsigned int StaticSize>
+struct hb_prealloced_array_t {
+
+ unsigned int len;
+ unsigned int allocated;
+ Type *array;
+ Type static_array[StaticSize];
+
+ hb_prealloced_array_t (void) { memset (this, 0, sizeof (*this)); }
+
+ inline Type& operator [] (unsigned int i) { return array[i]; }
+ inline const Type& operator [] (unsigned int i) const { return array[i]; }
+
+ inline Type *push (void)
+ {
+ if (!array) {
+ array = static_array;
+ allocated = ARRAY_LENGTH (static_array);
+ }
+ if (likely (len < allocated))
+ return &array[len++];
+
+ /* Need to reallocate */
+ unsigned int new_allocated = allocated + (allocated >> 1) + 8;
+ Type *new_array = NULL;
+
+ if (array == static_array) {
+ new_array = (Type *) calloc (new_allocated, sizeof (Type));
+ if (new_array)
+ memcpy (new_array, array, len * sizeof (Type));
+ } else {
+ bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
+ if (likely (!overflows)) {
+ new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
+ }
+ }
+
+ if (unlikely (!new_array))
+ return NULL;
+
+ array = new_array;
+ allocated = new_allocated;
+ return &array[len++];
+ }
+
+ inline void pop (void)
+ {
+ len--;
+ /* TODO: shrink array if needed */
+ }
+
+ inline void shrink (unsigned int l)
+ {
+ if (l < len)
+ len = l;
+ /* TODO: shrink array if needed */
+ }
+
+ template <typename T>
+ inline Type *find (T v) {
+ for (unsigned int i = 0; i < len; i++)
+ if (array[i] == v)
+ return &array[i];
+ return NULL;
+ }
+ template <typename T>
+ inline const Type *find (T v) const {
+ for (unsigned int i = 0; i < len; i++)
+ if (array[i] == v)
+ return &array[i];
+ return NULL;
+ }
+
+ inline void sort (void)
+ {
+ qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+ }
+
+ inline void sort (unsigned int start, unsigned int end)
+ {
+ qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
+ }
+
+ template <typename T>
+ inline Type *bsearch (T *key)
+ {
+ return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+ }
+ template <typename T>
+ inline const Type *bsearch (T *key) const
+ {
+ return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
+ }
+
+ inline void finish (void)
+ {
+ if (array != static_array)
+ free (array);
+ array = NULL;
+ allocated = len = 0;
+ }
+};
+
+template <typename Type>
+struct hb_array_t : hb_prealloced_array_t<Type, 2> {};
+
+
+template <typename item_t, typename lock_t>
+struct hb_lockable_set_t
+{
+ hb_array_t <item_t> items;
+
+ template <typename T>
+ inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
+ {
+ l.lock ();
+ item_t *item = items.find (v);
+ if (item) {
+ if (replace) {
+ item_t old = *item;
+ *item = v;
+ l.unlock ();
+ old.finish ();
+ }
+ else {
+ item = NULL;
+ l.unlock ();
+ }
+ } else {
+ item = items.push ();
+ if (likely (item))
+ *item = v;
+ l.unlock ();
+ }
+ return item;
+ }
+
+ template <typename T>
+ inline void remove (T v, lock_t &l)
+ {
+ l.lock ();
+ item_t *item = items.find (v);
+ if (item) {
+ item_t old = *item;
+ *item = items[items.len - 1];
+ items.pop ();
+ l.unlock ();
+ old.finish ();
+ } else {
+ l.unlock ();
+ }
+ }
+
+ template <typename T>
+ inline bool find (T v, item_t *i, lock_t &l)
+ {
+ l.lock ();
+ item_t *item = items.find (v);
+ if (item)
+ *i = *item;
+ l.unlock ();
+ return !!item;
+ }
+
+ template <typename T>
+ inline item_t *find_or_insert (T v, lock_t &l)
+ {
+ l.lock ();
+ item_t *item = items.find (v);
+ if (!item) {
+ item = items.push ();
+ if (likely (item))
+ *item = v;
+ }
+ l.unlock ();
+ return item;
+ }
+
+ inline void finish (lock_t &l)
+ {
+ l.lock ();
+ while (items.len) {
+ item_t old = items[items.len - 1];
+ items.pop ();
+ l.unlock ();
+ old.finish ();
+ l.lock ();
+ }
+ items.finish ();
+ l.unlock ();
+ }
+
+};
+
+
+
+
+/* Big-endian handling */
+
+static inline uint16_t hb_be_uint16 (const uint16_t v)
+{
+ const uint8_t *V = (const uint8_t *) &v;
+ return (uint16_t) (V[0] << 8) + V[1];
+}
+
+#define hb_be_uint16_put(v,V) HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END
+#define hb_be_uint16_get(v) (uint16_t) ((v[0] << 8) + v[1])
+#define hb_be_uint16_eq(a,b) (a[0] == b[0] && a[1] == b[1])
+
+#define hb_be_uint32_put(v,V) HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16); v[2] = (V>>8); v[3] = (V); } HB_STMT_END
+#define hb_be_uint32_get(v) (uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
+#define hb_be_uint32_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
+
+
+/* ASCII tag/character handling */
+
+static inline unsigned char ISALPHA (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
+static inline unsigned char ISALNUM (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
+static inline unsigned char TOUPPER (unsigned char c)
+{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
+static inline unsigned char TOLOWER (unsigned char c)
+{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
+
+#define HB_TAG_CHAR4(s) (HB_TAG(((const char *) s)[0], \
+ ((const char *) s)[1], \
+ ((const char *) s)[2], \
+ ((const char *) s)[3]))
+
+
+/* C++ helpers */
+
+/* Makes class uncopyable. Use in private: section. */
+#define NO_COPY(T) \
+ T (const T &o); \
+ T &operator = (const T &o)
+
+
+/* Debug */
+
+
+#ifndef HB_DEBUG
+#define HB_DEBUG 0
+#endif
+
+static inline bool
+_hb_debug (unsigned int level,
+ unsigned int max_level)
+{
+ return level < max_level;
+}
+
+#define DEBUG_LEVEL(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
+#define DEBUG(WHAT) (DEBUG_LEVEL (WHAT, 0))
+
+template <int max_level> inline bool /* always returns TRUE */
+_hb_debug_msg (const char *what,
+ const void *obj,
+ const char *func,
+ bool indented,
+ int level,
+ const char *message,
+ ...) HB_PRINTF_FUNC(6, 7);
+template <int max_level> inline bool /* always returns TRUE */
+_hb_debug_msg (const char *what,
+ const void *obj,
+ const char *func,
+ bool indented,
+ int level,
+ const char *message,
+ ...)
+{
+ va_list ap;
+ va_start (ap, message);
+
+ (void) (_hb_debug (level, max_level) &&
+ fprintf (stderr, "%s", what) &&
+ (obj && fprintf (stderr, "(%p)", obj), TRUE) &&
+ fprintf (stderr, ": ") &&
+ (func && fprintf (stderr, "%s: ", func), TRUE) &&
+ (indented && fprintf (stderr, "%-*d-> ", level + 1, level), TRUE) &&
+ vfprintf (stderr, message, ap) &&
+ fprintf (stderr, "\n"));
+
+ va_end (ap);
+
+ return TRUE;
+}
+template <> inline bool /* always returns TRUE */
+_hb_debug_msg<0> (const char *what,
+ const void *obj,
+ const char *func,
+ bool indented,
+ int level,
+ const char *message,
+ ...) HB_PRINTF_FUNC(6, 7);
+template <> inline bool /* always returns TRUE */
+_hb_debug_msg<0> (const char *what,
+ const void *obj,
+ const char *func,
+ bool indented,
+ int level,
+ const char *message,
+ ...)
+{
+ return TRUE;
+}
+
+#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, FALSE, (LEVEL), __VA_ARGS__)
+#define DEBUG_MSG(WHAT, OBJ, ...) DEBUG_MSG_LEVEL (WHAT, OBJ, 0, __VA_ARGS__)
+#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, FALSE, 0, __VA_ARGS__)
+
+
+/*
+ * Trace
+ */
+
+template <int max_level>
+struct hb_auto_trace_t {
+ explicit inline hb_auto_trace_t (unsigned int *plevel_,
+ const char *what,
+ const void *obj,
+ const char *func,
+ const char *message) : plevel(plevel_)
+ {
+ if (max_level) ++*plevel;
+ /* TODO support variadic args here */
+ _hb_debug_msg<max_level> (what, obj, func, TRUE, *plevel, "%s", message);
+ }
+ ~hb_auto_trace_t (void) { if (max_level) --*plevel; }
+
+ private:
+ unsigned int *plevel;
+};
+template <> /* Optimize when tracing is disabled */
+struct hb_auto_trace_t<0> {
+ explicit inline hb_auto_trace_t (unsigned int *plevel_,
+ const char *what,
+ const void *obj,
+ const char *func,
+ const char *message) {}
+};
+
+
+/* Misc */
+
+
+/* Pre-mature optimization:
+ * Checks for lo <= u <= hi but with an optimization if lo and hi
+ * are only different in a contiguous set of lower-most bits.
+ */
+template <typename T> inline bool
+hb_in_range (T u, T lo, T hi)
+{
+ if ( ((lo^hi) & lo) == 0 &&
+ ((lo^hi) & hi) == (lo^hi) &&
+ ((lo^hi) & ((lo^hi) + 1)) == 0 )
+ return (u & ~(lo^hi)) == lo;
+ else
+ return lo <= u && u <= hi;
+}
+
+
+/* Useful for set-operations on small enums.
+ * For example, for testing "x ∈ {x1, x2, x3}" use:
+ * (FLAG(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
+ */
+#define FLAG(x) (1<<(x))
+
+
+template <typename T> inline void
+hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
+{
+ if (unlikely (!len))
+ return;
+
+ unsigned int k = len - 1;
+ do {
+ unsigned int new_k = 0;
+
+ for (unsigned int j = 0; j < k; j++)
+ if (compar (&array[j], &array[j+1]) > 0) {
+ T t;
+ t = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = t;
+
+ new_k = j;
+ }
+ k = new_k;
+ } while (k);
+}
+
+
+
+
+#endif /* HB_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-shape.cc b/third_party/harfbuzz-ng/src/hb-shape.cc
index a73977b..9357f81 100644
--- a/third_party/harfbuzz-ng/src/hb-shape.cc
+++ b/third_party/harfbuzz-ng/src/hb-shape.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,42 +24,132 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#include "hb-private.h"
+#include "hb-private.hh"
#include "hb-shape.h"
#include "hb-buffer-private.hh"
-#include "hb-ot-shape.h"
-
#ifdef HAVE_GRAPHITE
-#include "hb-graphite.h"
+#include "hb-graphite2.h"
+#endif
+#ifdef HAVE_UNISCRIBE
+# include "hb-uniscribe.h"
+#endif
+#ifdef HAVE_OT
+# include "hb-ot-shape.h"
#endif
+#include "hb-fallback-shape-private.hh"
-HB_BEGIN_DECLS
+typedef hb_bool_t (*hb_shape_func_t) (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options);
+#define HB_SHAPER_IMPLEMENT(name) {#name, hb_##name##_shape}
+static struct hb_shaper_pair_t {
+ char name[16];
+ hb_shape_func_t func;
+} shapers[] = {
+ /* v--- Add new shapers in the right place here */
+#ifdef HAVE_GRAPHITE
+ HB_SHAPER_IMPLEMENT (graphite),
+#endif
+#ifdef HAVE_UNISCRIBE
+ HB_SHAPER_IMPLEMENT (uniscribe),
+#endif
+#ifdef HAVE_OT
+ HB_SHAPER_IMPLEMENT (ot),
+#endif
+ HB_SHAPER_IMPLEMENT (fallback) /* should be last */
+};
+#undef HB_SHAPER_IMPLEMENT
-void
-hb_shape (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features,
- unsigned int num_features)
+static struct static_shaper_list_t
{
-#if 0 && defined(HAVE_GRAPHITE)
- hb_blob_t *silf_blob;
- silf_blob = hb_face_get_table (face, HB_GRAPHITE_TAG_Silf);
- if (hb_blob_get_length(silf_blob))
+ static_shaper_list_t (void)
{
- hb_graphite_shape(font, face, buffer, features, num_features);
- hb_blob_destroy(silf_blob);
- return;
+ char *env = getenv ("HB_SHAPER_LIST");
+ if (env && *env)
+ {
+ /* Reorder shaper list to prefer requested shaper list. */
+ unsigned int i = 0;
+ char *end, *p = env;
+ for (;;) {
+ end = strchr (p, ',');
+ if (!end)
+ end = p + strlen (p);
+
+ for (unsigned int j = i; j < ARRAY_LENGTH (shapers); j++)
+ if (end - p == (int) strlen (shapers[j].name) &&
+ 0 == strncmp (shapers[j].name, p, end - p))
+ {
+ /* Reorder this shaper to position i */
+ struct hb_shaper_pair_t t = shapers[j];
+ memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i));
+ shapers[i] = t;
+ i++;
+ }
+
+ if (!*end)
+ break;
+ else
+ p = end + 1;
+ }
+ }
+
+ ASSERT_STATIC ((ARRAY_LENGTH (shapers) + 1) * sizeof (*shaper_list) <= sizeof (shaper_list));
+ unsigned int i;
+ for (i = 0; i < ARRAY_LENGTH (shapers); i++)
+ shaper_list[i] = shapers[i].name;
+ shaper_list[i] = NULL;
}
- hb_blob_destroy(silf_blob);
-#endif
- hb_ot_shape (font, face, buffer, features, num_features);
+ const char *shaper_list[ARRAY_LENGTH (shapers) + 1];
+} static_shaper_list;
+
+const char **
+hb_shape_list_shapers (void)
+{
+ return static_shaper_list.shaper_list;
}
+hb_bool_t
+hb_shape_full (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options,
+ const char * const *shaper_list)
+{
+ if (likely (!shaper_list)) {
+ for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++)
+ if (likely (shapers[i].func (font, buffer,
+ features, num_features,
+ shaper_options)))
+ return TRUE;
+ } else {
+ while (*shaper_list) {
+ for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++)
+ if (0 == strcmp (*shaper_list, shapers[i].name)) {
+ if (likely (shapers[i].func (font, buffer,
+ features, num_features,
+ shaper_options)))
+ return TRUE;
+ break;
+ }
+ shaper_list++;
+ }
+ }
+ return FALSE;
+}
-HB_END_DECLS
+void
+hb_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features)
+{
+ hb_shape_full (font, buffer, features, num_features, NULL, NULL);
+}
diff --git a/third_party/harfbuzz-ng/src/hb-shape.h b/third_party/harfbuzz-ng/src/hb-shape.h
index 48f1a55..685b11d 100644
--- a/third_party/harfbuzz-ng/src/hb-shape.h
+++ b/third_party/harfbuzz-ng/src/hb-shape.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -41,12 +41,23 @@ typedef struct _hb_feature_t {
unsigned int end;
} hb_feature_t;
+
void
-hb_shape (hb_font_t *font,
- hb_face_t *face,
- hb_buffer_t *buffer,
- hb_feature_t *features,
- unsigned int num_features);
+hb_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features);
+
+hb_bool_t
+hb_shape_full (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options,
+ const char * const *shaper_list);
+
+const char **
+hb_shape_list_shapers (void);
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-tt-font.cc b/third_party/harfbuzz-ng/src/hb-tt-font.cc
new file mode 100644
index 0000000..ccd86e1
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-tt-font.cc
@@ -0,0 +1,242 @@
+/*
+ * Copyright © 2011 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-open-type-private.hh"
+
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-hmtx-table.hh"
+
+#include "hb-font-private.hh"
+#include "hb-blob.h"
+
+#include <string.h>
+
+
+
+#if 0
+struct hb_tt_font_t
+{
+ const struct hhea *hhea;
+ hb_blob_t *hhea_blob;
+};
+
+
+static hb_tt_font_t *
+_hb_tt_font_create (hb_font_t *font)
+{
+ /* TODO Remove this object altogether */
+ hb_tt_font_t *tt = (hb_tt_font_t *) calloc (1, sizeof (hb_tt_font_t));
+
+ tt->hhea_blob = Sanitizer<hhea>::sanitize (hb_face_reference_table (font->face, HB_OT_TAG_hhea));
+ tt->hhea = Sanitizer<hhea>::lock_instance (tt->hhea_blob);
+
+ return tt;
+}
+
+static void
+_hb_tt_font_destroy (hb_tt_font_t *tt)
+{
+ hb_blob_destroy (tt->hhea_blob);
+
+ free (tt);
+}
+
+static inline const hhea&
+_get_hhea (hb_face_t *face)
+{
+// return likely (face->tt && face->tt->hhea) ? *face->tt->hhea : Null(hhea);
+}
+
+
+/*
+ * hb_tt_font_funcs_t
+ */
+
+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)
+{
+ if (font->parent)
+ return hb_font_get_glyph (font->parent, unicode, variation_selector, glyph);
+
+ *glyph = 0;
+ return FALSE;
+}
+
+static hb_position_t
+hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return font->parent_scale_x_distance (hb_font_get_glyph_h_advance (font->parent, glyph));
+
+ return font->x_scale;
+}
+
+static hb_position_t
+hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return font->parent_scale_y_distance (hb_font_get_glyph_v_advance (font->parent, glyph));
+
+ return font->y_scale;
+}
+
+static hb_bool_t
+hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent,
+ glyph,
+ x, y);
+ if (ret)
+ font->parent_scale_position (x, y);
+ return ret;
+ }
+
+ *x = *y = 0;
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent,
+ glyph,
+ x, y);
+ if (ret)
+ font->parent_scale_position (x, y);
+ return ret;
+ }
+
+ *x = *y = 0;
+ return FALSE;
+}
+
+static hb_position_t
+hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t left_glyph,
+ hb_codepoint_t right_glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return font->parent_scale_x_distance (hb_font_get_glyph_h_kerning (font->parent, left_glyph, right_glyph));
+
+ return 0;
+}
+
+static hb_position_t
+hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t top_glyph,
+ hb_codepoint_t bottom_glyph,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent)
+ return font->parent_scale_y_distance (hb_font_get_glyph_v_kerning (font->parent, top_glyph, bottom_glyph));
+
+ return 0;
+}
+
+static hb_bool_t
+hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_extents (font->parent,
+ glyph,
+ extents);
+ if (ret) {
+ font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
+ font->parent_scale_distance (&extents->width, &extents->height);
+ }
+ return ret;
+ }
+
+ memset (extents, 0, sizeof (*extents));
+ return FALSE;
+}
+
+static hb_bool_t
+hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ unsigned int point_index,
+ hb_position_t *x,
+ hb_position_t *y,
+ void *user_data HB_UNUSED)
+{
+ if (font->parent) {
+ hb_bool_t ret = hb_font_get_glyph_contour_point (font->parent,
+ glyph, point_index,
+ x, y);
+ if (ret)
+ font->parent_scale_position (x, y);
+ return ret;
+ }
+
+ *x = *y = 0;
+ return FALSE;
+}
+
+
+static hb_font_funcs_t _hb_font_funcs_nil = {
+ HB_OBJECT_HEADER_STATIC,
+
+ TRUE, /* immutable */
+
+ {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+ }
+};
+#endif
+
diff --git a/third_party/harfbuzz-ng/src/hb-unicode-private.hh b/third_party/harfbuzz-ng/src/hb-unicode-private.hh
new file mode 100644
index 0000000..2ad8a49
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-unicode-private.hh
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2011 Codethink Limited
+ * Copyright © 2010,2011 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Codethink Author(s): Ryan Lortie
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_UNICODE_PRIVATE_HH
+#define HB_UNICODE_PRIVATE_HH
+
+#include "hb-private.hh"
+
+#include "hb-unicode.h"
+#include "hb-object-private.hh"
+
+
+
+/*
+ * hb_unicode_funcs_t
+ */
+
+#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
+ HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
+ HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
+ HB_UNICODE_FUNC_IMPLEMENT (general_category) \
+ HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
+ HB_UNICODE_FUNC_IMPLEMENT (script) \
+ HB_UNICODE_FUNC_IMPLEMENT (compose) \
+ HB_UNICODE_FUNC_IMPLEMENT (decompose) \
+ /* ^--- Add new callbacks here */
+
+/* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
+#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
+ HB_UNICODE_FUNC_IMPLEMENT (unsigned int, combining_class) \
+ HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
+ HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
+ HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
+ HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
+ /* ^--- Add new simple callbacks here */
+
+struct _hb_unicode_funcs_t {
+ hb_object_header_t header;
+
+ hb_unicode_funcs_t *parent;
+
+ bool immutable;
+
+ /* Don't access these directly. Call hb_unicode_*() instead. */
+
+ struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+ } func;
+
+ struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) void *name;
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+ } user_data;
+
+ struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+ } destroy;
+};
+
+
+#ifdef HAVE_GLIB
+extern HB_INTERNAL hb_unicode_funcs_t _hb_glib_unicode_funcs;
+#define _hb_unicode_funcs_default _hb_glib_unicode_funcs
+#elif defined(HAVE_ICU)
+extern HB_INTERNAL hb_unicode_funcs_t _hb_icu_unicode_funcs;
+#define _hb_unicode_funcs_default _hb_icu_unicode_funcs
+#else
+extern HB_INTERNAL hb_unicode_funcs_t _hb_unicode_funcs_nil;
+#define _hb_unicode_funcs_default _hb_unicode_funcs_nil
+#endif
+
+
+
+
+#endif /* HB_UNICODE_PRIVATE_HH */
diff --git a/third_party/harfbuzz-ng/src/hb-unicode.c b/third_party/harfbuzz-ng/src/hb-unicode.c
deleted file mode 100644
index 2ab308b..0000000
--- a/third_party/harfbuzz-ng/src/hb-unicode.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2009 Red Hat, 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#include "hb-private.h"
-
-#include "hb-unicode-private.h"
-
-HB_BEGIN_DECLS
-
-
-/*
- * hb_unicode_funcs_t
- */
-
-static hb_codepoint_t hb_unicode_get_mirroring_nil (hb_codepoint_t unicode) { return unicode; }
-static hb_category_t hb_unicode_get_general_category_nil (hb_codepoint_t unicode HB_UNUSED) { return HB_CATEGORY_OTHER_LETTER; }
-static hb_script_t hb_unicode_get_script_nil (hb_codepoint_t unicode HB_UNUSED) { return HB_SCRIPT_UNKNOWN; }
-static unsigned int hb_unicode_get_combining_class_nil (hb_codepoint_t unicode HB_UNUSED) { return 0; }
-static unsigned int hb_unicode_get_eastasian_width_nil (hb_codepoint_t unicode HB_UNUSED) { return 1; }
-
-hb_unicode_funcs_t _hb_unicode_funcs_nil = {
- HB_REFERENCE_COUNT_INVALID, /* ref_count */
- TRUE, /* immutable */
- {
- hb_unicode_get_general_category_nil,
- hb_unicode_get_combining_class_nil,
- hb_unicode_get_mirroring_nil,
- hb_unicode_get_script_nil,
- hb_unicode_get_eastasian_width_nil
- }
-};
-
-hb_unicode_funcs_t *
-hb_unicode_funcs_create (void)
-{
- hb_unicode_funcs_t *ufuncs;
-
- if (!HB_OBJECT_DO_CREATE (hb_unicode_funcs_t, ufuncs))
- return &_hb_unicode_funcs_nil;
-
- ufuncs->v = _hb_unicode_funcs_nil.v;
-
- return ufuncs;
-}
-
-hb_unicode_funcs_t *
-hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs)
-{
- HB_OBJECT_DO_REFERENCE (ufuncs);
-}
-
-unsigned int
-hb_unicode_funcs_get_reference_count (hb_unicode_funcs_t *ufuncs)
-{
- HB_OBJECT_DO_GET_REFERENCE_COUNT (ufuncs);
-}
-
-void
-hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
-{
- HB_OBJECT_DO_DESTROY (ufuncs);
-
- free (ufuncs);
-}
-
-hb_unicode_funcs_t *
-hb_unicode_funcs_copy (hb_unicode_funcs_t *other_ufuncs)
-{
- hb_unicode_funcs_t *ufuncs;
-
- if (!HB_OBJECT_DO_CREATE (hb_unicode_funcs_t, ufuncs))
- return &_hb_unicode_funcs_nil;
-
- ufuncs->v = other_ufuncs->v;
-
- return ufuncs;
-}
-
-void
-hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
-{
- if (HB_OBJECT_IS_INERT (ufuncs))
- return;
-
- ufuncs->immutable = TRUE;
-}
-
-hb_bool_t
-hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
-{
- return ufuncs->immutable;
-}
-
-
-void
-hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_mirroring_func_t mirroring_func)
-{
- if (ufuncs->immutable)
- return;
-
- ufuncs->v.get_mirroring = mirroring_func ? mirroring_func : hb_unicode_get_mirroring_nil;
-}
-
-void
-hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_general_category_func_t general_category_func)
-{
- if (ufuncs->immutable)
- return;
-
- ufuncs->v.get_general_category = general_category_func ? general_category_func : hb_unicode_get_general_category_nil;
-}
-
-void
-hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_script_func_t script_func)
-{
- if (ufuncs->immutable)
- return;
-
- ufuncs->v.get_script = script_func ? script_func : hb_unicode_get_script_nil;
-}
-
-void
-hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_combining_class_func_t combining_class_func)
-{
- if (ufuncs->immutable)
- return;
-
- ufuncs->v.get_combining_class = combining_class_func ? combining_class_func : hb_unicode_get_combining_class_nil;
-}
-
-void
-hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_eastasian_width_func_t eastasian_width_func)
-{
- if (ufuncs->immutable)
- return;
-
- ufuncs->v.get_eastasian_width = eastasian_width_func ? eastasian_width_func : hb_unicode_get_eastasian_width_nil;
-}
-
-
-hb_unicode_get_mirroring_func_t
-hb_unicode_funcs_get_mirroring_func (hb_unicode_funcs_t *ufuncs)
-{
- return ufuncs->v.get_mirroring;
-}
-
-hb_unicode_get_general_category_func_t
-hb_unicode_funcs_get_general_category_func (hb_unicode_funcs_t *ufuncs)
-{
- return ufuncs->v.get_general_category;
-}
-
-hb_unicode_get_script_func_t
-hb_unicode_funcs_get_script_func (hb_unicode_funcs_t *ufuncs)
-{
- return ufuncs->v.get_script;
-}
-
-hb_unicode_get_combining_class_func_t
-hb_unicode_funcs_get_combining_class_func (hb_unicode_funcs_t *ufuncs)
-{
- return ufuncs->v.get_combining_class;
-}
-
-hb_unicode_get_eastasian_width_func_t
-hb_unicode_funcs_get_eastasian_width_func (hb_unicode_funcs_t *ufuncs)
-{
- return ufuncs->v.get_eastasian_width;
-}
-
-
-
-hb_codepoint_t
-hb_unicode_get_mirroring (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode)
-{
- return ufuncs->v.get_mirroring (unicode);
-}
-
-hb_category_t
-hb_unicode_get_general_category (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode)
-{
- return ufuncs->v.get_general_category (unicode);
-}
-
-hb_script_t
-hb_unicode_get_script (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode)
-{
- return ufuncs->v.get_script (unicode);
-}
-
-unsigned int
-hb_unicode_get_combining_class (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode)
-{
- return ufuncs->v.get_combining_class (unicode);
-}
-
-unsigned int
-hb_unicode_get_eastasian_width (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode)
-{
- return ufuncs->v.get_eastasian_width (unicode);
-}
-
-
-
-#define LTR HB_DIRECTION_LTR
-#define RTL HB_DIRECTION_RTL
-const hb_direction_t horiz_dir[] =
-{
- LTR, /* Zyyy */
- LTR, /* Qaai */
- RTL, /* Arab */
- LTR, /* Armn */
- LTR, /* Beng */
- LTR, /* Bopo */
- LTR, /* Cher */
- LTR, /* Qaac */
- LTR, /* Cyrl (Cyrs) */
- LTR, /* Dsrt */
- LTR, /* Deva */
- LTR, /* Ethi */
- LTR, /* Geor (Geon, Geoa) */
- LTR, /* Goth */
- LTR, /* Grek */
- LTR, /* Gujr */
- LTR, /* Guru */
- LTR, /* Hani */
- LTR, /* Hang */
- RTL, /* Hebr */
- LTR, /* Hira */
- LTR, /* Knda */
- LTR, /* Kana */
- LTR, /* Khmr */
- LTR, /* Laoo */
- LTR, /* Latn (Latf, Latg) */
- LTR, /* Mlym */
- LTR, /* Mong */
- LTR, /* Mymr */
- LTR, /* Ogam */
- LTR, /* Ital */
- LTR, /* Orya */
- LTR, /* Runr */
- LTR, /* Sinh */
- RTL, /* Syrc (Syrj, Syrn, Syre) */
- LTR, /* Taml */
- LTR, /* Telu */
- RTL, /* Thaa */
- LTR, /* Thai */
- LTR, /* Tibt */
- LTR, /* Cans */
- LTR, /* Yiii */
- LTR, /* Tglg */
- LTR, /* Hano */
- LTR, /* Buhd */
- LTR, /* Tagb */
-
- /* Unicode-4.0 additions */
- LTR, /* Brai */
- RTL, /* Cprt */
- LTR, /* Limb */
- LTR, /* Osma */
- LTR, /* Shaw */
- LTR, /* Linb */
- LTR, /* Tale */
- LTR, /* Ugar */
-
- /* Unicode-4.1 additions */
- LTR, /* Talu */
- LTR, /* Bugi */
- LTR, /* Glag */
- LTR, /* Tfng */
- LTR, /* Sylo */
- LTR, /* Xpeo */
- LTR, /* Khar */
-
- /* Unicode-5.0 additions */
- LTR, /* Zzzz */
- LTR, /* Bali */
- LTR, /* Xsux */
- RTL, /* Phnx */
- LTR, /* Phag */
- RTL, /* Nkoo */
-
- /* Unicode-5.1 additions */
- LTR, /* Kali */
- LTR, /* Lepc */
- LTR, /* Rjng */
- LTR, /* Sund */
- LTR, /* Saur */
- LTR, /* Cham */
- LTR, /* Olck */
- LTR, /* Vaii */
- LTR, /* Cari */
- LTR, /* Lyci */
- LTR, /* Lydi */
-
- /* Unicode-5.2 additions */
- RTL, /* Avst */
- LTR, /* Bamu */
- LTR, /* Egyp */
- RTL, /* Armi */
- RTL, /* Phli */
- RTL, /* Prti */
- LTR, /* Java */
- LTR, /* Kthi */
- LTR, /* Lisu */
- LTR, /* Mtei */
- RTL, /* Sarb */
- RTL, /* Orkh */
- RTL, /* Samr */
- LTR, /* Lana */
- LTR, /* Tavt */
-
- /* Unicode-6.0 additions */
- LTR, /* Batk */
- LTR, /* Brah */
- RTL /* Mand */
-};
-#undef LTR
-#undef RTL
-
-hb_direction_t
-_hb_script_get_horizontal_direction (hb_script_t script)
-{
- if (unlikely ((unsigned int) script >= ARRAY_LENGTH (horiz_dir)))
- return HB_DIRECTION_LTR;
-
- return horiz_dir[script];
-}
-
-
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-unicode.cc b/third_party/harfbuzz-ng/src/hb-unicode.cc
new file mode 100644
index 0000000..4b285c5
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-unicode.cc
@@ -0,0 +1,273 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2011 Codethink Limited
+ * Copyright © 2010,2011 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.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Codethink Author(s): Ryan Lortie
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-private.hh"
+
+#include "hb-unicode-private.hh"
+
+
+
+/*
+ * hb_unicode_funcs_t
+ */
+
+static unsigned int
+hb_unicode_combining_class_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ return 0;
+}
+
+static unsigned int
+hb_unicode_eastasian_width_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ return 1;
+}
+
+static hb_unicode_general_category_t
+hb_unicode_general_category_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
+}
+
+static hb_codepoint_t
+hb_unicode_mirroring_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ return unicode;
+}
+
+static hb_script_t
+hb_unicode_script_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t unicode HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ return HB_SCRIPT_UNKNOWN;
+}
+
+static hb_bool_t
+hb_unicode_compose_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t a HB_UNUSED,
+ hb_codepoint_t b HB_UNUSED,
+ hb_codepoint_t *ab HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ /* TODO handle Hangul jamo here? */
+ return FALSE;
+}
+
+static hb_bool_t
+hb_unicode_decompose_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+ hb_codepoint_t ab HB_UNUSED,
+ hb_codepoint_t *a HB_UNUSED,
+ hb_codepoint_t *b HB_UNUSED,
+ void *user_data HB_UNUSED)
+{
+ /* TODO handle Hangul jamo here? */
+ return FALSE;
+}
+
+
+hb_unicode_funcs_t _hb_unicode_funcs_nil = {
+ HB_OBJECT_HEADER_STATIC,
+
+ NULL, /* parent */
+ TRUE, /* immutable */
+ {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil,
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+ }
+};
+
+
+hb_unicode_funcs_t *
+hb_unicode_funcs_get_default (void)
+{
+ return &_hb_unicode_funcs_default;
+}
+
+hb_unicode_funcs_t *
+hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
+{
+ hb_unicode_funcs_t *ufuncs;
+
+ if (!(ufuncs = hb_object_create<hb_unicode_funcs_t> ()))
+ return &_hb_unicode_funcs_nil;
+
+ if (!parent)
+ parent = &_hb_unicode_funcs_nil;
+
+ hb_unicode_funcs_make_immutable (parent);
+ ufuncs->parent = hb_unicode_funcs_reference (parent);
+
+ ufuncs->func = parent->func;
+
+ /* We can safely copy user_data from parent since we hold a reference
+ * onto it and it's immutable. We should not copy the destroy notifiers
+ * though. */
+ ufuncs->user_data = parent->user_data;
+
+ return ufuncs;
+}
+
+hb_unicode_funcs_t *
+hb_unicode_funcs_get_empty (void)
+{
+ return &_hb_unicode_funcs_nil;
+}
+
+hb_unicode_funcs_t *
+hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs)
+{
+ return hb_object_reference (ufuncs);
+}
+
+void
+hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
+{
+ if (!hb_object_destroy (ufuncs)) return;
+
+#define HB_UNICODE_FUNC_IMPLEMENT(name) \
+ if (ufuncs->destroy.name) ufuncs->destroy.name (ufuncs->user_data.name);
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+
+ hb_unicode_funcs_destroy (ufuncs->parent);
+
+ free (ufuncs);
+}
+
+hb_bool_t
+hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (ufuncs, key, data, destroy, replace);
+}
+
+void *
+hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (ufuncs, key);
+}
+
+
+void
+hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
+{
+ if (hb_object_is_inert (ufuncs))
+ return;
+
+ ufuncs->immutable = TRUE;
+}
+
+hb_bool_t
+hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
+{
+ return ufuncs->immutable;
+}
+
+hb_unicode_funcs_t *
+hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs)
+{
+ return ufuncs->parent ? ufuncs->parent : &_hb_unicode_funcs_nil;
+}
+
+
+#define HB_UNICODE_FUNC_IMPLEMENT(name) \
+ \
+void \
+hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t *ufuncs, \
+ hb_unicode_##name##_func_t func, \
+ void *user_data, \
+ hb_destroy_func_t destroy) \
+{ \
+ if (ufuncs->immutable) \
+ return; \
+ \
+ if (ufuncs->destroy.name) \
+ ufuncs->destroy.name (ufuncs->user_data.name); \
+ \
+ if (func) { \
+ ufuncs->func.name = func; \
+ ufuncs->user_data.name = user_data; \
+ ufuncs->destroy.name = destroy; \
+ } else { \
+ ufuncs->func.name = ufuncs->parent->func.name; \
+ ufuncs->user_data.name = ufuncs->parent->user_data.name; \
+ ufuncs->destroy.name = NULL; \
+ } \
+}
+
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+
+
+#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
+ \
+return_type \
+hb_unicode_##name (hb_unicode_funcs_t *ufuncs, \
+ hb_codepoint_t unicode) \
+{ \
+ return ufuncs->func.name (ufuncs, unicode, ufuncs->user_data.name); \
+}
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
+#undef HB_UNICODE_FUNC_IMPLEMENT
+
+hb_bool_t
+hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab)
+{
+ *ab = 0;
+ return ufuncs->func.compose (ufuncs, a, b, ab, ufuncs->user_data.compose);
+}
+
+hb_bool_t
+hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b)
+{
+ *a = ab; *b = 0;
+ return ufuncs->func.decompose (ufuncs, ab, a, b, ufuncs->user_data.decompose);
+}
+
diff --git a/third_party/harfbuzz-ng/src/hb-unicode.h b/third_party/harfbuzz-ng/src/hb-unicode.h
index 43b04ca..13886df 100644
--- a/third_party/harfbuzz-ng/src/hb-unicode.h
+++ b/third_party/harfbuzz-ng/src/hb-unicode.h
@@ -1,5 +1,7 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2011 Codethink Limited
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -22,6 +24,8 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
+ * Codethink Author(s): Ryan Lortie
+ * Google Author(s): Behdad Esfahbod
*/
#ifndef HB_UNICODE_H
@@ -32,176 +36,44 @@
HB_BEGIN_DECLS
-/* Unicode General Category property */
-typedef enum
-{
- HB_CATEGORY_CONTROL, /* Cc */
- HB_CATEGORY_FORMAT, /* Cf */
- HB_CATEGORY_UNASSIGNED, /* Cn */
- HB_CATEGORY_PRIVATE_USE, /* Co */
- HB_CATEGORY_SURROGATE, /* Cs */
- HB_CATEGORY_LOWERCASE_LETTER, /* Ll */
- HB_CATEGORY_MODIFIER_LETTER, /* Lm */
- HB_CATEGORY_OTHER_LETTER, /* Lo */
- HB_CATEGORY_TITLECASE_LETTER, /* Lt */
- HB_CATEGORY_UPPERCASE_LETTER, /* Lu */
- HB_CATEGORY_COMBINING_MARK, /* Mc */
- HB_CATEGORY_ENCLOSING_MARK, /* Me */
- HB_CATEGORY_NON_SPACING_MARK, /* Mn */
- HB_CATEGORY_DECIMAL_NUMBER, /* Nd */
- HB_CATEGORY_LETTER_NUMBER, /* Nl */
- HB_CATEGORY_OTHER_NUMBER, /* No */
- HB_CATEGORY_CONNECT_PUNCTUATION, /* Pc */
- HB_CATEGORY_DASH_PUNCTUATION, /* Pd */
- HB_CATEGORY_CLOSE_PUNCTUATION, /* Pe */
- HB_CATEGORY_FINAL_PUNCTUATION, /* Pf */
- HB_CATEGORY_INITIAL_PUNCTUATION, /* Pi */
- HB_CATEGORY_OTHER_PUNCTUATION, /* Po */
- HB_CATEGORY_OPEN_PUNCTUATION, /* Ps */
- HB_CATEGORY_CURRENCY_SYMBOL, /* Sc */
- HB_CATEGORY_MODIFIER_SYMBOL, /* Sk */
- HB_CATEGORY_MATH_SYMBOL, /* Sm */
- HB_CATEGORY_OTHER_SYMBOL, /* So */
- HB_CATEGORY_LINE_SEPARATOR, /* Zl */
- HB_CATEGORY_PARAGRAPH_SEPARATOR, /* Zp */
- HB_CATEGORY_SPACE_SEPARATOR /* Zs */
-} hb_category_t;
-
-/* Unicode Script property */
-typedef enum
-{ /* ISO 15924 code */
- HB_SCRIPT_INVALID_CODE = -1,
- HB_SCRIPT_COMMON = 0, /* Zyyy */
- HB_SCRIPT_INHERITED, /* Qaai */
- HB_SCRIPT_ARABIC, /* Arab */
- HB_SCRIPT_ARMENIAN, /* Armn */
- HB_SCRIPT_BENGALI, /* Beng */
- HB_SCRIPT_BOPOMOFO, /* Bopo */
- HB_SCRIPT_CHEROKEE, /* Cher */
- HB_SCRIPT_COPTIC, /* Qaac */
- HB_SCRIPT_CYRILLIC, /* Cyrl (Cyrs) */
- HB_SCRIPT_DESERET, /* Dsrt */
- HB_SCRIPT_DEVANAGARI, /* Deva */
- HB_SCRIPT_ETHIOPIC, /* Ethi */
- HB_SCRIPT_GEORGIAN, /* Geor (Geon, Geoa) */
- HB_SCRIPT_GOTHIC, /* Goth */
- HB_SCRIPT_GREEK, /* Grek */
- HB_SCRIPT_GUJARATI, /* Gujr */
- HB_SCRIPT_GURMUKHI, /* Guru */
- HB_SCRIPT_HAN, /* Hani */
- HB_SCRIPT_HANGUL, /* Hang */
- HB_SCRIPT_HEBREW, /* Hebr */
- HB_SCRIPT_HIRAGANA, /* Hira */
- HB_SCRIPT_KANNADA, /* Knda */
- HB_SCRIPT_KATAKANA, /* Kana */
- HB_SCRIPT_KHMER, /* Khmr */
- HB_SCRIPT_LAO, /* Laoo */
- HB_SCRIPT_LATIN, /* Latn (Latf, Latg) */
- HB_SCRIPT_MALAYALAM, /* Mlym */
- HB_SCRIPT_MONGOLIAN, /* Mong */
- HB_SCRIPT_MYANMAR, /* Mymr */
- HB_SCRIPT_OGHAM, /* Ogam */
- HB_SCRIPT_OLD_ITALIC, /* Ital */
- HB_SCRIPT_ORIYA, /* Orya */
- HB_SCRIPT_RUNIC, /* Runr */
- HB_SCRIPT_SINHALA, /* Sinh */
- HB_SCRIPT_SYRIAC, /* Syrc (Syrj, Syrn, Syre) */
- HB_SCRIPT_TAMIL, /* Taml */
- HB_SCRIPT_TELUGU, /* Telu */
- HB_SCRIPT_THAANA, /* Thaa */
- HB_SCRIPT_THAI, /* Thai */
- HB_SCRIPT_TIBETAN, /* Tibt */
- HB_SCRIPT_CANADIAN_ABORIGINAL, /* Cans */
- HB_SCRIPT_YI, /* Yiii */
- HB_SCRIPT_TAGALOG, /* Tglg */
- HB_SCRIPT_HANUNOO, /* Hano */
- HB_SCRIPT_BUHID, /* Buhd */
- HB_SCRIPT_TAGBANWA, /* Tagb */
-
- /* Unicode-4.0 additions */
- HB_SCRIPT_BRAILLE, /* Brai */
- HB_SCRIPT_CYPRIOT, /* Cprt */
- HB_SCRIPT_LIMBU, /* Limb */
- HB_SCRIPT_OSMANYA, /* Osma */
- HB_SCRIPT_SHAVIAN, /* Shaw */
- HB_SCRIPT_LINEAR_B, /* Linb */
- HB_SCRIPT_TAI_LE, /* Tale */
- HB_SCRIPT_UGARITIC, /* Ugar */
-
- /* Unicode-4.1 additions */
- HB_SCRIPT_NEW_TAI_LUE, /* Talu */
- HB_SCRIPT_BUGINESE, /* Bugi */
- HB_SCRIPT_GLAGOLITIC, /* Glag */
- HB_SCRIPT_TIFINAGH, /* Tfng */
- HB_SCRIPT_SYLOTI_NAGRI, /* Sylo */
- HB_SCRIPT_OLD_PERSIAN, /* Xpeo */
- HB_SCRIPT_KHAROSHTHI, /* Khar */
-
- /* Unicode-5.0 additions */
- HB_SCRIPT_UNKNOWN, /* Zzzz */
- HB_SCRIPT_BALINESE, /* Bali */
- HB_SCRIPT_CUNEIFORM, /* Xsux */
- HB_SCRIPT_PHOENICIAN, /* Phnx */
- HB_SCRIPT_PHAGS_PA, /* Phag */
- HB_SCRIPT_NKO, /* Nkoo */
-
- /* Unicode-5.1 additions */
- HB_SCRIPT_KAYAH_LI, /* Kali */
- HB_SCRIPT_LEPCHA, /* Lepc */
- HB_SCRIPT_REJANG, /* Rjng */
- HB_SCRIPT_SUNDANESE, /* Sund */
- HB_SCRIPT_SAURASHTRA, /* Saur */
- HB_SCRIPT_CHAM, /* Cham */
- HB_SCRIPT_OL_CHIKI, /* Olck */
- HB_SCRIPT_VAI, /* Vaii */
- HB_SCRIPT_CARIAN, /* Cari */
- HB_SCRIPT_LYCIAN, /* Lyci */
- HB_SCRIPT_LYDIAN, /* Lydi */
-
- /* Unicode-5.2 additions */
- HB_SCRIPT_AVESTAN, /* Avst */
- HB_SCRIPT_BAMUM, /* Bamu */
- HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, /* Egyp */
- HB_SCRIPT_IMPERIAL_ARAMAIC, /* Armi */
- HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, /* Phli */
- HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, /* Prti */
- HB_SCRIPT_JAVANESE, /* Java */
- HB_SCRIPT_KAITHI, /* Kthi */
- HB_SCRIPT_LISU, /* Lisu */
- HB_SCRIPT_MEETEI_MAYEK, /* Mtei */
- HB_SCRIPT_OLD_SOUTH_ARABIAN, /* Sarb */
- HB_SCRIPT_OLD_TURKIC, /* Orkh */
- HB_SCRIPT_SAMARITAN, /* Samr */
- HB_SCRIPT_TAI_THAM, /* Lana */
- HB_SCRIPT_TAI_VIET, /* Tavt */
-
- /* Unicode-6.0 additions */
- HB_SCRIPT_BATAK, /* Batk */
- HB_SCRIPT_BRAHMI, /* Brah */
- HB_SCRIPT_MANDAIC /* Mand */
-} hb_script_t;
-
-
/*
* hb_unicode_funcs_t
*/
typedef struct _hb_unicode_funcs_t hb_unicode_funcs_t;
+
+/*
+ * just give me the best implementation you've got there.
+ */
+hb_unicode_funcs_t *
+hb_unicode_funcs_get_default (void);
+
+
hb_unicode_funcs_t *
-hb_unicode_funcs_create (void);
+hb_unicode_funcs_create (hb_unicode_funcs_t *parent);
hb_unicode_funcs_t *
-hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs);
+hb_unicode_funcs_get_empty (void);
-unsigned int
-hb_unicode_funcs_get_reference_count (hb_unicode_funcs_t *ufuncs);
+hb_unicode_funcs_t *
+hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs);
void
hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs);
-hb_unicode_funcs_t *
-hb_unicode_funcs_copy (hb_unicode_funcs_t *ufuncs);
+hb_bool_t
+hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+
+void *
+hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key);
+
void
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs);
@@ -209,85 +81,113 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs);
hb_bool_t
hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs);
+hb_unicode_funcs_t *
+hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs);
+
+
/*
* funcs
*/
-
/* typedefs */
-typedef hb_codepoint_t (*hb_unicode_get_mirroring_func_t) (hb_codepoint_t unicode);
-typedef hb_category_t (*hb_unicode_get_general_category_func_t) (hb_codepoint_t unicode);
-typedef hb_script_t (*hb_unicode_get_script_func_t) (hb_codepoint_t unicode);
-typedef unsigned int (*hb_unicode_get_combining_class_func_t) (hb_codepoint_t unicode);
-typedef unsigned int (*hb_unicode_get_eastasian_width_func_t) (hb_codepoint_t unicode);
-
+typedef unsigned int (*hb_unicode_combining_class_func_t) (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode,
+ void *user_data);
+typedef unsigned int (*hb_unicode_eastasian_width_func_t) (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode,
+ void *user_data);
+typedef hb_unicode_general_category_t (*hb_unicode_general_category_func_t) (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode,
+ void *user_data);
+typedef hb_codepoint_t (*hb_unicode_mirroring_func_t) (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode,
+ void *user_data);
+typedef hb_script_t (*hb_unicode_script_func_t) (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode,
+ void *user_data);
+
+typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab,
+ void *user_data);
+typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b,
+ void *user_data);
/* setters */
void
-hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_mirroring_func_t mirroring_func);
+hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
+ hb_unicode_combining_class_func_t combining_class_func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_general_category_func_t general_category_func);
+hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
+ hb_unicode_eastasian_width_func_t eastasian_width_func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_script_func_t script_func);
+hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
+ hb_unicode_general_category_func_t general_category_func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_combining_class_func_t combining_class_func);
+hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
+ hb_unicode_mirroring_func_t mirroring_func,
+ void *user_data, hb_destroy_func_t destroy);
void
-hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
- hb_unicode_get_eastasian_width_func_t eastasian_width_func);
-
-
-/* getters */
-
-/* These never return NULL. Return fallback defaults instead. */
+hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
+ hb_unicode_script_func_t script_func,
+ void *user_data, hb_destroy_func_t destroy);
-hb_unicode_get_mirroring_func_t
-hb_unicode_funcs_get_mirroring_func (hb_unicode_funcs_t *ufuncs);
+void
+hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs,
+ hb_unicode_compose_func_t compose_func,
+ void *user_data, hb_destroy_func_t destroy);
-hb_unicode_get_general_category_func_t
-hb_unicode_funcs_get_general_category_func (hb_unicode_funcs_t *ufuncs);
+void
+hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs,
+ hb_unicode_decompose_func_t decompose_func,
+ void *user_data, hb_destroy_func_t destroy);
-hb_unicode_get_script_func_t
-hb_unicode_funcs_get_script_func (hb_unicode_funcs_t *ufuncs);
-hb_unicode_get_combining_class_func_t
-hb_unicode_funcs_get_combining_class_func (hb_unicode_funcs_t *ufuncs);
+/* accessors */
-hb_unicode_get_eastasian_width_func_t
-hb_unicode_funcs_get_eastasian_width_func (hb_unicode_funcs_t *ufuncs);
+unsigned int
+hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
+unsigned int
+hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
-/* accessors */
+hb_unicode_general_category_t
+hb_unicode_general_category (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
hb_codepoint_t
-hb_unicode_get_mirroring (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode);
-
-hb_category_t
-hb_unicode_get_general_category (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode);
+hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
hb_script_t
-hb_unicode_get_script (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode);
-
-unsigned int
-hb_unicode_get_combining_class (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode);
-
-unsigned int
-hb_unicode_get_eastasian_width (hb_unicode_funcs_t *ufuncs,
- hb_codepoint_t unicode);
+hb_unicode_script (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode);
+hb_bool_t
+hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab);
+hb_bool_t
+hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b);
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-uniscribe.cc b/third_party/harfbuzz-ng/src/hb-uniscribe.cc
new file mode 100644
index 0000000..ce86074
--- /dev/null
+++ b/third_party/harfbuzz-ng/src/hb-uniscribe.cc
@@ -0,0 +1,463 @@
+/*
+ * Copyright © 2011 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
+ */
+
+#define _WIN32_WINNT 0x0500
+
+#include "hb-private.hh"
+
+#include <windows.h>
+#include <usp10.h>
+
+typedef ULONG WIN_ULONG;
+
+#include "hb-uniscribe.h"
+
+#include "hb-ot-name-table.hh"
+#include "hb-ot-tag.h"
+
+#include "hb-font-private.hh"
+#include "hb-buffer-private.hh"
+
+
+
+#ifndef HB_DEBUG_UNISCRIBE
+#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
+#endif
+
+
+/*
+DWORD GetFontData(
+ __in HDC hdc,
+ __in DWORD dwTable,
+ __in DWORD dwOffset,
+ __out LPVOID lpvBuffer,
+ __in DWORD cbData
+);
+*/
+
+static bool
+populate_log_font (LOGFONTW *lf,
+ HDC hdc,
+ hb_font_t *font)
+{
+ memset (lf, 0, sizeof (*lf));
+ int dpi = GetDeviceCaps (hdc, LOGPIXELSY);
+ lf->lfHeight = -font->y_scale;
+
+ hb_blob_t *blob = Sanitizer<name>::sanitize (hb_face_reference_table (font->face, HB_TAG ('n','a','m','e')));
+ const name *name_table = Sanitizer<name>::lock_instance (blob);
+ unsigned int len = name_table->get_name (3, 1, 0x409, 4,
+ lf->lfFaceName,
+ sizeof (lf->lfFaceName[0]) * LF_FACESIZE)
+ / sizeof (lf->lfFaceName[0]);
+ hb_blob_destroy (blob);
+
+ if (unlikely (!len)) {
+ DEBUG_MSG (UNISCRIBE, NULL, "Didn't find English name table entry");
+ return FALSE;
+ }
+ if (unlikely (len >= LF_FACESIZE)) {
+ DEBUG_MSG (UNISCRIBE, NULL, "Font name too long");
+ return FALSE;
+ }
+
+ for (unsigned int i = 0; i < len; i++)
+ lf->lfFaceName[i] = hb_be_uint16 (lf->lfFaceName[i]);
+ lf->lfFaceName[len] = 0;
+
+ return TRUE;
+}
+
+
+static hb_user_data_key_t hb_uniscribe_data_key;
+
+
+static struct hb_uniscribe_face_data_t {
+ HANDLE fh;
+} _hb_uniscribe_face_data_nil = {0};
+
+static void
+_hb_uniscribe_face_data_destroy (hb_uniscribe_face_data_t *data)
+{
+ if (data->fh)
+ RemoveFontMemResourceEx (data->fh);
+ free (data);
+}
+
+static hb_uniscribe_face_data_t *
+_hb_uniscribe_face_get_data (hb_face_t *face)
+{
+ hb_uniscribe_face_data_t *data = (hb_uniscribe_face_data_t *) hb_face_get_user_data (face, &hb_uniscribe_data_key);
+ if (likely (data)) return data;
+
+ data = (hb_uniscribe_face_data_t *) calloc (1, sizeof (hb_uniscribe_face_data_t));
+ if (unlikely (!data))
+ return &_hb_uniscribe_face_data_nil;
+
+
+ hb_blob_t *blob = hb_face_reference_blob (face);
+ unsigned int blob_length;
+ const char *blob_data = hb_blob_get_data (blob, &blob_length);
+ if (unlikely (!blob_length))
+ DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");
+
+ DWORD num_fonts_installed;
+ data->fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed);
+ hb_blob_destroy (blob);
+ if (unlikely (!data->fh))
+ DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
+
+
+ if (unlikely (!hb_face_set_user_data (face, &hb_uniscribe_data_key, data,
+ (hb_destroy_func_t) _hb_uniscribe_face_data_destroy,
+ FALSE)))
+ {
+ _hb_uniscribe_face_data_destroy (data);
+ data = (hb_uniscribe_face_data_t *) hb_face_get_user_data (face, &hb_uniscribe_data_key);
+ if (data)
+ return data;
+ else
+ return &_hb_uniscribe_face_data_nil;
+ }
+
+ return data;
+}
+
+
+static struct hb_uniscribe_font_data_t {
+ HDC hdc;
+ LOGFONTW log_font;
+ HFONT hfont;
+ SCRIPT_CACHE script_cache;
+} _hb_uniscribe_font_data_nil = {NULL, NULL, NULL};
+
+static void
+_hb_uniscribe_font_data_destroy (hb_uniscribe_font_data_t *data)
+{
+ if (data->hdc)
+ ReleaseDC (NULL, data->hdc);
+ if (data->hfont)
+ DeleteObject (data->hfont);
+ if (data->script_cache)
+ ScriptFreeCache (&data->script_cache);
+ free (data);
+}
+
+static hb_uniscribe_font_data_t *
+_hb_uniscribe_font_get_data (hb_font_t *font)
+{
+ hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) hb_font_get_user_data (font, &hb_uniscribe_data_key);
+ if (likely (data)) return data;
+
+ data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_t));
+ if (unlikely (!data))
+ return &_hb_uniscribe_font_data_nil;
+
+ data->hdc = GetDC (NULL);
+
+ if (unlikely (!populate_log_font (&data->log_font, data->hdc, font)))
+ DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
+ else {
+ data->hfont = CreateFontIndirectW (&data->log_font);
+ if (unlikely (!data->hfont))
+ DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
+ if (!SelectObject (data->hdc, data->hfont))
+ DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
+ }
+
+ if (unlikely (!hb_font_set_user_data (font, &hb_uniscribe_data_key, data,
+ (hb_destroy_func_t) _hb_uniscribe_font_data_destroy,
+ FALSE)))
+ {
+ _hb_uniscribe_font_data_destroy (data);
+ data = (hb_uniscribe_font_data_t *) hb_font_get_user_data (font, &hb_uniscribe_data_key);
+ if (data)
+ return data;
+ else
+ return &_hb_uniscribe_font_data_nil;
+ }
+
+ return data;
+}
+
+LOGFONTW *
+hb_uniscribe_font_get_logfontw (hb_font_t *font)
+{
+ hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
+ if (unlikely (!font_data))
+ return NULL;
+ return &font_data->log_font;
+}
+
+HFONT
+hb_uniscribe_font_get_hfont (hb_font_t *font)
+{
+ hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
+ if (unlikely (!font_data))
+ return 0;
+ return font_data->hfont;
+}
+
+
+hb_bool_t
+hb_uniscribe_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options)
+{
+ buffer->guess_properties ();
+
+#define FAIL(...) \
+ HB_STMT_START { \
+ DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
+ return FALSE; \
+ } HB_STMT_END;
+
+ hb_uniscribe_face_data_t *face_data = _hb_uniscribe_face_get_data (font->face);
+ if (unlikely (!face_data->fh))
+ FAIL ("Couldn't get face data");
+
+ hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
+ if (unlikely (!font_data->hfont))
+ FAIL ("Couldn't get font font");
+
+ if (unlikely (!buffer->len))
+ return TRUE;
+
+ HRESULT hr;
+
+retry:
+
+ unsigned int scratch_size;
+ char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
+
+ /* Allocate char buffers; they all fit */
+
+#define ALLOCATE_ARRAY(Type, name, len) \
+ Type *name = (Type *) scratch; \
+ scratch += len * sizeof (name[0]); \
+ scratch_size -= len * sizeof (name[0]);
+
+#define utf16_index() var1.u32
+
+ WCHAR *pchars = (WCHAR *) scratch;
+ unsigned int chars_len = 0;
+ for (unsigned int i = 0; i < buffer->len; i++) {
+ hb_codepoint_t c = buffer->info[i].codepoint;
+ buffer->info[i].utf16_index() = chars_len;
+ if (likely (c < 0x10000))
+ pchars[chars_len++] = c;
+ else if (unlikely (c >= 0x110000))
+ pchars[chars_len++] = 0xFFFD;
+ else {
+ pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
+ pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
+ }
+ }
+
+ ALLOCATE_ARRAY (WCHAR, wchars, chars_len);
+ ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
+ ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len);
+
+ /* On Windows, we don't care about alignment...*/
+ unsigned int glyphs_size = scratch_size / (sizeof (WORD) +
+ sizeof (SCRIPT_GLYPHPROP) +
+ sizeof (int) +
+ sizeof (GOFFSET) +
+ sizeof (uint32_t));
+
+ ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
+ ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
+ ALLOCATE_ARRAY (int, advances, glyphs_size);
+ ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
+ ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
+
+
+#define MAX_ITEMS 10
+
+ SCRIPT_ITEM items[MAX_ITEMS + 1];
+ SCRIPT_CONTROL bidi_control = {0};
+ SCRIPT_STATE bidi_state = {0};
+ WIN_ULONG script_tags[MAX_ITEMS];
+ int item_count;
+
+ /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */
+ //bidi_control.fMergeNeutralItems = TRUE;
+ *(uint32_t*)&bidi_control |= 1<<24;
+
+ bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
+// bidi_state.fOverrideDirection = 1;
+
+ hr = ScriptItemizeOpenType (wchars,
+ chars_len,
+ MAX_ITEMS,
+ &bidi_control,
+ &bidi_state,
+ items,
+ script_tags,
+ &item_count);
+ if (unlikely (FAILED (hr)))
+ FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
+
+#undef MAX_ITEMS
+
+ int *range_char_counts = NULL;
+ TEXTRANGE_PROPERTIES **range_properties = NULL;
+ int range_count = 0;
+ if (num_features) {
+ /* TODO setup ranges */
+ }
+
+ OPENTYPE_TAG language_tag = hb_ot_tag_from_language (buffer->props.language);
+
+ unsigned int glyphs_offset = 0;
+ unsigned int glyphs_len;
+ for (unsigned int i = 0; i < item_count; i++)
+ {
+ unsigned int chars_offset = items[i].iCharPos;
+ unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
+ OPENTYPE_TAG script_tag = script_tags[i]; /* XXX buffer->props.script */
+
+ hr = ScriptShapeOpenType (font_data->hdc,
+ &font_data->script_cache,
+ &items[i].a,
+ script_tag,
+ language_tag,
+ range_char_counts,
+ range_properties,
+ range_count,
+ wchars + chars_offset,
+ item_chars_len,
+ glyphs_size - glyphs_offset,
+ /* out */
+ log_clusters + chars_offset,
+ char_props + chars_offset,
+ glyphs + glyphs_offset,
+ glyph_props + glyphs_offset,
+ (int *) &glyphs_len);
+
+ if (unlikely (items[i].a.fNoGlyphIndex))
+ FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
+ if (unlikely (hr == E_OUTOFMEMORY))
+ {
+ buffer->ensure (buffer->allocated * 2);
+ if (buffer->in_error)
+ FAIL ("Buffer resize failed");
+ goto retry;
+ }
+ if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT))
+ FAIL ("ScriptShapeOpenType() failed: Font doesn't support script");
+ if (unlikely (FAILED (hr)))
+ FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
+
+ hr = ScriptPlaceOpenType (font_data->hdc,
+ &font_data->script_cache,
+ &items[i].a,
+ script_tag,
+ language_tag,
+ range_char_counts,
+ range_properties,
+ range_count,
+ wchars + chars_offset,
+ log_clusters + chars_offset,
+ char_props + chars_offset,
+ item_chars_len,
+ glyphs + glyphs_offset,
+ glyph_props + glyphs_offset,
+ glyphs_len,
+ /* out */
+ advances + glyphs_offset,
+ offsets + glyphs_offset,
+ NULL);
+ if (unlikely (FAILED (hr)))
+ FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
+
+ glyphs_offset += glyphs_len;
+ }
+ glyphs_len = glyphs_offset;
+
+ /* 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++)
+ 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);
+ }
+ if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
+ for (unsigned int i = 1; i < glyphs_len; i++)
+ if (!glyph_props[i].sva.fClusterStart)
+ vis_clusters[i] = vis_clusters[i - 1];
+ } else {
+ for (int i = glyphs_len - 2; i >= 0; i--)
+ if (!glyph_props[i].sva.fClusterStart)
+ vis_clusters[i] = vis_clusters[i + 1];
+ }
+
+#undef utf16_index
+
+ buffer->ensure (glyphs_len);
+ if (buffer->in_error)
+ FAIL ("Buffer in error");
+
+#undef FAIL
+
+ /* Set glyph infos */
+ buffer->len = 0;
+ for (unsigned int i = 0; i < glyphs_len; i++)
+ {
+ hb_glyph_info_t *info = &buffer->info[buffer->len++];
+
+ info->codepoint = glyphs[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].du;
+ info->var2.u32 = offsets[i].dv;
+ }
+
+ /* Set glyph positions */
+ buffer->clear_positions ();
+ for (unsigned int i = 0; i < glyphs_len; 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 = info->var1.u32;
+ pos->y_offset = info->var2.u32;
+ }
+
+ /* Wow, done! */
+ return TRUE;
+}
+
+
diff --git a/third_party/harfbuzz-ng/src/hb-blob-private.h b/third_party/harfbuzz-ng/src/hb-uniscribe.h
index 92109ed..dbcacd7 100644
--- a/third_party/harfbuzz-ng/src/hb-blob-private.h
+++ b/third_party/harfbuzz-ng/src/hb-uniscribe.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -21,39 +21,35 @@
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
- * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_BLOB_PRIVATE_H
-#define HB_BLOB_PRIVATE_H
+#ifndef HB_UNISCRIBE_H
+#define HB_UNISCRIBE_H
-#include "hb-private.h"
+#include "hb-common.h"
+#include "hb-shape.h"
-#include "hb-blob.h"
+#define _WIN32_WINNT 0x0500
+#include <windows.h>
HB_BEGIN_DECLS
-struct _hb_blob_t {
- hb_reference_count_t ref_count;
+hb_bool_t
+hb_uniscribe_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shaper_options);
- unsigned int length;
+LOGFONTW *
+hb_uniscribe_font_get_logfontw (hb_font_t *font);
- hb_mutex_t lock;
- /* the rest are protected by lock */
-
- unsigned int lock_count;
- hb_memory_mode_t mode;
-
- const char *data;
-
- hb_destroy_func_t destroy;
- void *user_data;
-};
-
-extern HB_INTERNAL hb_blob_t _hb_blob_nil;
+HFONT
+hb_uniscribe_font_get_hfont (hb_font_t *font);
HB_END_DECLS
-#endif /* HB_BLOB_PRIVATE_H */
+#endif /* HB_UNISCRIBE_H */
diff --git a/third_party/harfbuzz-ng/src/hb-common.c b/third_party/harfbuzz-ng/src/hb-version.h
index 74f8933..c1e3cab 100644
--- a/third_party/harfbuzz-ng/src/hb-common.c
+++ b/third_party/harfbuzz-ng/src/hb-version.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright © 2011 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -21,27 +21,42 @@
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
- * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
*/
-#include "hb-private.h"
+#ifndef HB_VERSION_H
+#define HB_VERSION_H
+
+#include "hb-common.h"
HB_BEGIN_DECLS
-hb_tag_t
-hb_tag_from_string (const char *s)
-{
- char tag[4];
- unsigned int i;
+#define HB_VERSION_MAJOR 0
+#define HB_VERSION_MINOR 7
+#define HB_VERSION_MICRO 0
+
+#define HB_VERSION_STRING "0.7.0"
+
+#define HB_VERSION_CHECK(major,minor,micro) \
+ ((major)*10000+(minor)*100+(micro) >= \
+ HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
- for (i = 0; i < 4 && s[i]; i++)
- tag[i] = s[i];
- for (; i < 4; i++)
- tag[i] = ' ';
- return HB_TAG_STR (tag);
-}
+void
+hb_version (unsigned int *major,
+ unsigned int *minor,
+ unsigned int *micro);
+
+const char *
+hb_version_string (void);
+
+hb_bool_t
+hb_version_check (unsigned int major,
+ unsigned int minor,
+ unsigned int micro);
HB_END_DECLS
+
+#endif /* HB_VERSION_H */
diff --git a/third_party/harfbuzz-ng/src/hb.h b/third_party/harfbuzz-ng/src/hb.h
index 691adee..0a2ebd9 100644
--- a/third_party/harfbuzz-ng/src/hb.h
+++ b/third_party/harfbuzz-ng/src/hb.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright © 2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -31,9 +31,9 @@
#include "hb-buffer.h"
#include "hb-common.h"
#include "hb-font.h"
-#include "hb-language.h"
#include "hb-shape.h"
#include "hb-unicode.h"
+#include "hb-version.h"
HB_BEGIN_DECLS
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/main.cc b/third_party/harfbuzz-ng/src/main.cc
index 8126dae..442b1b9 100644
--- a/third_party/harfbuzz-ng/src/main.cc
+++ b/third_party/harfbuzz-ng/src/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
@@ -24,9 +24,9 @@
* Red Hat Author(s): Behdad Esfahbod
*/
-#define HB_OT_LAYOUT_CC
+#include "hb-mutex-private.hh"
#include "hb-open-file-private.hh"
-#include "hb-ot-layout-gdef-private.hh"
+#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsubgpos-private.hh"
#ifdef HAVE_GLIB
@@ -35,7 +35,6 @@
#include <stdlib.h>
#include <stdio.h>
-HB_BEGIN_DECLS
int
@@ -193,4 +192,3 @@ main (int argc, char **argv)
}
-HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/test.c b/third_party/harfbuzz-ng/src/test.c
deleted file mode 100644
index 836dd4c..0000000
--- a/third_party/harfbuzz-ng/src/test.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "hb.h"
-
-#ifdef HAVE_GLIB
-#include <glib.h>
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-
-HB_BEGIN_DECLS
-
-
-int
-main (int argc, char **argv)
-{
- hb_blob_t *blob = NULL;
- hb_face_t *face = NULL;
-
- if (argc != 2) {
- fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
- exit (1);
- }
-
- /* Create the blob */
- {
- const char *font_data;
- unsigned int len;
- hb_destroy_func_t destroy;
- void *user_data;
-
-#ifdef HAVE_GLIB
- GMappedFile *mf = g_mapped_file_new (argv[1], FALSE, NULL);
- font_data = g_mapped_file_get_contents (mf);
- len = g_mapped_file_get_length (mf);
- destroy = (hb_destroy_func_t) g_mapped_file_unref;
- user_data = (void *) mf;
-#else
- FILE *f = fopen (argv[1], "rb");
- fseek (f, 0, SEEK_END);
- len = ftell (f);
- fseek (f, 0, SEEK_SET);
- font_data = (const char *) malloc (len);
- if (!font_data) len = 0;
- len = fread ((char *) font_data, 1, len, f);
- destroy = free;
- user_data = (void *) font_data;
- fclose (f);
-#endif
-
- blob = hb_blob_create (font_data, len,
- HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
- destroy, user_data);
- }
-
- /* Create the face */
- face = hb_face_create_for_data (blob, 0 /* first face */);
-
- /* So, what now? */
-
- hb_face_destroy (face);
- hb_blob_destroy (blob);
-
- return 0;
-}
diff --git a/third_party/harfbuzz/harfbuzz.gyp b/third_party/harfbuzz/harfbuzz.gyp
index eb6cc53..7100d73e 100644
--- a/third_party/harfbuzz/harfbuzz.gyp
+++ b/third_party/harfbuzz/harfbuzz.gyp
@@ -71,10 +71,10 @@
'target_name': 'harfbuzz',
'type': 'none',
'dependencies': [
- '../harfbuzz-ng/harfbuzz.gyp:harfbuzz'
+ '../harfbuzz-ng/harfbuzz.gyp:harfbuzz-ng'
],
'export_dependent_settings': [
- '../harfbuzz-ng/harfbuzz.gyp:harfbuzz'
+ '../harfbuzz-ng/harfbuzz.gyp:harfbuzz-ng'
],
}
]