mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-26 23:23:33 +00:00
Bug 782908 - Updated harfbuzz to current version r=jfkthame
This commit is contained in:
parent
409cf6bf73
commit
00b438ec82
@ -1,4 +1,4 @@
|
||||
gfx/harfbuzz status as of 2012-08-06:
|
||||
gfx/harfbuzz status as of 2012-08-16:
|
||||
|
||||
This directory contains the "harfbuzz-ng" source from the 'master' branch of
|
||||
git://anongit.freedesktop.org/git/harfbuzz.
|
||||
|
@ -87,6 +87,8 @@ HBSOURCES += \
|
||||
hb-ot-shape-complex-private.hh \
|
||||
hb-ot-shape-normalize-private.hh \
|
||||
hb-ot-shape-normalize.cc \
|
||||
hb-ot-shape-fallback-private.hh \
|
||||
hb-ot-shape-fallback.cc \
|
||||
hb-ot-shape-private.hh \
|
||||
$(NULL)
|
||||
HBHEADERS += \
|
||||
@ -162,16 +164,36 @@ endif
|
||||
DIST_SUBDIRS += hb-old
|
||||
|
||||
|
||||
|
||||
# Put the library together
|
||||
|
||||
if OS_WIN32
|
||||
export_symbols = -export-symbols harfbuzz.def
|
||||
harfbuzz_def_dependency = harfbuzz.def
|
||||
endif
|
||||
|
||||
# Use a C linker, not C++; Don't link to libstdc++
|
||||
libharfbuzz_la_LINK = $(LINK) $(libharfbuzz_la_LDFLAGS)
|
||||
libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS)
|
||||
nodist_libharfbuzz_la_SOURCES = $(nodist_HBSOURCES)
|
||||
libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
|
||||
libharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
|
||||
libharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) $(export_symbols) -no-undefined
|
||||
libharfbuzz_la_LIBADD = $(HBLIBS)
|
||||
libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
|
||||
pkginclude_HEADERS = $(HBHEADERS)
|
||||
nodist_pkginclude_HEADERS = hb-version.h
|
||||
|
||||
CLEANFILES += harfbuzz.def
|
||||
harfbuzz.def: $(HBHEADERS)
|
||||
$(AM_V_GEN) (echo EXPORTS; \
|
||||
(cat $^ || echo 'hb_ERROR ()' ) | \
|
||||
$(EGREP) '^hb_.* \(' | \
|
||||
sed -e 's/ (.*//' | \
|
||||
LANG=C sort; \
|
||||
echo LIBRARY libharfbuzz-$(HB_VERSION_MAJOR).dll; \
|
||||
) >"$@.tmp"
|
||||
@ ! grep -q hb_ERROR "$@.tmp" && mv "$@.tmp" "$@" || ($(RM) "$@"; false)
|
||||
|
||||
|
||||
GENERATORS = \
|
||||
gen-arabic-table.py \
|
||||
@ -219,6 +241,7 @@ test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
||||
dist_check_SCRIPTS = \
|
||||
check-c-linkage-decls.sh \
|
||||
check-header-guards.sh \
|
||||
check-exported-symbols.sh \
|
||||
check-includes.sh \
|
||||
check-internal-symbols.sh \
|
||||
check-static-inits.sh \
|
||||
|
@ -49,6 +49,7 @@ CPPSRCS = \
|
||||
hb-ot-shape-complex-arabic.cc \
|
||||
hb-ot-shape-complex-indic.cc \
|
||||
hb-ot-shape-complex-misc.cc \
|
||||
hb-ot-shape-fallback.cc \
|
||||
hb-ot-shape-normalize.cc \
|
||||
hb-ot-shape.cc \
|
||||
hb-ot-tag.cc \
|
||||
@ -71,7 +72,6 @@ EXPORTS_harfbuzz = \
|
||||
hb-ot.h \
|
||||
hb-ot-layout.h \
|
||||
hb-ot-tag.h \
|
||||
hb-ot-shape.h \
|
||||
hb-set.h \
|
||||
hb-shape.h \
|
||||
hb-shape-plan.h \
|
||||
|
40
gfx/harfbuzz/src/check-exported-symbols.sh
Executable file
40
gfx/harfbuzz/src/check-exported-symbols.sh
Executable file
@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
test -z "$srcdir" && srcdir=.
|
||||
test -z "$MAKE" && MAKE=make
|
||||
stat=0
|
||||
|
||||
if which nm 2>/dev/null >/dev/null; then
|
||||
:
|
||||
else
|
||||
echo "check-exported-symbols.sh: 'nm' not found; skipping test"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
defs="harfbuzz.def"
|
||||
$MAKE $defs > /dev/null
|
||||
tested=false
|
||||
for def in $defs; do
|
||||
lib=`echo "$def" | sed 's/[.]def$//;s@.*/@@'`
|
||||
so=.libs/lib${lib}.so
|
||||
if test -f "$so"; then
|
||||
echo "Checking that $so has the same symbol list as $def"
|
||||
{
|
||||
echo EXPORTS
|
||||
nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' T _fini\>\| T _init\>' | cut -d' ' -f3
|
||||
stat=1
|
||||
# cheat: copy the last line from the def file!
|
||||
tail -n1 "$def"
|
||||
} | diff "$def" - >&2 || stat=1
|
||||
tested=true
|
||||
fi
|
||||
done
|
||||
if ! $tested; then
|
||||
echo "check-exported-symbols.sh: libharfbuzz shared library not found; skipping test"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
exit $stat
|
@ -14,18 +14,12 @@ else
|
||||
exit 77
|
||||
fi
|
||||
|
||||
if which c++filt 2>/dev/null >/dev/null; then
|
||||
cplusplusfilt=c++filt
|
||||
else
|
||||
cplusplusfilt=cat
|
||||
fi
|
||||
|
||||
tested=false
|
||||
for suffix in so; do
|
||||
so=.libs/libharfbuzz.$suffix
|
||||
for suffix in .so; do
|
||||
so=`echo .libs/libharfbuzz$suffix`
|
||||
if test -f "$so"; then
|
||||
echo "Checking that we are not exposing internal symbols"
|
||||
if nm $so | grep ' [TW] ' | $cplusplusfilt | grep -v ' T _fini\>\| T _init\>\| T hb_'; then
|
||||
if nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' T _fini\>\| T _init\>\| T hb_'; then
|
||||
echo "Ouch, internal symbols exposed"
|
||||
stat=1
|
||||
fi
|
||||
|
@ -14,8 +14,14 @@ else
|
||||
exit 77
|
||||
fi
|
||||
|
||||
OBJS=.libs/*.o
|
||||
if test "x`echo $OBJS`" = "x$OBJS" 2>/dev/null >/dev/null; then
|
||||
echo "check-static-inits.sh: object files not found; skipping test"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
echo "Checking that no object file has static initializers"
|
||||
for obj in .libs/*.o; do
|
||||
for obj in $OBJS; do
|
||||
if objdump -t "$obj" | grep '[.]ctors'; then
|
||||
echo "Ouch, $obj has static initializers"
|
||||
stat=1
|
||||
@ -23,7 +29,7 @@ for obj in .libs/*.o; do
|
||||
done
|
||||
|
||||
echo "Checking that no object file has lazy static C++ constructors/destructors"
|
||||
for obj in .libs/*.o; do
|
||||
for obj in $OBJS; do
|
||||
if objdump -t "$obj" | grep '__c'; then
|
||||
echo "Ouch, $obj has lazy static C++ constructors/destructors"
|
||||
stat=1
|
||||
|
@ -64,14 +64,16 @@ hb_segment_properties_equal (const hb_segment_properties_t *a,
|
||||
}
|
||||
|
||||
|
||||
static inline long
|
||||
#if 0
|
||||
static inline unsigned int
|
||||
hb_segment_properties_hash (const hb_segment_properties_t *p)
|
||||
{
|
||||
/* TODO improve */
|
||||
return (long) p->direction +
|
||||
(long) p->script +
|
||||
(long) p->language;
|
||||
return (unsigned int) p->direction +
|
||||
(unsigned int) p->script +
|
||||
(intptr_t) (p->language);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -37,8 +37,6 @@
|
||||
#define HB_DEBUG_BUFFER (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
#define _HB_BUFFER_UNICODE_FUNCS_DEFAULT (const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_default))
|
||||
|
||||
/* Here is how the buffer works internally:
|
||||
*
|
||||
* There are two info pointers: info and out_info. They always have
|
||||
@ -144,7 +142,7 @@ hb_buffer_t::reset (void)
|
||||
return;
|
||||
|
||||
hb_unicode_funcs_destroy (unicode);
|
||||
unicode = _HB_BUFFER_UNICODE_FUNCS_DEFAULT;
|
||||
unicode = hb_unicode_funcs_get_default ();
|
||||
|
||||
hb_segment_properties_t default_props = _HB_BUFFER_PROPS_DEFAULT;
|
||||
props = default_props;
|
||||
@ -552,7 +550,7 @@ hb_buffer_get_empty (void)
|
||||
static const hb_buffer_t _hb_buffer_nil = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
_HB_BUFFER_UNICODE_FUNCS_DEFAULT,
|
||||
const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
|
||||
_HB_BUFFER_PROPS_DEFAULT,
|
||||
|
||||
true, /* in_error */
|
||||
@ -608,7 +606,8 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
|
||||
return;
|
||||
|
||||
if (!unicode)
|
||||
unicode = _HB_BUFFER_UNICODE_FUNCS_DEFAULT;
|
||||
unicode = hb_unicode_funcs_get_default ();
|
||||
|
||||
|
||||
hb_unicode_funcs_reference (unicode);
|
||||
hb_unicode_funcs_destroy (buffer->unicode);
|
||||
|
@ -201,8 +201,8 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
|
||||
|
||||
/*
|
||||
* NOT IMPLEMENTED
|
||||
void
|
||||
hb_buffer_normalize_characters (hb_buffer_t *buffer);
|
||||
void
|
||||
hb_buffer_normalize_characters (hb_buffer_t *buffer);
|
||||
*/
|
||||
|
||||
|
||||
|
@ -238,17 +238,12 @@ hb_language_to_string (hb_language_t language)
|
||||
hb_language_t
|
||||
hb_language_get_default (void)
|
||||
{
|
||||
static hb_language_t default_language;
|
||||
static hb_language_t default_language = HB_LANGUAGE_INVALID;
|
||||
|
||||
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);
|
||||
hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
|
||||
if (unlikely (language == HB_LANGUAGE_INVALID)) {
|
||||
language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
|
||||
hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
|
||||
}
|
||||
|
||||
return default_language;
|
||||
|
@ -43,8 +43,6 @@
|
||||
# endif /* !__cplusplus */
|
||||
#endif
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
#if !defined (HB_DONT_DEFINE_STDINT)
|
||||
|
||||
#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
|
||||
@ -69,6 +67,8 @@ typedef unsigned __int64 uint64_t;
|
||||
|
||||
#endif
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
typedef int hb_bool_t;
|
||||
|
||||
@ -96,7 +96,8 @@ typedef uint32_t hb_tag_t;
|
||||
#define HB_TAG_NONE HB_TAG(0,0,0,0)
|
||||
|
||||
/* len=-1 means str is NUL-terminated */
|
||||
hb_tag_t hb_tag_from_string (const char *str, int len);
|
||||
hb_tag_t
|
||||
hb_tag_from_string (const char *str, int len);
|
||||
|
||||
|
||||
/* hb_direction_t */
|
||||
|
@ -141,15 +141,15 @@ _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
|
||||
struct hb_coretext_shaper_shape_plan_data_t {};
|
||||
|
||||
hb_coretext_shaper_shape_plan_data_t *
|
||||
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
|
||||
const hb_feature_t *user_features,
|
||||
unsigned int num_user_features)
|
||||
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||
const hb_feature_t *user_features HB_UNUSED,
|
||||
unsigned int num_user_features HB_UNUSED)
|
||||
{
|
||||
return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data)
|
||||
_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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_FALLBACK_SHAPE_PRIVATE_HH
|
||||
#define HB_FALLBACK_SHAPE_PRIVATE_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-shape.h"
|
||||
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_FALLBACK_SHAPE_PRIVATE_HH */
|
@ -71,15 +71,15 @@ _hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data)
|
||||
struct hb_fallback_shaper_shape_plan_data_t {};
|
||||
|
||||
hb_fallback_shaper_shape_plan_data_t *
|
||||
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
|
||||
const hb_feature_t *user_features,
|
||||
unsigned int num_user_features)
|
||||
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||
const hb_feature_t *user_features HB_UNUSED,
|
||||
unsigned int num_user_features HB_UNUSED)
|
||||
{
|
||||
return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data)
|
||||
_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data HB_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -94,12 +94,12 @@ struct hb_face_t {
|
||||
|
||||
hb_bool_t immutable;
|
||||
|
||||
hb_reference_table_func_t reference_table;
|
||||
hb_reference_table_func_t reference_table_func;
|
||||
void *user_data;
|
||||
hb_destroy_func_t destroy;
|
||||
|
||||
unsigned int index;
|
||||
unsigned int upem;
|
||||
mutable unsigned int upem;
|
||||
|
||||
struct hb_shaper_data_t shaper_data;
|
||||
|
||||
@ -107,6 +107,31 @@ struct hb_face_t {
|
||||
hb_shape_plan_t *shape_plan;
|
||||
plan_node_t *next;
|
||||
} *shape_plans;
|
||||
|
||||
|
||||
inline hb_blob_t *reference_table (hb_tag_t tag) const
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
|
||||
if (unlikely (!this || !reference_table_func))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
|
||||
if (unlikely (!blob))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
inline unsigned int get_upem (void) const
|
||||
{
|
||||
if (unlikely (!upem))
|
||||
load_upem ();
|
||||
return upem;
|
||||
}
|
||||
|
||||
private:
|
||||
HB_INTERNAL void load_upem (void) const;
|
||||
};
|
||||
|
||||
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
|
||||
@ -254,6 +279,7 @@ struct hb_font_t {
|
||||
inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
|
||||
char *name, unsigned int size)
|
||||
{
|
||||
if (size) *name = '\0';
|
||||
return klass->get.glyph_name (this, user_data,
|
||||
glyph,
|
||||
name, size,
|
||||
@ -263,6 +289,8 @@ struct hb_font_t {
|
||||
inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph)
|
||||
{
|
||||
*glyph = 0;
|
||||
if (len == -1) len = strlen (name);
|
||||
return klass->get.glyph_from_name (this, user_data,
|
||||
name, len,
|
||||
glyph,
|
||||
@ -377,6 +405,46 @@ struct hb_font_t {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Generates gidDDD if glyph has no name. */
|
||||
inline void
|
||||
glyph_to_string (hb_codepoint_t glyph,
|
||||
char *s, unsigned int size)
|
||||
{
|
||||
if (get_glyph_name (glyph, s, size)) return;
|
||||
|
||||
snprintf (s, size, "gid%u", glyph);
|
||||
}
|
||||
|
||||
/* Parses gidDDD and uniUUUU strings automatically. */
|
||||
inline hb_bool_t
|
||||
glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph)
|
||||
{
|
||||
if (get_glyph_from_name (s, len, glyph)) return true;
|
||||
|
||||
if (len == -1) len = strlen (s);
|
||||
|
||||
/* Straight glyph index. */
|
||||
if (hb_codepoint_parse (s, len, 10, glyph))
|
||||
return true;
|
||||
|
||||
if (len > 3)
|
||||
{
|
||||
/* gidDDD syntax for glyph indices. */
|
||||
if (0 == strncmp (s, "gid", 3) &&
|
||||
hb_codepoint_parse (s + 3, len - 3, 10, glyph))
|
||||
return true;
|
||||
|
||||
/* uniUUUU and other Unicode character indices. */
|
||||
hb_codepoint_t unichar;
|
||||
if (0 == strncmp (s, "uni", 3) &&
|
||||
hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
|
||||
get_glyph (unichar, 0, glyph))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
inline hb_position_t em_scale (int16_t v, int scale) { return v * (int64_t) scale / hb_face_get_upem (this->face); }
|
||||
|
@ -54,7 +54,7 @@ hb_font_get_glyph_nil (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return hb_font_get_glyph (font->parent, unicode, variation_selector, glyph);
|
||||
return font->parent->get_glyph (unicode, variation_selector, glyph);
|
||||
|
||||
*glyph = 0;
|
||||
return false;
|
||||
@ -67,7 +67,7 @@ hb_font_get_glyph_h_advance_nil (hb_font_t *font,
|
||||
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->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
|
||||
|
||||
return font->x_scale;
|
||||
}
|
||||
@ -79,7 +79,7 @@ hb_font_get_glyph_v_advance_nil (hb_font_t *font,
|
||||
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->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
|
||||
|
||||
return font->y_scale;
|
||||
}
|
||||
@ -93,7 +93,7 @@ hb_font_get_glyph_h_origin_nil (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent) {
|
||||
hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent, glyph, x, y);
|
||||
hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
@ -112,7 +112,7 @@ hb_font_get_glyph_v_origin_nil (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent) {
|
||||
hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent, glyph, x, y);
|
||||
hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
@ -130,7 +130,7 @@ hb_font_get_glyph_h_kerning_nil (hb_font_t *font,
|
||||
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 font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -143,7 +143,7 @@ hb_font_get_glyph_v_kerning_nil (hb_font_t *font,
|
||||
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 font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -156,9 +156,7 @@ hb_font_get_glyph_extents_nil (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent) {
|
||||
hb_bool_t ret = hb_font_get_glyph_extents (font->parent,
|
||||
glyph,
|
||||
extents);
|
||||
hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
|
||||
if (ret) {
|
||||
font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
|
||||
font->parent_scale_distance (&extents->width, &extents->height);
|
||||
@ -180,7 +178,7 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font,
|
||||
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);
|
||||
hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
@ -198,9 +196,9 @@ hb_font_get_glyph_name_nil (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return hb_font_get_glyph_name (font->parent, glyph, name, size);
|
||||
return font->parent->get_glyph_name (glyph, name, size);
|
||||
|
||||
snprintf (name, size, "gid%u", glyph);
|
||||
if (size) *name = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -212,7 +210,7 @@ hb_font_get_glyph_from_name_nil (hb_font_t *font,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->parent)
|
||||
return hb_font_get_glyph_from_name (font->parent, name, len, glyph);
|
||||
return font->parent->get_glyph_from_name (name, len, glyph);
|
||||
|
||||
*glyph = 0;
|
||||
return false;
|
||||
@ -488,6 +486,24 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
|
||||
return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
|
||||
}
|
||||
|
||||
/* Generates gidDDD if glyph has no name. */
|
||||
void
|
||||
hb_font_glyph_to_string (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
char *s, unsigned int size)
|
||||
{
|
||||
font->glyph_to_string (glyph, s, size);
|
||||
}
|
||||
|
||||
/* Parses gidDDD and uniUUUU strings automatically. */
|
||||
hb_bool_t
|
||||
hb_font_glyph_from_string (hb_font_t *font,
|
||||
const char *s, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph)
|
||||
{
|
||||
return font->glyph_from_string (s, len, glyph);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hb_face_t
|
||||
@ -498,7 +514,7 @@ static const hb_face_t _hb_face_nil = {
|
||||
|
||||
true, /* immutable */
|
||||
|
||||
NULL, /* reference_table */
|
||||
NULL, /* reference_table_func */
|
||||
NULL, /* user_data */
|
||||
NULL, /* destroy */
|
||||
|
||||
@ -516,19 +532,19 @@ static const hb_face_t _hb_face_nil = {
|
||||
|
||||
|
||||
hb_face_t *
|
||||
hb_face_create_for_tables (hb_reference_table_func_t reference_table,
|
||||
hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy)
|
||||
{
|
||||
hb_face_t *face;
|
||||
|
||||
if (!reference_table || !(face = hb_object_create<hb_face_t> ())) {
|
||||
if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
|
||||
if (destroy)
|
||||
destroy (user_data);
|
||||
return hb_face_get_empty ();
|
||||
}
|
||||
|
||||
face->reference_table = reference_table;
|
||||
face->reference_table_func = reference_table_func;
|
||||
face->user_data = user_data;
|
||||
face->destroy = destroy;
|
||||
|
||||
@ -624,9 +640,6 @@ hb_face_destroy (hb_face_t *face)
|
||||
{
|
||||
if (!hb_object_destroy (face)) return;
|
||||
|
||||
/* The cached shape_plans think they have a reference on us, and
|
||||
* try to release it. Make sure that doesn't mess up. */
|
||||
face->header.ref_count.ref_count = HB_REFERENCE_COUNT_INVALID_VALUE;
|
||||
for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
|
||||
{
|
||||
hb_face_t::plan_node_t *next = node->next;
|
||||
@ -682,22 +695,13 @@ hb_blob_t *
|
||||
hb_face_reference_table (hb_face_t *face,
|
||||
hb_tag_t tag)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
|
||||
if (unlikely (!face || !face->reference_table))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
blob = face->reference_table (face, tag, face->user_data);
|
||||
if (unlikely (!blob))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
return blob;
|
||||
return face->reference_table (tag);
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
hb_face_reference_blob (hb_face_t *face)
|
||||
{
|
||||
return hb_face_reference_table (face, HB_TAG_NONE);
|
||||
return face->reference_table (HB_TAG_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -729,13 +733,17 @@ hb_face_set_upem (hb_face_t *face,
|
||||
unsigned int
|
||||
hb_face_get_upem (hb_face_t *face)
|
||||
{
|
||||
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;
|
||||
return face->get_upem ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hb_face_t::load_upem (void) const
|
||||
{
|
||||
hb_blob_t *head_blob = Sanitizer<head>::sanitize (reference_table (HB_OT_TAG_head));
|
||||
const head *head_table = Sanitizer<head>::lock_instance (head_blob);
|
||||
upem = head_table->get_upem ();
|
||||
hb_blob_destroy (head_blob);
|
||||
}
|
||||
|
||||
|
||||
|
@ -52,7 +52,7 @@ typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag
|
||||
|
||||
/* calls destroy() when not needing user_data anymore */
|
||||
hb_face_t *
|
||||
hb_face_create_for_tables (hb_reference_table_func_t reference_table,
|
||||
hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
|
||||
void *user_data,
|
||||
hb_destroy_func_t destroy);
|
||||
|
||||
@ -143,7 +143,8 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs);
|
||||
hb_bool_t
|
||||
hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
|
||||
|
||||
/* funcs */
|
||||
|
||||
/* glyph extents */
|
||||
|
||||
typedef struct hb_glyph_extents_t
|
||||
{
|
||||
@ -346,6 +347,17 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
|
||||
hb_direction_t direction,
|
||||
hb_position_t *x, hb_position_t *y);
|
||||
|
||||
/* Generates gidDDD if glyph has no name. */
|
||||
void
|
||||
hb_font_glyph_to_string (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
char *s, unsigned int size);
|
||||
/* Parses gidDDD and uniUUUU strings automatically. */
|
||||
hb_bool_t
|
||||
hb_font_glyph_from_string (hb_font_t *font,
|
||||
const char *s, int len, /* -1 means nul-terminated */
|
||||
hb_codepoint_t *glyph);
|
||||
|
||||
|
||||
/*
|
||||
* hb_font_t
|
||||
|
@ -201,7 +201,7 @@ hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
|
||||
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;
|
||||
extents->height = -ft_face->glyph->metrics.height;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -464,6 +464,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
||||
|
||||
FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
|
||||
|
||||
assert (font->y_scale >= 0);
|
||||
FT_Set_Char_Size (ft_face,
|
||||
font->x_scale, font->y_scale,
|
||||
0, 0);
|
||||
|
@ -250,9 +250,6 @@ hb_glib_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
/* 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;
|
||||
int len;
|
||||
@ -367,22 +364,21 @@ hb_glib_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
|
||||
return utf8_decomposed_len;
|
||||
}
|
||||
|
||||
extern HB_INTERNAL const hb_unicode_funcs_t _hb_glib_unicode_funcs;
|
||||
const 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)
|
||||
{
|
||||
static const 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
|
||||
}
|
||||
};
|
||||
|
||||
return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
#include "hb-gobject.h"
|
||||
|
||||
/* enumerations from "../../src/hb-blob.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)
|
||||
@ -64,7 +64,7 @@ hb_memory_mode_t_hb_memory_mode_t_get_type (void)
|
||||
return g_define_type_id__volatile;
|
||||
}
|
||||
|
||||
/* enumerations from "../../src/hb-common.h" */
|
||||
/* 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)
|
||||
@ -89,55 +89,6 @@ hb_direction_t_hb_direction_t_get_type (void)
|
||||
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)
|
||||
@ -261,6 +212,132 @@ hb_script_t_hb_script_t_get_type (void)
|
||||
return g_define_type_id__volatile;
|
||||
}
|
||||
|
||||
/* enumerations from "hb-unicode.h" */
|
||||
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_unicode_combining_class_t_hb_unicode_combining_class_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_COMBINING_CLASS_NOT_REORDERED, "HB_UNICODE_COMBINING_CLASS_NOT_REORDERED", "not-reordered" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_OVERLAY, "HB_UNICODE_COMBINING_CLASS_OVERLAY", "overlay" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_NUKTA, "HB_UNICODE_COMBINING_CLASS_NUKTA", "nukta" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_KANA_VOICING, "HB_UNICODE_COMBINING_CLASS_KANA_VOICING", "kana-voicing" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_VIRAMA, "HB_UNICODE_COMBINING_CLASS_VIRAMA", "virama" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC10, "HB_UNICODE_COMBINING_CLASS_CCC10", "ccc10" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC11, "HB_UNICODE_COMBINING_CLASS_CCC11", "ccc11" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC12, "HB_UNICODE_COMBINING_CLASS_CCC12", "ccc12" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC13, "HB_UNICODE_COMBINING_CLASS_CCC13", "ccc13" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC14, "HB_UNICODE_COMBINING_CLASS_CCC14", "ccc14" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC15, "HB_UNICODE_COMBINING_CLASS_CCC15", "ccc15" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC16, "HB_UNICODE_COMBINING_CLASS_CCC16", "ccc16" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC17, "HB_UNICODE_COMBINING_CLASS_CCC17", "ccc17" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC18, "HB_UNICODE_COMBINING_CLASS_CCC18", "ccc18" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC19, "HB_UNICODE_COMBINING_CLASS_CCC19", "ccc19" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC20, "HB_UNICODE_COMBINING_CLASS_CCC20", "ccc20" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC21, "HB_UNICODE_COMBINING_CLASS_CCC21", "ccc21" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC22, "HB_UNICODE_COMBINING_CLASS_CCC22", "ccc22" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC23, "HB_UNICODE_COMBINING_CLASS_CCC23", "ccc23" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC24, "HB_UNICODE_COMBINING_CLASS_CCC24", "ccc24" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC25, "HB_UNICODE_COMBINING_CLASS_CCC25", "ccc25" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC26, "HB_UNICODE_COMBINING_CLASS_CCC26", "ccc26" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC27, "HB_UNICODE_COMBINING_CLASS_CCC27", "ccc27" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC28, "HB_UNICODE_COMBINING_CLASS_CCC28", "ccc28" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC29, "HB_UNICODE_COMBINING_CLASS_CCC29", "ccc29" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC30, "HB_UNICODE_COMBINING_CLASS_CCC30", "ccc30" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC31, "HB_UNICODE_COMBINING_CLASS_CCC31", "ccc31" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC32, "HB_UNICODE_COMBINING_CLASS_CCC32", "ccc32" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC33, "HB_UNICODE_COMBINING_CLASS_CCC33", "ccc33" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC34, "HB_UNICODE_COMBINING_CLASS_CCC34", "ccc34" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC35, "HB_UNICODE_COMBINING_CLASS_CCC35", "ccc35" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC36, "HB_UNICODE_COMBINING_CLASS_CCC36", "ccc36" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC84, "HB_UNICODE_COMBINING_CLASS_CCC84", "ccc84" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC91, "HB_UNICODE_COMBINING_CLASS_CCC91", "ccc91" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC103, "HB_UNICODE_COMBINING_CLASS_CCC103", "ccc103" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC107, "HB_UNICODE_COMBINING_CLASS_CCC107", "ccc107" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC118, "HB_UNICODE_COMBINING_CLASS_CCC118", "ccc118" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC122, "HB_UNICODE_COMBINING_CLASS_CCC122", "ccc122" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC129, "HB_UNICODE_COMBINING_CLASS_CCC129", "ccc129" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC130, "HB_UNICODE_COMBINING_CLASS_CCC130", "ccc130" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_CCC133, "HB_UNICODE_COMBINING_CLASS_CCC133", "ccc133" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT, "HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT", "attached-below-left" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW, "HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW", "attached-below" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE, "HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE", "attached-above" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT, "HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT", "attached-above-right" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_BELOW_LEFT, "HB_UNICODE_COMBINING_CLASS_BELOW_LEFT", "below-left" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_BELOW, "HB_UNICODE_COMBINING_CLASS_BELOW", "below" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT, "HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT", "below-right" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_LEFT, "HB_UNICODE_COMBINING_CLASS_LEFT", "left" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_RIGHT, "HB_UNICODE_COMBINING_CLASS_RIGHT", "right" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT, "HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT", "above-left" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_ABOVE, "HB_UNICODE_COMBINING_CLASS_ABOVE", "above" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT, "HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT", "above-right" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW, "HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW", "double-below" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE, "HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE", "double-above" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT, "HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT", "iota-subscript" },
|
||||
{ HB_UNICODE_COMBINING_CLASS_INVALID, "HB_UNICODE_COMBINING_CLASS_INVALID", "invalid" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
GType g_define_type_id =
|
||||
g_enum_register_static (g_intern_static_string ("hb_unicode_combining_class_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 */
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright © 2011 Martin Hosken
|
||||
* Copyright © 2011 SIL International
|
||||
* Copyright © 2011 Google, Inc.
|
||||
* Copyright © 2011,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
@ -26,79 +26,68 @@
|
||||
* 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"
|
||||
#define HB_SHAPER graphite2
|
||||
#define hb_graphite2_shaper_font_data_t gr_font
|
||||
#include "hb-shaper-impl-private.hh"
|
||||
|
||||
#include <graphite2/Font.h>
|
||||
#include <graphite2/Segment.h>
|
||||
|
||||
#include "hb-graphite2.h"
|
||||
|
||||
struct hb_gr_cluster_t {
|
||||
unsigned int base_char;
|
||||
unsigned int num_chars;
|
||||
unsigned int base_glyph;
|
||||
unsigned int num_glyphs;
|
||||
#include "hb-ot-tag.h"
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font)
|
||||
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
*/
|
||||
|
||||
typedef struct hb_graphite2_tablelist_t {
|
||||
struct hb_graphite2_tablelist_t *next;
|
||||
hb_blob_t *blob;
|
||||
unsigned int tag;
|
||||
} hb_graphite2_tablelist_t;
|
||||
|
||||
struct hb_graphite2_shaper_face_data_t {
|
||||
hb_face_t *face;
|
||||
gr_face *grface;
|
||||
hb_graphite2_tablelist_t *tlist;
|
||||
};
|
||||
|
||||
|
||||
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)
|
||||
static const void *hb_graphite2_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;
|
||||
hb_graphite2_shaper_face_data_t *face_data = (hb_graphite2_shaper_face_data_t *) data;
|
||||
hb_graphite2_tablelist_t *tlist = face_data->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;
|
||||
hb_blob_t *blob = NULL;
|
||||
|
||||
if (!face->face)
|
||||
return NULL;
|
||||
hb_blob_t *blob = hb_face_reference_table (face->face, tag);
|
||||
for (hb_graphite2_tablelist_t *p = tlist; p; p = p->next)
|
||||
if (p->tag == tag) {
|
||||
blob = p->blob;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pl || pl->blob)
|
||||
if (unlikely (!blob))
|
||||
{
|
||||
p = (hb_gr_tablelist_t *) malloc (sizeof (hb_gr_tablelist_t));
|
||||
if (!p) {
|
||||
blob = face_data->face->reference_table (tag);
|
||||
|
||||
hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) calloc (1, sizeof (hb_graphite2_tablelist_t));
|
||||
if (unlikely (!p)) {
|
||||
hb_blob_destroy (blob);
|
||||
return NULL;
|
||||
}
|
||||
p->next = NULL;
|
||||
if (pl)
|
||||
pl->next = p;
|
||||
else
|
||||
face->tlist = p;
|
||||
pl = p;
|
||||
p->blob = blob;
|
||||
p->tag = tag;
|
||||
|
||||
/* TODO Not thread-safe, but fairly harmless.
|
||||
* We can do the double-chcked pointer cmpexch thing here. */
|
||||
p->next = face_data->tlist;
|
||||
face_data->tlist = p;
|
||||
}
|
||||
pl->blob = blob;
|
||||
pl->tag = tag;
|
||||
|
||||
unsigned int tlen;
|
||||
const char *d = hb_blob_get_data (blob, &tlen);
|
||||
@ -106,147 +95,143 @@ static const void *hb_gr_get_table (const void *data, unsigned int tag, size_t *
|
||||
return d;
|
||||
}
|
||||
|
||||
static float hb_gr_get_advance (const void *hb_font, unsigned short gid)
|
||||
hb_graphite2_shaper_face_data_t *
|
||||
_hb_graphite2_shaper_face_data_create (hb_face_t *face)
|
||||
{
|
||||
return ((hb_font_t *) font)->get_glyph_h_advance (gid);
|
||||
hb_blob_t *silf_blob = face->reference_table (HB_GRAPHITE2_TAG_SILF);
|
||||
/* Umm, we just reference the table to check whether it exists.
|
||||
* Maybe add better API for this? */
|
||||
if (!hb_blob_get_length (silf_blob))
|
||||
{
|
||||
hb_blob_destroy (silf_blob);
|
||||
return NULL;
|
||||
}
|
||||
hb_blob_destroy (silf_blob);
|
||||
|
||||
hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t));
|
||||
if (unlikely (!data))
|
||||
hb_blob_destroy (silf_blob);
|
||||
|
||||
data->face = face;
|
||||
data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_default);
|
||||
|
||||
if (unlikely (!data->grface)) {
|
||||
free (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void _hb_gr_face_data_destroy (void *data)
|
||||
void
|
||||
_hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
|
||||
{
|
||||
hb_gr_face_data_t *f = (hb_gr_face_data_t *) data;
|
||||
hb_gr_tablelist_t *tlist = f->tlist;
|
||||
hb_graphite2_tablelist_t *tlist = data->tlist;
|
||||
|
||||
while (tlist)
|
||||
{
|
||||
hb_gr_tablelist_t *old = tlist;
|
||||
hb_graphite2_tablelist_t *old = tlist;
|
||||
hb_blob_destroy (tlist->blob);
|
||||
tlist = tlist->next;
|
||||
free (old);
|
||||
}
|
||||
gr_face_destroy (f->grface);
|
||||
|
||||
gr_face_destroy (data->grface);
|
||||
|
||||
free (data);
|
||||
}
|
||||
|
||||
static void _hb_gr_font_data_destroy (void *data)
|
||||
|
||||
/*
|
||||
* shaper font data
|
||||
*/
|
||||
|
||||
static float hb_graphite2_get_advance (const void *hb_font, unsigned short gid)
|
||||
{
|
||||
hb_gr_font_data_t *f = (hb_gr_font_data_t *) data;
|
||||
|
||||
gr_font_destroy (f->grfont);
|
||||
free (f);
|
||||
return ((hb_font_t *) hb_font)->get_glyph_h_advance (gid);
|
||||
}
|
||||
|
||||
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_graphite2_shaper_font_data_t *
|
||||
_hb_graphite2_shaper_font_data_create (hb_font_t *font)
|
||||
{
|
||||
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;
|
||||
if (unlikely (!hb_graphite2_shaper_face_data_ensure (font->face))) return NULL;
|
||||
|
||||
data = (hb_gr_face_data_t *) calloc (1, sizeof (hb_gr_face_data_t));
|
||||
if (unlikely (!data))
|
||||
return &_hb_gr_face_data_nil;
|
||||
hb_face_t *face = font->face;
|
||||
hb_graphite2_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
||||
|
||||
|
||||
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;
|
||||
return gr_make_font_with_advance_fn (font->x_scale, font, &hb_graphite2_get_advance, face_data->grface);
|
||||
}
|
||||
|
||||
static hb_gr_font_data_t *
|
||||
_hb_gr_font_get_data (hb_font_t *font)
|
||||
void
|
||||
_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data)
|
||||
{
|
||||
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;
|
||||
data->grfont = gr_make_font_with_advance_fn (font->x_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;
|
||||
gr_font_destroy (data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper shape_plan data
|
||||
*/
|
||||
|
||||
struct hb_graphite2_shaper_shape_plan_data_t {};
|
||||
|
||||
hb_graphite2_shaper_shape_plan_data_t *
|
||||
_hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||
const hb_feature_t *user_features HB_UNUSED,
|
||||
unsigned int num_user_features HB_UNUSED)
|
||||
{
|
||||
return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shaper_shape_plan_data_t *data HB_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* shaper
|
||||
*/
|
||||
|
||||
struct hb_graphite2_cluster_t {
|
||||
unsigned int base_char;
|
||||
unsigned int num_chars;
|
||||
unsigned int base_glyph;
|
||||
unsigned int num_glyphs;
|
||||
};
|
||||
|
||||
hb_bool_t
|
||||
_hb_graphite_shape (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features)
|
||||
_hb_graphite2_shape (hb_shape_plan_t *shape_plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features)
|
||||
{
|
||||
|
||||
buffer->guess_properties ();
|
||||
|
||||
/* XXX We do a hell of a lot of stuff just to figure out this font
|
||||
* is not graphite! Shouldn't do. */
|
||||
|
||||
hb_gr_font_data_t *data = _hb_gr_font_get_data (font);
|
||||
if (!data->grface) return false;
|
||||
hb_face_t *face = font->face;
|
||||
gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
|
||||
gr_font *grfont = HB_SHAPER_DATA_GET (font);
|
||||
|
||||
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);
|
||||
gr_feature_val *feats = gr_face_featureval_for_lang (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);
|
||||
const gr_feature_ref *fref = gr_face_find_fref (grface, features->tag);
|
||||
if (fref)
|
||||
gr_fref_set_feature_value (fref, features->value, feats);
|
||||
features++;
|
||||
}
|
||||
|
||||
/* TODO Use scratch buffer for these. */
|
||||
hb_codepoint_t *gids = NULL, *pg;
|
||||
hb_gr_cluster_t *clusters = NULL;
|
||||
hb_graphite2_cluster_t *clusters = NULL;
|
||||
gr_segment *seg = NULL;
|
||||
uint32_t *text = NULL;
|
||||
const gr_slot *is;
|
||||
@ -266,7 +251,7 @@ _hb_graphite_shape (hb_font_t *font,
|
||||
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,
|
||||
seg = gr_make_seg (grfont, grface,
|
||||
script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
|
||||
feats,
|
||||
gr_utf32, text, charlen,
|
||||
@ -274,7 +259,7 @@ _hb_graphite_shape (hb_font_t *font,
|
||||
if (!seg) goto dieout;
|
||||
|
||||
glyphlen = gr_seg_n_slots (seg);
|
||||
clusters = (hb_gr_cluster_t *) calloc (charlen, sizeof (hb_gr_cluster_t));
|
||||
clusters = (hb_graphite2_cluster_t *) calloc (charlen, sizeof (hb_graphite2_cluster_t));
|
||||
if (!glyphlen || !clusters) goto dieout;
|
||||
|
||||
gids = (hb_codepoint_t *) malloc (glyphlen * sizeof (hb_codepoint_t));
|
||||
@ -296,7 +281,7 @@ _hb_graphite_shape (hb_font_t *font,
|
||||
|
||||
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;
|
||||
hb_graphite2_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;
|
||||
@ -315,31 +300,35 @@ _hb_graphite_shape (hb_font_t *font,
|
||||
buffer->replace_glyphs (clusters[i].num_chars, clusters[i].num_glyphs, gids + clusters[i].base_glyph);
|
||||
buffer->swap_buffers ();
|
||||
|
||||
if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
|
||||
curradvx = gr_seg_advance_X(seg);
|
||||
|
||||
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;
|
||||
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, grface, grfont);
|
||||
pPos->y_advance = gr_slot_advance_Y (is, grface, grfont);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
curradvx -= pPos->x_advance;
|
||||
pPos->x_offset = gr_slot_origin_X (is) - curradvx;
|
||||
if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
curradvx += pPos->x_advance;
|
||||
pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
|
||||
curradvy += pPos->y_advance;
|
||||
}
|
||||
pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx;
|
||||
if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
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);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
hb_buffer_reverse_clusters (buffer);
|
||||
|
||||
success = 1;
|
||||
|
||||
dieout:
|
||||
if (feats) gr_featureval_destroy (feats);
|
||||
if (gids) free (gids);
|
||||
if (clusters) free (clusters);
|
||||
if (seg) gr_seg_destroy (seg);
|
||||
|
@ -31,7 +31,7 @@
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
#define HB_GRAPHITE_TAG_Silf HB_TAG('S','i','l','f')
|
||||
#define HB_GRAPHITE2_TAG_SILF HB_TAG('S','i','l','f')
|
||||
|
||||
/* TODO add gr_font/face etc getters and other glue API */
|
||||
|
||||
|
@ -33,11 +33,10 @@
|
||||
|
||||
#include "hb-unicode-private.hh"
|
||||
|
||||
#include <unicode/uversion.h>
|
||||
#include <unicode/uchar.h>
|
||||
#include <unicode/unorm.h>
|
||||
#include <unicode/ustring.h>
|
||||
|
||||
#include <unicode/uversion.h>
|
||||
|
||||
|
||||
hb_script_t
|
||||
@ -164,6 +163,10 @@ hb_icu_unicode_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
return hb_icu_script_to_script (scriptCode);
|
||||
}
|
||||
|
||||
#if U_ICU_VERSION_MAJOR_NUM >= 49
|
||||
static const UNormalizer2 *normalizer;
|
||||
#endif
|
||||
|
||||
static hb_bool_t
|
||||
hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
hb_codepoint_t a,
|
||||
@ -171,11 +174,20 @@ hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
hb_codepoint_t *ab,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (!a || !b)
|
||||
return false;
|
||||
#if U_ICU_VERSION_MAJOR_NUM >= 49
|
||||
{
|
||||
UChar32 ret = unorm2_composePair (normalizer, a, b);
|
||||
if (ret < 0) return false;
|
||||
*ab = ret;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We don't ifdef-out the fallback code such that compiler always
|
||||
* sees it and makes sure it's compilable. */
|
||||
|
||||
UChar utf16[4], normalized[5];
|
||||
int len;
|
||||
unsigned int len;
|
||||
hb_bool_t ret, err;
|
||||
UErrorCode icu_err;
|
||||
|
||||
@ -207,8 +219,34 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
hb_codepoint_t *b,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
#if U_ICU_VERSION_MAJOR_NUM >= 49
|
||||
{
|
||||
UChar decomposed[4];
|
||||
int len;
|
||||
UErrorCode icu_err = U_ZERO_ERROR;
|
||||
len = unorm2_getRawDecomposition (normalizer, ab, decomposed,
|
||||
ARRAY_LENGTH (decomposed), &icu_err);
|
||||
if (U_FAILURE (icu_err) || len < 0) return false;
|
||||
|
||||
len = u_countChar32 (decomposed, len);
|
||||
if (len == 1) {
|
||||
U16_GET_UNSAFE (decomposed, 0, *a);
|
||||
*b = 0;
|
||||
return *a != ab;
|
||||
} else if (len == 2) {
|
||||
len =0;
|
||||
U16_NEXT_UNSAFE (decomposed, len, *a);
|
||||
U16_NEXT_UNSAFE (decomposed, len, *b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We don't ifdef-out the fallback code such that compiler always
|
||||
* sees it and makes sure it's compilable. */
|
||||
|
||||
UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1];
|
||||
int len;
|
||||
unsigned int len;
|
||||
hb_bool_t ret, err;
|
||||
UErrorCode icu_err;
|
||||
|
||||
@ -278,7 +316,7 @@ hb_icu_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1];
|
||||
int len;
|
||||
unsigned int len;
|
||||
int32_t utf32_len;
|
||||
hb_bool_t err;
|
||||
UErrorCode icu_err;
|
||||
@ -306,22 +344,28 @@ hb_icu_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
extern HB_INTERNAL const hb_unicode_funcs_t _hb_icu_unicode_funcs;
|
||||
const 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)
|
||||
{
|
||||
static const 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
|
||||
}
|
||||
};
|
||||
|
||||
#if U_ICU_VERSION_MAJOR_NUM >= 49
|
||||
if (!hb_atomic_ptr_get (&normalizer)) {
|
||||
UErrorCode icu_err = U_ZERO_ERROR;
|
||||
/* We ignore failure in getNFCInstace(). */
|
||||
hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err));
|
||||
}
|
||||
#endif
|
||||
return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs);
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,6 @@
|
||||
|
||||
#include <unicode/uscript.h>
|
||||
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
#elif !defined(HB_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
typedef CRITICAL_SECTION hb_mutex_impl_t;
|
||||
#define HB_MUTEX_IMPL_INIT { NULL, 0, 0, NULL, NULL, 0 }
|
||||
|
@ -152,7 +152,7 @@ hb_old_getGlyphMetrics (HB_Font old_font,
|
||||
metrics->x = extents.x_bearing;
|
||||
metrics->y = extents.y_bearing;
|
||||
metrics->width = extents.width;
|
||||
metrics->height = -extents.height;
|
||||
metrics->height = extents.height;
|
||||
metrics->xOffset = font->get_glyph_h_advance (glyph);
|
||||
metrics->yOffset = 0;
|
||||
}
|
||||
@ -188,7 +188,7 @@ static HB_Error
|
||||
table_func (void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length)
|
||||
{
|
||||
hb_face_t *face = (hb_face_t *) font;
|
||||
hb_blob_t *blob = hb_face_reference_table (face, (hb_tag_t) tag);
|
||||
hb_blob_t *blob = face->reference_table ((hb_tag_t) tag);
|
||||
unsigned int capacity = *length;
|
||||
*length = hb_blob_get_length (blob);
|
||||
memcpy (buffer, hb_blob_get_data (blob, NULL), MIN (capacity, *length));
|
||||
|
@ -314,7 +314,6 @@ struct Lookup
|
||||
TRACE_SANITIZE ();
|
||||
/* Real sanitize of the subtables is done by GSUB/GPOS/... */
|
||||
if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
|
||||
if (!subTable.len) TRACE_RETURN (false);
|
||||
if (unlikely (lookupFlag & LookupFlag::UseMarkFilteringSet))
|
||||
{
|
||||
USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
|
||||
|
@ -473,7 +473,14 @@ struct Ligature
|
||||
|
||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
return c->len == 1 || (c->len == 2 && component.len == 2 && component[1] == c->second);
|
||||
if (c->len != component.len)
|
||||
return false;
|
||||
|
||||
for (unsigned int i = 1; i < c->len; i++)
|
||||
if (likely (c->glyphs[i] != component[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool apply (hb_apply_context_t *c) const
|
||||
@ -706,7 +713,7 @@ struct LigatureSubstFormat1
|
||||
|
||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
return (this+ligatureSet[(this+coverage) (c->first)]).would_apply (c);
|
||||
return (this+ligatureSet[(this+coverage) (c->glyphs[0])]).would_apply (c);
|
||||
}
|
||||
|
||||
inline bool apply (hb_apply_context_t *c) const
|
||||
@ -1064,8 +1071,16 @@ struct SubstLookupSubTable
|
||||
unsigned int lookup_type) const
|
||||
{
|
||||
TRACE_WOULD_APPLY ();
|
||||
if (get_coverage (lookup_type).get_coverage (c->first) == NOT_COVERED) return false;
|
||||
if (c->len == 1) return true; /* Done! */
|
||||
if (get_coverage (lookup_type).get_coverage (c->glyphs[0]) == NOT_COVERED) return false;
|
||||
if (c->len == 1) {
|
||||
switch (lookup_type) {
|
||||
case Single:
|
||||
case Multiple:
|
||||
case Alternate:
|
||||
case ReverseChainSingle:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only need to look further for lookups that support substitutions
|
||||
* of input longer than 1. */
|
||||
@ -1170,7 +1185,8 @@ struct SubstLookup : Lookup
|
||||
|
||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
if (!c->digest.may_have (c->first)) return false;
|
||||
if (unlikely (!c->len)) return false;
|
||||
if (!c->digest.may_have (c->glyphs[0])) return false;
|
||||
unsigned int lookup_type = get_type ();
|
||||
unsigned int count = get_subtable_count ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
|
@ -43,15 +43,6 @@
|
||||
hb_auto_trace_t<HB_DEBUG_CLOSURE> trace (&c->debug_depth, "CLOSURE", this, HB_FUNC, "");
|
||||
|
||||
|
||||
/* TODO Add TRACE_RETURN annotation to gsub. */
|
||||
#ifndef HB_DEBUG_WOULD_APPLY
|
||||
#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
#define TRACE_WOULD_APPLY() \
|
||||
hb_auto_trace_t<HB_DEBUG_WOULD_APPLY> trace (&c->debug_depth, "WOULD_APPLY", this, HB_FUNC, "first %u second %u", c->first, c->second);
|
||||
|
||||
|
||||
struct hb_closure_context_t
|
||||
{
|
||||
hb_face_t *face;
|
||||
@ -71,23 +62,31 @@ struct hb_closure_context_t
|
||||
|
||||
|
||||
|
||||
/* TODO Add TRACE_RETURN annotation to gsub. */
|
||||
#ifndef HB_DEBUG_WOULD_APPLY
|
||||
#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
#define TRACE_WOULD_APPLY() \
|
||||
hb_auto_trace_t<HB_DEBUG_WOULD_APPLY> trace (&c->debug_depth, "WOULD_APPLY", this, HB_FUNC, "%d glyphs", c->len);
|
||||
|
||||
|
||||
struct hb_would_apply_context_t
|
||||
{
|
||||
hb_face_t *face;
|
||||
hb_codepoint_t first;
|
||||
hb_codepoint_t second;
|
||||
const hb_codepoint_t *glyphs;
|
||||
unsigned int len;
|
||||
const hb_set_digest_t digest;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_would_apply_context_t (hb_face_t *face_,
|
||||
hb_codepoint_t first_,
|
||||
hb_codepoint_t second_,
|
||||
const hb_codepoint_t *glyphs_,
|
||||
unsigned int len_,
|
||||
const hb_set_digest_t *digest_
|
||||
) :
|
||||
face (face_),
|
||||
first (first_), second (second_), len (second == (hb_codepoint_t) -1 ? 1 : 2),
|
||||
glyphs (glyphs_),
|
||||
len (len_),
|
||||
digest (*digest_),
|
||||
debug_depth (0) {};
|
||||
};
|
||||
@ -407,7 +406,7 @@ static inline bool would_match_input (hb_would_apply_context_t *c,
|
||||
return false;
|
||||
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
if (likely (!match_func (c->second, input[i - 1], match_data)))
|
||||
if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -757,7 +756,7 @@ struct ContextFormat1
|
||||
{
|
||||
TRACE_WOULD_APPLY ();
|
||||
|
||||
const RuleSet &rule_set = this+ruleSet[(this+coverage) (c->first)];
|
||||
const RuleSet &rule_set = this+ruleSet[(this+coverage) (c->glyphs[0])];
|
||||
struct ContextApplyLookupContext lookup_context = {
|
||||
{match_glyph, NULL},
|
||||
NULL
|
||||
@ -830,7 +829,7 @@ struct ContextFormat2
|
||||
TRACE_WOULD_APPLY ();
|
||||
|
||||
const ClassDef &class_def = this+classDef;
|
||||
unsigned int index = class_def (c->first);
|
||||
unsigned int index = class_def (c->glyphs[0]);
|
||||
const RuleSet &rule_set = this+ruleSet[index];
|
||||
struct ContextApplyLookupContext lookup_context = {
|
||||
{match_class, NULL},
|
||||
@ -929,7 +928,6 @@ struct ContextFormat3
|
||||
TRACE_SANITIZE ();
|
||||
if (!c->check_struct (this)) return TRACE_RETURN (false);
|
||||
unsigned int count = glyphCount;
|
||||
if (unlikely (!glyphCount)) return TRACE_RETURN (false);
|
||||
if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
|
||||
@ -1253,7 +1251,7 @@ struct ChainContextFormat1
|
||||
{
|
||||
TRACE_WOULD_APPLY ();
|
||||
|
||||
const ChainRuleSet &rule_set = this+ruleSet[(this+coverage) (c->first)];
|
||||
const ChainRuleSet &rule_set = this+ruleSet[(this+coverage) (c->glyphs[0])];
|
||||
struct ChainContextApplyLookupContext lookup_context = {
|
||||
{match_glyph, NULL},
|
||||
{NULL, NULL, NULL}
|
||||
@ -1329,7 +1327,7 @@ struct ChainContextFormat2
|
||||
|
||||
const ClassDef &input_class_def = this+inputClassDef;
|
||||
|
||||
unsigned int index = input_class_def (c->first);
|
||||
unsigned int index = input_class_def (c->glyphs[0]);
|
||||
const ChainRuleSet &rule_set = this+ruleSet[index];
|
||||
struct ChainContextApplyLookupContext lookup_context = {
|
||||
{match_class, NULL},
|
||||
@ -1468,7 +1466,6 @@ struct ChainContextFormat3
|
||||
if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
|
||||
OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
|
||||
if (!input.sanitize (c, this)) return TRACE_RETURN (false);
|
||||
if (unlikely (!input.len)) return TRACE_RETURN (false);
|
||||
OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
|
||||
if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
|
||||
ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
|
||||
|
@ -39,9 +39,9 @@
|
||||
|
||||
|
||||
/* buffer var allocations, used during the GSUB/GPOS processing */
|
||||
#define glyph_props() var1.u16[1] /* GDEF glyph properties */
|
||||
#define syllable() var2.u8[0] /* GSUB/GPOS shaping boundaries */
|
||||
#define lig_props() var2.u8[1] /* GSUB/GPOS ligature tracking */
|
||||
#define glyph_props() var1.u16[0] /* GDEF glyph properties */
|
||||
#define syllable() var1.u8[2] /* GSUB/GPOS shaping boundaries */
|
||||
#define lig_props() var1.u8[3] /* GSUB/GPOS ligature tracking */
|
||||
|
||||
#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
|
||||
|
||||
|
@ -49,13 +49,13 @@ _hb_ot_layout_create (hb_face_t *face)
|
||||
if (unlikely (!layout))
|
||||
return NULL;
|
||||
|
||||
layout->gdef_blob = Sanitizer<GDEF>::sanitize (hb_face_reference_table (face, HB_OT_TAG_GDEF));
|
||||
layout->gdef_blob = Sanitizer<GDEF>::sanitize (face->reference_table (HB_OT_TAG_GDEF));
|
||||
layout->gdef = Sanitizer<GDEF>::lock_instance (layout->gdef_blob);
|
||||
|
||||
layout->gsub_blob = Sanitizer<GSUB>::sanitize (hb_face_reference_table (face, HB_OT_TAG_GSUB));
|
||||
layout->gsub_blob = Sanitizer<GSUB>::sanitize (face->reference_table (HB_OT_TAG_GSUB));
|
||||
layout->gsub = Sanitizer<GSUB>::lock_instance (layout->gsub_blob);
|
||||
|
||||
layout->gpos_blob = Sanitizer<GPOS>::sanitize (hb_face_reference_table (face, HB_OT_TAG_GPOS));
|
||||
layout->gpos_blob = Sanitizer<GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
|
||||
layout->gpos = Sanitizer<GPOS>::lock_instance (layout->gpos_blob);
|
||||
|
||||
layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
|
||||
@ -415,9 +415,8 @@ hb_ot_layout_would_substitute_lookup_fast (hb_face_t *face,
|
||||
unsigned int glyphs_length,
|
||||
unsigned int lookup_index)
|
||||
{
|
||||
if (unlikely (glyphs_length < 1 || glyphs_length > 2)) return false;
|
||||
if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
|
||||
hb_would_apply_context_t c (face, glyphs[0], glyphs_length == 2 ? glyphs[1] : -1, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]);
|
||||
hb_would_apply_context_t c (face, glyphs, glyphs_length, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]);
|
||||
return hb_ot_layout_from_face (face)->gsub->would_substitute_lookup (&c, lookup_index);
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,6 @@ hb_ot_layout_feature_get_lookup_indexes (hb_face_t *face,
|
||||
hb_bool_t
|
||||
hb_ot_layout_has_substitution (hb_face_t *face);
|
||||
|
||||
/* Supports length 1 or 2 right now. */
|
||||
hb_bool_t
|
||||
hb_ot_layout_would_substitute_lookup (hb_face_t *face,
|
||||
const hb_codepoint_t *glyphs,
|
||||
|
@ -914,9 +914,9 @@ static const uint16_t shaping_table[][4] =
|
||||
#define SHAPING_TABLE_LAST 0x06D3
|
||||
|
||||
|
||||
static const struct {
|
||||
static const struct ligature_set_t {
|
||||
uint16_t first;
|
||||
struct {
|
||||
struct ligature_pairs_t {
|
||||
uint16_t second;
|
||||
uint16_t ligature;
|
||||
} ligatures[4];
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2010 Google, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
|
||||
/* buffer var allocations */
|
||||
#define arabic_shaping_action() complex_var_temporary_u8() /* arabic shaping action */
|
||||
#define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */
|
||||
|
||||
|
||||
/*
|
||||
@ -99,7 +99,7 @@ static uint16_t get_ligature (hb_codepoint_t first, hb_codepoint_t second)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const hb_tag_t arabic_syriac_features[] =
|
||||
static const hb_tag_t arabic_features[] =
|
||||
{
|
||||
HB_TAG('i','n','i','t'),
|
||||
HB_TAG('m','e','d','i'),
|
||||
@ -127,9 +127,7 @@ enum {
|
||||
|
||||
NONE,
|
||||
|
||||
COMMON_NUM_FEATURES = 4,
|
||||
SYRIAC_NUM_FEATURES = 7,
|
||||
TOTAL_NUM_FEATURES = NONE
|
||||
ARABIC_NUM_FEATURES = NONE
|
||||
};
|
||||
|
||||
static const struct arabic_state_table_entry {
|
||||
@ -184,9 +182,8 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
|
||||
|
||||
map->add_gsub_pause (NULL);
|
||||
|
||||
unsigned int num_features = plan->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
|
||||
for (unsigned int i = 0; i < num_features; i++)
|
||||
map->add_bool_feature (arabic_syriac_features[i], false);
|
||||
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
|
||||
map->add_bool_feature (arabic_features[i], false);
|
||||
|
||||
map->add_gsub_pause (NULL);
|
||||
|
||||
@ -200,10 +197,55 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
|
||||
map->add_bool_feature (HB_TAG('c','s','w','h'));
|
||||
}
|
||||
|
||||
struct arabic_shape_plan_t
|
||||
{
|
||||
ASSERT_POD ();
|
||||
|
||||
bool do_fallback;
|
||||
/* The "+ 1" in the next array is to accommodate for the "NONE" command,
|
||||
* which is not an OpenType feature, but this simplifies the code by not
|
||||
* having to do a "if (... < NONE) ..." and just rely on the fact that
|
||||
* mask_array[NONE] == 0. */
|
||||
hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
|
||||
};
|
||||
|
||||
static void *
|
||||
data_create_arabic (const hb_ot_shape_plan_t *plan)
|
||||
{
|
||||
arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t));
|
||||
if (unlikely (!arabic_plan))
|
||||
return NULL;
|
||||
|
||||
hb_mask_t total_masks = 0;
|
||||
for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
|
||||
arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
|
||||
total_masks |= arabic_plan->mask_array[i];
|
||||
}
|
||||
|
||||
/* Pitfalls:
|
||||
* - This path fires if user force-set init/medi/fina/isol off,
|
||||
* - If font does not declare script 'arab', well, what to do?
|
||||
* Most probably it's safe to assume that init/medi/fina/isol
|
||||
* still mean Arabic shaping, although they do not have to.
|
||||
*/
|
||||
arabic_plan->do_fallback = 0 == total_masks;
|
||||
|
||||
return arabic_plan;
|
||||
}
|
||||
|
||||
static void
|
||||
data_destroy_arabic (void *data)
|
||||
{
|
||||
free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
arabic_fallback_shape (hb_font_t *font, hb_buffer_t *buffer)
|
||||
{
|
||||
/* Only Arabic has presentation forms encoded in Unicode. */
|
||||
if (buffer->props.script != HB_SCRIPT_ARABIC)
|
||||
return;
|
||||
|
||||
unsigned int count = buffer->len;
|
||||
hb_codepoint_t glyph;
|
||||
|
||||
@ -236,9 +278,7 @@ arabic_fallback_shape (hb_font_t *font, hb_buffer_t *buffer)
|
||||
}
|
||||
|
||||
static void
|
||||
setup_masks_arabic (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font)
|
||||
arabic_joining (hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
unsigned int prev = 0, state = 0;
|
||||
@ -265,30 +305,37 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan,
|
||||
state = entry->next_state;
|
||||
}
|
||||
|
||||
hb_mask_t mask_array[TOTAL_NUM_FEATURES + 1] = {0};
|
||||
hb_mask_t total_masks = 0;
|
||||
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] = plan->map.get_1_mask (arabic_syriac_features[i]);
|
||||
total_masks |= mask_array[i];
|
||||
}
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
|
||||
}
|
||||
|
||||
if (total_masks) {
|
||||
/* Has OpenType tables */
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
buffer->info[i].mask |= mask_array[buffer->info[i].arabic_shaping_action()];
|
||||
} else if (buffer->props.script == HB_SCRIPT_ARABIC) {
|
||||
/* Fallback Arabic shaping to Presentation Forms */
|
||||
/* Pitfalls:
|
||||
* - This path fires if user force-set init/medi/fina/isol off,
|
||||
* - If font does not declare script 'arab', well, what to do?
|
||||
* Most probably it's safe to assume that init/medi/fina/isol
|
||||
* still mean Arabic shaping, although they do not have to.
|
||||
*/
|
||||
static void
|
||||
preprocess_text_arabic (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font)
|
||||
{
|
||||
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
|
||||
|
||||
if (unlikely (arabic_plan->do_fallback))
|
||||
{
|
||||
arabic_joining (buffer);
|
||||
arabic_fallback_shape (font, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
|
||||
static void
|
||||
setup_masks_arabic (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font)
|
||||
{
|
||||
const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
|
||||
|
||||
if (likely (!arabic_plan->do_fallback))
|
||||
{
|
||||
arabic_joining (buffer);
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
buffer->info[i].mask |= arabic_plan->mask_array[buffer->info[i].arabic_shaping_action()];
|
||||
}
|
||||
}
|
||||
|
||||
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
|
||||
@ -296,8 +343,9 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
|
||||
"arabic",
|
||||
collect_features_arabic,
|
||||
NULL, /* override_features */
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
data_create_arabic,
|
||||
data_destroy_arabic,
|
||||
preprocess_text_arabic,
|
||||
NULL, /* normalization_preference */
|
||||
setup_masks_arabic,
|
||||
true, /* zero_width_attached_marks */
|
||||
|
@ -35,8 +35,8 @@
|
||||
|
||||
|
||||
/* 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_category() complex_var_u8_0() /* indic_category_t */
|
||||
#define indic_position() complex_var_u8_1() /* indic_matra_category_t */
|
||||
|
||||
|
||||
#define INDIC_TABLE_ELEMENT_TYPE uint8_t
|
||||
|
@ -57,7 +57,7 @@ indic_options_init (void)
|
||||
return u;
|
||||
}
|
||||
|
||||
inline indic_options_t
|
||||
static inline indic_options_t
|
||||
indic_options (void)
|
||||
{
|
||||
static indic_options_union_t options;
|
||||
@ -148,8 +148,8 @@ indic_features[] =
|
||||
{HB_TAG('r','p','h','f'), false},
|
||||
{HB_TAG('r','k','r','f'), true},
|
||||
{HB_TAG('p','r','e','f'), false},
|
||||
{HB_TAG('b','l','w','f'), false},
|
||||
{HB_TAG('h','a','l','f'), false},
|
||||
{HB_TAG('b','l','w','f'), false},
|
||||
{HB_TAG('a','b','v','f'), false},
|
||||
{HB_TAG('p','s','t','f'), false},
|
||||
{HB_TAG('c','f','a','r'), false},
|
||||
@ -180,8 +180,8 @@ enum {
|
||||
RPHF,
|
||||
_RKRF,
|
||||
PREF,
|
||||
BLWF,
|
||||
HALF,
|
||||
BLWF,
|
||||
ABVF,
|
||||
PSTF,
|
||||
CFAR,
|
||||
@ -1134,6 +1134,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
|
||||
override_features_indic,
|
||||
data_create_indic,
|
||||
data_destroy_indic,
|
||||
NULL, /* preprocess_text */
|
||||
NULL, /* normalization_preference */
|
||||
setup_masks_indic,
|
||||
false, /* zero_width_attached_marks */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2010 Google, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
@ -90,6 +90,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
|
||||
NULL, /* override_features */
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
NULL, /* preprocess_text */
|
||||
normalization_preference_default,
|
||||
NULL, /* setup_masks */
|
||||
true, /* zero_width_attached_marks */
|
||||
@ -99,9 +100,9 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
|
||||
/* Thai / Lao shaper */
|
||||
|
||||
static void
|
||||
setup_masks_thai (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font HB_UNUSED)
|
||||
preprocess_text_thai (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font HB_UNUSED)
|
||||
{
|
||||
/* The following is NOT specified in the MS OT Thai spec, however, it seems
|
||||
* to be what Uniscribe and other engines implement. According to Eric Muller:
|
||||
@ -200,7 +201,8 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
|
||||
NULL, /* override_features */
|
||||
NULL, /* data_create */
|
||||
NULL, /* data_destroy */
|
||||
preprocess_text_thai,
|
||||
NULL, /* normalization_preference */
|
||||
setup_masks_thai,
|
||||
NULL, /* setup_masks */
|
||||
true, /* zero_width_attached_marks */
|
||||
};
|
||||
|
@ -35,9 +35,8 @@
|
||||
|
||||
|
||||
/* buffer var allocations, used by complex shapers */
|
||||
#define complex_var_persistent_u8_0() var2.u8[2]
|
||||
#define complex_var_persistent_u8_1() var2.u8[3]
|
||||
#define complex_var_temporary_u8() var2.u8[0]
|
||||
#define complex_var_u8_0() var2.u8[2]
|
||||
#define complex_var_u8_1() var2.u8[3]
|
||||
|
||||
|
||||
|
||||
@ -57,7 +56,6 @@ struct hb_ot_complex_shaper_t
|
||||
/* collect_features()
|
||||
* Called during shape_plan().
|
||||
* Shapers should use plan->map to add their features and callbacks.
|
||||
* May be NULL.
|
||||
*/
|
||||
void (*collect_features) (hb_ot_shape_planner_t *plan);
|
||||
|
||||
@ -65,7 +63,6 @@ struct hb_ot_complex_shaper_t
|
||||
* Called during shape_plan().
|
||||
* Shapers should use plan->map to override features and add callbacks after
|
||||
* common features are added.
|
||||
* May be NULL.
|
||||
*/
|
||||
void (*override_features) (hb_ot_shape_planner_t *plan);
|
||||
|
||||
@ -74,7 +71,7 @@ struct hb_ot_complex_shaper_t
|
||||
* Called at the end of shape_plan().
|
||||
* Whatever shapers return will be accessible through plan->data later.
|
||||
* If NULL is returned, means a plan failure.
|
||||
* May be NULL. */
|
||||
*/
|
||||
void *(*data_create) (const hb_ot_shape_plan_t *plan);
|
||||
|
||||
/* data_destroy()
|
||||
@ -84,6 +81,16 @@ struct hb_ot_complex_shaper_t
|
||||
* May be NULL. */
|
||||
void (*data_destroy) (void *data);
|
||||
|
||||
|
||||
/* preprocess_text()
|
||||
* Called during shape().
|
||||
* Shapers can use to modify text before shaping starts.
|
||||
*/
|
||||
void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
hb_font_t *font);
|
||||
|
||||
|
||||
/* normalization_preference()
|
||||
* Called during shape().
|
||||
*/
|
||||
@ -93,6 +100,7 @@ struct hb_ot_complex_shaper_t
|
||||
/* setup_masks()
|
||||
* Called during shape().
|
||||
* Shapers should use map to get feature masks and set on buffer.
|
||||
* Shapers may NOT modify characters.
|
||||
*/
|
||||
void (*setup_masks) (const hb_ot_shape_plan_t *plan,
|
||||
hb_buffer_t *buffer,
|
||||
|
@ -24,19 +24,16 @@
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_GRAPHITE2_PRIVATE_HH
|
||||
#define HB_GRAPHITE2_PRIVATE_HH
|
||||
#ifndef HB_OT_SHAPE_FALLBACK_PRIVATE_HH
|
||||
#define HB_OT_SHAPE_FALLBACK_PRIVATE_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-graphite2.h"
|
||||
#include "hb-ot-shape-private.hh"
|
||||
|
||||
|
||||
HB_INTERNAL hb_bool_t
|
||||
_hb_graphite2_shape (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features);
|
||||
HB_INTERNAL void _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
|
||||
#endif /* HB_GRAPHITE2_PRIVATE_HH */
|
||||
#endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */
|
326
gfx/harfbuzz/src/hb-ot-shape-fallback.cc
Normal file
326
gfx/harfbuzz/src/hb-ot-shape-fallback.cc
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright © 2011,2012 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-fallback-private.hh"
|
||||
|
||||
static void
|
||||
zero_mark_advances (hb_buffer_t *buffer,
|
||||
unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
{
|
||||
buffer->pos[i].x_advance = 0;
|
||||
buffer->pos[i].y_advance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
recategorize_combining_class (unsigned int modified_combining_class)
|
||||
{
|
||||
if (modified_combining_class >= 200)
|
||||
return modified_combining_class;
|
||||
|
||||
/* This should be kept in sync with modified combining class mapping
|
||||
* from hb-unicode.cc. */
|
||||
switch (modified_combining_class)
|
||||
{
|
||||
|
||||
/* Hebrew */
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC10: /* sheva */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC11: /* hataf segol */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC12: /* hataf patah */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC13: /* hataf qamats */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC14: /* hiriq */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC15: /* tsere */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC16: /* segol */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC17: /* patah */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC20: /* qubuts */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC22: /* meteg */
|
||||
return HB_UNICODE_COMBINING_CLASS_BELOW;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC23: /* rafe */
|
||||
return HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC24: /* shin dot */
|
||||
return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC25: /* sin dot */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam */
|
||||
return HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC26: /* point varika */
|
||||
return HB_UNICODE_COMBINING_CLASS_ABOVE;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC21: /* dagesh */
|
||||
break;
|
||||
|
||||
|
||||
/* Arabic and Syriac */
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC27: /* fathatan */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC28: /* dammatan */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC30: /* fatha */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC31: /* damma */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC33: /* shadda */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC34: /* sukun */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC35: /* superscript alef */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC36: /* superscript alaph */
|
||||
return HB_UNICODE_COMBINING_CLASS_ABOVE;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC29: /* kasratan */
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC32: /* kasra */
|
||||
return HB_UNICODE_COMBINING_CLASS_BELOW;
|
||||
|
||||
|
||||
/* Thai */
|
||||
|
||||
/* Note: to be useful we also need to position U+0E3A that has ccc=9 (virama).
|
||||
* But viramas can be both above and below based on the codepoint / script. */
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC103: /* sara u / sara uu */
|
||||
return HB_UNICODE_COMBINING_CLASS_BELOW;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC107: /* mai */
|
||||
return HB_UNICODE_COMBINING_CLASS_ABOVE;
|
||||
|
||||
|
||||
/* Lao */
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC118: /* sign u / sign uu */
|
||||
return HB_UNICODE_COMBINING_CLASS_BELOW;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC122: /* mai */
|
||||
return HB_UNICODE_COMBINING_CLASS_ABOVE;
|
||||
|
||||
|
||||
/* Tibetan */
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC129: /* sign aa */
|
||||
return HB_UNICODE_COMBINING_CLASS_BELOW;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC130: /* sign i*/
|
||||
return HB_UNICODE_COMBINING_CLASS_ABOVE;
|
||||
|
||||
case HB_MODIFIED_COMBINING_CLASS_CCC132: /* sign u */
|
||||
return HB_UNICODE_COMBINING_CLASS_BELOW;
|
||||
|
||||
}
|
||||
|
||||
return modified_combining_class;
|
||||
}
|
||||
|
||||
static inline void
|
||||
position_mark (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
hb_glyph_extents_t &base_extents,
|
||||
unsigned int i,
|
||||
unsigned int combining_class)
|
||||
{
|
||||
hb_glyph_extents_t mark_extents;
|
||||
if (!font->get_glyph_extents (buffer->info[i].codepoint,
|
||||
&mark_extents))
|
||||
return;
|
||||
|
||||
hb_position_t y_gap = font->y_scale / 16;
|
||||
|
||||
hb_glyph_position_t &pos = buffer->pos[i];
|
||||
pos.x_offset = pos.y_offset = 0;
|
||||
|
||||
|
||||
/* We dont position LEFT and RIGHT marks. */
|
||||
|
||||
/* X positioning */
|
||||
switch (combining_class)
|
||||
{
|
||||
case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
|
||||
case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
|
||||
if (buffer->props.direction == HB_DIRECTION_LTR) {
|
||||
pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
|
||||
break;
|
||||
} else if (buffer->props.direction == HB_DIRECTION_RTL) {
|
||||
pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
|
||||
case HB_UNICODE_COMBINING_CLASS_BELOW:
|
||||
case HB_UNICODE_COMBINING_CLASS_ABOVE:
|
||||
/* Center align. */
|
||||
pos.x_offset += base_extents.x_bearing + (base_extents.width - mark_extents.width) / 2 - mark_extents.x_bearing;
|
||||
break;
|
||||
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
|
||||
case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
|
||||
case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
|
||||
/* Left align. */
|
||||
pos.x_offset += base_extents.x_bearing - mark_extents.x_bearing;
|
||||
break;
|
||||
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
|
||||
case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
|
||||
case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
|
||||
/* Right align. */
|
||||
pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width - mark_extents.x_bearing;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Y positioning */
|
||||
switch (combining_class)
|
||||
{
|
||||
case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
|
||||
case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
|
||||
case HB_UNICODE_COMBINING_CLASS_BELOW:
|
||||
case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
|
||||
/* Add gap, fall-through. */
|
||||
base_extents.height -= y_gap;
|
||||
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
|
||||
pos.y_offset += base_extents.y_bearing + base_extents.height - mark_extents.y_bearing;
|
||||
base_extents.height += mark_extents.height;
|
||||
break;
|
||||
|
||||
case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
|
||||
case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
|
||||
case HB_UNICODE_COMBINING_CLASS_ABOVE:
|
||||
case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
|
||||
/* Add gap, fall-through. */
|
||||
base_extents.y_bearing += y_gap;
|
||||
base_extents.height -= y_gap;
|
||||
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
|
||||
case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
|
||||
pos.y_offset += base_extents.y_bearing - (mark_extents.y_bearing + mark_extents.height);
|
||||
base_extents.y_bearing -= mark_extents.height;
|
||||
base_extents.height += mark_extents.height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
position_around_base (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int base,
|
||||
unsigned int end)
|
||||
{
|
||||
hb_glyph_extents_t base_extents;
|
||||
if (!font->get_glyph_extents (buffer->info[base].codepoint,
|
||||
&base_extents))
|
||||
{
|
||||
/* If extents don't work, zero marks and go home. */
|
||||
zero_mark_advances (buffer, base + 1, end);
|
||||
return;
|
||||
}
|
||||
base_extents.x_bearing += buffer->pos[base].x_offset;
|
||||
base_extents.y_bearing += buffer->pos[base].y_offset;
|
||||
|
||||
/* XXX Handle ligature component positioning... */
|
||||
HB_UNUSED bool is_ligature = is_a_ligature (buffer->info[base]);
|
||||
|
||||
hb_position_t x_offset = 0, y_offset = 0;
|
||||
if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
|
||||
x_offset -= buffer->pos[base].x_advance;
|
||||
y_offset -= buffer->pos[base].y_advance;
|
||||
}
|
||||
unsigned int last_combining_class = 255;
|
||||
hb_glyph_extents_t cluster_extents;
|
||||
for (unsigned int i = base + 1; i < end; i++)
|
||||
if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
{
|
||||
unsigned int this_combining_class = recategorize_combining_class (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]));
|
||||
if (this_combining_class != last_combining_class)
|
||||
cluster_extents = base_extents;
|
||||
|
||||
position_mark (plan, font, buffer, base_extents, i, this_combining_class);
|
||||
|
||||
buffer->pos[i].x_advance = 0;
|
||||
buffer->pos[i].y_advance = 0;
|
||||
buffer->pos[i].x_offset += x_offset;
|
||||
buffer->pos[i].y_offset += y_offset;
|
||||
|
||||
/* combine cluster extents. */
|
||||
|
||||
last_combining_class = this_combining_class;
|
||||
} else {
|
||||
if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
|
||||
x_offset -= buffer->pos[i].x_advance;
|
||||
y_offset -= buffer->pos[i].y_advance;
|
||||
} else {
|
||||
x_offset += buffer->pos[i].x_advance;
|
||||
y_offset += buffer->pos[i].y_advance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
position_cluster (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
if (end - start < 2)
|
||||
return;
|
||||
|
||||
/* Find the base glyph */
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (is_a_ligature (buffer->info[i]) ||
|
||||
!(FLAG (_hb_glyph_info_get_general_category (&buffer->info[i])) &
|
||||
(FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) |
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))))
|
||||
{
|
||||
position_around_base (plan, font, buffer, i, end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int start = 0;
|
||||
unsigned int last_cluster = buffer->info[0].cluster;
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
if (buffer->info[i].cluster != last_cluster) {
|
||||
position_cluster (plan, font, buffer, start, i);
|
||||
start = i;
|
||||
last_cluster = buffer->info[i].cluster;
|
||||
}
|
||||
position_cluster (plan, font, buffer, start, count);
|
||||
}
|
@ -32,6 +32,8 @@
|
||||
#include "hb-font.h"
|
||||
#include "hb-buffer.h"
|
||||
|
||||
/* buffer var allocations, used during the normalization process */
|
||||
#define glyph_index() var1.u32
|
||||
|
||||
enum hb_ot_shape_normalization_mode_t {
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
|
||||
|
@ -81,106 +81,348 @@
|
||||
* egrep "`echo -n ';('; grep ';<' UnicodeData.txt | cut -d';' -f1 | tr '\n' '|'; echo ') '`" UnicodeData.txt
|
||||
*/
|
||||
|
||||
static void
|
||||
output_glyph (hb_buffer_t *buffer, hb_codepoint_t glyph)
|
||||
static hb_bool_t
|
||||
decompose_func (hb_unicode_funcs_t *unicode,
|
||||
hb_codepoint_t ab,
|
||||
hb_codepoint_t *a,
|
||||
hb_codepoint_t *b)
|
||||
{
|
||||
buffer->output_glyph (glyph);
|
||||
/* XXX FIXME, move these to complex shapers and propagage to normalizer.*/
|
||||
switch (ab) {
|
||||
case 0x0AC9 : return false;
|
||||
|
||||
case 0x0931 : return false;
|
||||
case 0x0B94 : return false;
|
||||
|
||||
/* These ones have Unicode decompositions, but we do it
|
||||
* this way to be close to what Uniscribe does. */
|
||||
case 0x0DDA : *a = 0x0DD9; *b= 0x0DDA; return true;
|
||||
case 0x0DDC : *a = 0x0DD9; *b= 0x0DDC; return true;
|
||||
case 0x0DDD : *a = 0x0DD9; *b= 0x0DDD; return true;
|
||||
case 0x0DDE : *a = 0x0DD9; *b= 0x0DDE; return true;
|
||||
|
||||
case 0x0F77 : *a = 0x0FB2; *b= 0x0F81; return true;
|
||||
case 0x0F79 : *a = 0x0FB3; *b= 0x0F81; return true;
|
||||
case 0x17BE : *a = 0x17C1; *b= 0x17BE; return true;
|
||||
case 0x17BF : *a = 0x17C1; *b= 0x17BF; return true;
|
||||
case 0x17C0 : *a = 0x17C1; *b= 0x17C0; return true;
|
||||
case 0x17C4 : *a = 0x17C1; *b= 0x17C4; return true;
|
||||
case 0x17C5 : *a = 0x17C1; *b= 0x17C5; return true;
|
||||
case 0x1925 : *a = 0x1920; *b= 0x1923; return true;
|
||||
case 0x1926 : *a = 0x1920; *b= 0x1924; return true;
|
||||
case 0x1B3C : *a = 0x1B42; *b= 0x1B3C; return true;
|
||||
case 0x1112E : *a = 0x11127; *b= 0x11131; return true;
|
||||
case 0x1112F : *a = 0x11127; *b= 0x11132; return true;
|
||||
#if 0
|
||||
case 0x0B57 : *a = 0xno decomp, -> RIGHT; return true;
|
||||
case 0x1C29 : *a = 0xno decomp, -> LEFT; return true;
|
||||
case 0xA9C0 : *a = 0xno decomp, -> RIGHT; return true;
|
||||
case 0x111BF : *a = 0xno decomp, -> ABOVE; return true;
|
||||
#endif
|
||||
}
|
||||
return unicode->decompose (ab, a, b);
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
compose_func (hb_unicode_funcs_t *unicode,
|
||||
hb_codepoint_t a,
|
||||
hb_codepoint_t b,
|
||||
hb_codepoint_t *ab)
|
||||
{
|
||||
/* XXX, this belongs to indic normalizer. */
|
||||
if ((FLAG (unicode->general_category (a)) &
|
||||
(FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) |
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))))
|
||||
return false;
|
||||
/* XXX, add composition-exclusion exceptions to Indic shaper. */
|
||||
if (a == 0x09AF && b == 0x09BC) { *ab = 0x09DF; return true; }
|
||||
|
||||
/* XXX, these belong to the hebew / default shaper. */
|
||||
/* Hebrew presentation-form shaping.
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=728866 */
|
||||
// Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA;
|
||||
// note that some letters do not have a dagesh presForm encoded
|
||||
static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = {
|
||||
0xFB30, // ALEF
|
||||
0xFB31, // BET
|
||||
0xFB32, // GIMEL
|
||||
0xFB33, // DALET
|
||||
0xFB34, // HE
|
||||
0xFB35, // VAV
|
||||
0xFB36, // ZAYIN
|
||||
0, // HET
|
||||
0xFB38, // TET
|
||||
0xFB39, // YOD
|
||||
0xFB3A, // FINAL KAF
|
||||
0xFB3B, // KAF
|
||||
0xFB3C, // LAMED
|
||||
0, // FINAL MEM
|
||||
0xFB3E, // MEM
|
||||
0, // FINAL NUN
|
||||
0xFB40, // NUN
|
||||
0xFB41, // SAMEKH
|
||||
0, // AYIN
|
||||
0xFB43, // FINAL PE
|
||||
0xFB44, // PE
|
||||
0, // FINAL TSADI
|
||||
0xFB46, // TSADI
|
||||
0xFB47, // QOF
|
||||
0xFB48, // RESH
|
||||
0xFB49, // SHIN
|
||||
0xFB4A // TAV
|
||||
};
|
||||
|
||||
hb_bool_t found = unicode->compose (a, b, ab);
|
||||
|
||||
if (!found && (b & ~0x7F) == 0x0580) {
|
||||
// special-case Hebrew presentation forms that are excluded from
|
||||
// standard normalization, but wanted for old fonts
|
||||
switch (b) {
|
||||
case 0x05B4: // HIRIQ
|
||||
if (a == 0x05D9) { // YOD
|
||||
*ab = 0xFB1D;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B7: // patah
|
||||
if (a == 0x05F2) { // YIDDISH YOD YOD
|
||||
*ab = 0xFB1F;
|
||||
found = true;
|
||||
} else if (a == 0x05D0) { // ALEF
|
||||
*ab = 0xFB2E;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B8: // QAMATS
|
||||
if (a == 0x05D0) { // ALEF
|
||||
*ab = 0xFB2F;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05B9: // HOLAM
|
||||
if (a == 0x05D5) { // VAV
|
||||
*ab = 0xFB4B;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05BC: // DAGESH
|
||||
if (a >= 0x05D0 && a <= 0x05EA) {
|
||||
*ab = sDageshForms[a - 0x05D0];
|
||||
found = (*ab != 0);
|
||||
} else if (a == 0xFB2A) { // SHIN WITH SHIN DOT
|
||||
*ab = 0xFB2C;
|
||||
found = true;
|
||||
} else if (a == 0xFB2B) { // SHIN WITH SIN DOT
|
||||
*ab = 0xFB2D;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05BF: // RAFE
|
||||
switch (a) {
|
||||
case 0x05D1: // BET
|
||||
*ab = 0xFB4C;
|
||||
found = true;
|
||||
break;
|
||||
case 0x05DB: // KAF
|
||||
*ab = 0xFB4D;
|
||||
found = true;
|
||||
break;
|
||||
case 0x05E4: // PE
|
||||
*ab = 0xFB4E;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x05C1: // SHIN DOT
|
||||
if (a == 0x05E9) { // SHIN
|
||||
*ab = 0xFB2A;
|
||||
found = true;
|
||||
} else if (a == 0xFB49) { // SHIN WITH DAGESH
|
||||
*ab = 0xFB2C;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 0x05C2: // SIN DOT
|
||||
if (a == 0x05E9) { // SHIN
|
||||
*ab = 0xFB2B;
|
||||
found = true;
|
||||
} else if (a == 0xFB49) { // SHIN WITH DAGESH
|
||||
*ab = 0xFB2D;
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
set_glyph (hb_glyph_info_t &info, hb_font_t *font)
|
||||
{
|
||||
font->get_glyph (info.codepoint, 0, &info.glyph_index());
|
||||
}
|
||||
|
||||
static inline void
|
||||
output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
|
||||
{
|
||||
buffer->cur().glyph_index() = glyph;
|
||||
buffer->output_glyph (unichar);
|
||||
_hb_glyph_info_set_unicode_props (&buffer->prev(), buffer->unicode);
|
||||
}
|
||||
|
||||
static bool
|
||||
decompose (hb_font_t *font, hb_buffer_t *buffer,
|
||||
bool shortest,
|
||||
hb_codepoint_t ab)
|
||||
static inline void
|
||||
next_char (hb_buffer_t *buffer, hb_codepoint_t glyph)
|
||||
{
|
||||
hb_codepoint_t a, b, glyph;
|
||||
buffer->cur().glyph_index() = glyph;
|
||||
buffer->next_glyph ();
|
||||
}
|
||||
|
||||
if (!buffer->unicode->decompose (ab, &a, &b) ||
|
||||
(b && !font->get_glyph (b, 0, &glyph)))
|
||||
return false;
|
||||
static inline void
|
||||
skip_char (hb_buffer_t *buffer)
|
||||
{
|
||||
buffer->skip_glyph ();
|
||||
}
|
||||
|
||||
bool has_a = font->get_glyph (a, 0, &glyph);
|
||||
/* Returns 0 if didn't decompose, number of resulting characters otherwise. */
|
||||
static inline unsigned int
|
||||
decompose (hb_font_t *font, hb_buffer_t *buffer, bool shortest, hb_codepoint_t ab)
|
||||
{
|
||||
hb_codepoint_t a, b, a_glyph, b_glyph;
|
||||
|
||||
if (!decompose_func (buffer->unicode, ab, &a, &b) ||
|
||||
(b && !font->get_glyph (b, 0, &b_glyph)))
|
||||
return 0;
|
||||
|
||||
bool has_a = font->get_glyph (a, 0, &a_glyph);
|
||||
if (shortest && has_a) {
|
||||
/* Output a and b */
|
||||
output_glyph (buffer, a);
|
||||
if (b)
|
||||
output_glyph (buffer, b);
|
||||
return true;
|
||||
output_char (buffer, a, a_glyph);
|
||||
if (likely (b)) {
|
||||
output_char (buffer, b, b_glyph);
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (decompose (font, buffer, shortest, a)) {
|
||||
if (b)
|
||||
output_glyph (buffer, b);
|
||||
return true;
|
||||
unsigned int ret;
|
||||
if ((ret = decompose (font, buffer, shortest, a))) {
|
||||
if (b) {
|
||||
output_char (buffer, b, b_glyph);
|
||||
return ret + 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (has_a) {
|
||||
output_glyph (buffer, a);
|
||||
if (b)
|
||||
output_glyph (buffer, b);
|
||||
return true;
|
||||
output_char (buffer, a, a_glyph);
|
||||
if (likely (b)) {
|
||||
output_char (buffer, b, b_glyph);
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
decompose_compatibility (hb_font_t *font, hb_buffer_t *buffer,
|
||||
hb_codepoint_t u)
|
||||
/* Returns 0 if didn't decompose, number of resulting characters otherwise. */
|
||||
static inline bool
|
||||
decompose_compatibility (hb_font_t *font, hb_buffer_t *buffer, hb_codepoint_t u)
|
||||
{
|
||||
unsigned int len, i;
|
||||
hb_codepoint_t decomposed[HB_UNICODE_MAX_DECOMPOSITION_LEN];
|
||||
hb_codepoint_t glyphs[HB_UNICODE_MAX_DECOMPOSITION_LEN];
|
||||
|
||||
len = buffer->unicode->decompose_compatibility (u, decomposed);
|
||||
if (!len)
|
||||
return false;
|
||||
|
||||
hb_codepoint_t glyph;
|
||||
for (i = 0; i < len; i++)
|
||||
if (!font->get_glyph (decomposed[i], 0, &glyph))
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
output_glyph (buffer, decomposed[i]);
|
||||
if (!font->get_glyph (decomposed[i], 0, &glyphs[i]))
|
||||
return 0;
|
||||
|
||||
return true;
|
||||
for (i = 0; i < len; i++)
|
||||
output_char (buffer, decomposed[i], glyphs[i]);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void
|
||||
decompose_current_character (hb_font_t *font, hb_buffer_t *buffer,
|
||||
bool shortest)
|
||||
/* Returns true if recomposition may be benefitial. */
|
||||
static inline bool
|
||||
decompose_current_character (hb_font_t *font, hb_buffer_t *buffer, bool shortest)
|
||||
{
|
||||
hb_codepoint_t glyph;
|
||||
unsigned int len = 1;
|
||||
|
||||
/* Kind of a cute waterfall here... */
|
||||
if (shortest && font->get_glyph (buffer->cur().codepoint, 0, &glyph))
|
||||
buffer->next_glyph ();
|
||||
else if (decompose (font, buffer, shortest, buffer->cur().codepoint))
|
||||
buffer->skip_glyph ();
|
||||
next_char (buffer, glyph);
|
||||
else if ((len = decompose (font, buffer, shortest, buffer->cur().codepoint)))
|
||||
skip_char (buffer);
|
||||
else if (!shortest && font->get_glyph (buffer->cur().codepoint, 0, &glyph))
|
||||
buffer->next_glyph ();
|
||||
else if (decompose_compatibility (font, buffer, buffer->cur().codepoint))
|
||||
buffer->skip_glyph ();
|
||||
next_char (buffer, glyph);
|
||||
else if ((len = decompose_compatibility (font, buffer, buffer->cur().codepoint)))
|
||||
skip_char (buffer);
|
||||
else
|
||||
buffer->next_glyph ();
|
||||
next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
|
||||
|
||||
/*
|
||||
* A recomposition would only be useful if we decomposed into at least three
|
||||
* characters...
|
||||
*/
|
||||
return len > 2;
|
||||
}
|
||||
|
||||
static void
|
||||
decompose_multi_char_cluster (hb_font_t *font, hb_buffer_t *buffer,
|
||||
unsigned int end)
|
||||
static inline void
|
||||
handle_variation_selector_cluster (hb_font_t *font, hb_buffer_t *buffer, unsigned int end)
|
||||
{
|
||||
for (; buffer->idx < end - 1;) {
|
||||
if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
|
||||
/* The next two lines are some ugly lines... But work. */
|
||||
font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index());
|
||||
buffer->replace_glyphs (2, 1, &buffer->cur().codepoint);
|
||||
} else {
|
||||
set_glyph (buffer->cur(), font);
|
||||
buffer->next_glyph ();
|
||||
}
|
||||
}
|
||||
if (likely (buffer->idx < end)) {
|
||||
set_glyph (buffer->cur(), font);
|
||||
buffer->next_glyph ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if recomposition may be benefitial. */
|
||||
static inline bool
|
||||
decompose_multi_char_cluster (hb_font_t *font, hb_buffer_t *buffer, unsigned int end)
|
||||
{
|
||||
/* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
|
||||
for (unsigned int i = buffer->idx; i < end; i++)
|
||||
if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) {
|
||||
while (buffer->idx < end)
|
||||
buffer->next_glyph ();
|
||||
return;
|
||||
handle_variation_selector_cluster (font, buffer, end);
|
||||
return false;
|
||||
}
|
||||
|
||||
while (buffer->idx < end)
|
||||
decompose_current_character (font, buffer, false);
|
||||
/* We can be smarter here and only return true if there are at least two ccc!=0 marks.
|
||||
* But does not matter. */
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
decompose_cluster (hb_font_t *font, hb_buffer_t *buffer, bool recompose, unsigned int end)
|
||||
{
|
||||
if (likely (buffer->idx + 1 == end))
|
||||
return decompose_current_character (font, buffer, recompose);
|
||||
else
|
||||
return decompose_multi_char_cluster (font, buffer, end);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
|
||||
{
|
||||
@ -190,12 +432,13 @@ compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
|
||||
return a < b ? -1 : a == b ? 0 : +1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer,
|
||||
hb_ot_shape_normalization_mode_t mode)
|
||||
{
|
||||
bool recompose = mode != HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED;
|
||||
bool has_multichar_clusters = false;
|
||||
bool can_use_recompose = false;
|
||||
unsigned int count;
|
||||
|
||||
/* We do a fairly straightforward yet custom normalization process in three
|
||||
@ -216,17 +459,12 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer,
|
||||
if (buffer->cur().cluster != buffer->info[end].cluster)
|
||||
break;
|
||||
|
||||
if (buffer->idx + 1 == end)
|
||||
decompose_current_character (font, buffer, recompose);
|
||||
else {
|
||||
decompose_multi_char_cluster (font, buffer, end);
|
||||
has_multichar_clusters = true;
|
||||
}
|
||||
can_use_recompose = decompose_cluster (font, buffer, recompose, end) || can_use_recompose;
|
||||
}
|
||||
buffer->swap_buffers ();
|
||||
|
||||
|
||||
if (mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL && !has_multichar_clusters)
|
||||
if (mode != HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_FULL && !can_use_recompose)
|
||||
return; /* Done! */
|
||||
|
||||
|
||||
@ -281,9 +519,10 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer,
|
||||
(starter == buffer->out_len - 1 ||
|
||||
_hb_glyph_info_get_modified_combining_class (&buffer->prev()) < _hb_glyph_info_get_modified_combining_class (&buffer->cur())) &&
|
||||
/* And compose. */
|
||||
buffer->unicode->compose (buffer->out_info[starter].codepoint,
|
||||
buffer->cur().codepoint,
|
||||
&composed) &&
|
||||
compose_func (buffer->unicode,
|
||||
buffer->out_info[starter].codepoint,
|
||||
buffer->cur().codepoint,
|
||||
&composed) &&
|
||||
/* And the font has glyph for the composite. */
|
||||
font->get_glyph (composed, 0, &glyph))
|
||||
{
|
||||
@ -292,8 +531,9 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer,
|
||||
if (unlikely (buffer->in_error))
|
||||
return;
|
||||
buffer->merge_out_clusters (starter, buffer->out_len);
|
||||
buffer->out_len--; /* Remove the second composble. */
|
||||
buffer->out_len--; /* Remove the second composable. */
|
||||
buffer->out_info[starter].codepoint = composed; /* Modify starter and carry on. */
|
||||
set_glyph (buffer->out_info[starter], font);
|
||||
_hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode);
|
||||
|
||||
continue;
|
||||
|
@ -34,8 +34,8 @@
|
||||
|
||||
|
||||
/* buffer var allocations, used during the entire shaping process */
|
||||
#define unicode_props0() var1.u8[0]
|
||||
#define unicode_props1() var1.u8[1]
|
||||
#define unicode_props0() var2.u8[0]
|
||||
#define unicode_props1() var2.u8[1]
|
||||
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009,2010 Red Hat, Inc.
|
||||
* Copyright © 2010,2011 Google, Inc.
|
||||
* Copyright © 2010,2011,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
@ -32,14 +32,15 @@
|
||||
#include "hb-shaper-impl-private.hh"
|
||||
|
||||
#include "hb-ot-shape-private.hh"
|
||||
#include "hb-ot-shape-normalize-private.hh"
|
||||
#include "hb-ot-shape-complex-private.hh"
|
||||
#include "hb-ot-shape-fallback-private.hh"
|
||||
#include "hb-ot-shape-normalize-private.hh"
|
||||
|
||||
#include "hb-ot-layout-private.hh"
|
||||
#include "hb-set-private.hh"
|
||||
|
||||
|
||||
hb_tag_t common_features[] = {
|
||||
static hb_tag_t common_features[] = {
|
||||
HB_TAG('c','c','m','p'),
|
||||
HB_TAG('l','i','g','a'),
|
||||
HB_TAG('l','o','c','l'),
|
||||
@ -49,11 +50,12 @@ hb_tag_t common_features[] = {
|
||||
};
|
||||
|
||||
|
||||
hb_tag_t horizontal_features[] = {
|
||||
static hb_tag_t horizontal_features[] = {
|
||||
HB_TAG('c','a','l','t'),
|
||||
HB_TAG('c','l','i','g'),
|
||||
HB_TAG('c','u','r','s'),
|
||||
HB_TAG('k','e','r','n'),
|
||||
HB_TAG('r','c','l','t'),
|
||||
};
|
||||
|
||||
/* Note:
|
||||
@ -61,7 +63,7 @@ hb_tag_t horizontal_features[] = {
|
||||
* According to the spec, valt and vpal are also mutually exclusive.
|
||||
* But we apply them all for now.
|
||||
*/
|
||||
hb_tag_t vertical_features[] = {
|
||||
static hb_tag_t vertical_features[] = {
|
||||
HB_TAG('v','a','l','t'),
|
||||
HB_TAG('v','e','r','t'),
|
||||
HB_TAG('v','k','r','n'),
|
||||
@ -206,7 +208,6 @@ _hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
|
||||
|
||||
struct hb_ot_shape_context_t
|
||||
{
|
||||
/* Input to hb_ot_shape_internal() */
|
||||
hb_ot_shape_plan_t *plan;
|
||||
hb_font_t *font;
|
||||
hb_face_t *face;
|
||||
@ -216,34 +217,13 @@ struct hb_ot_shape_context_t
|
||||
|
||||
/* Transient stuff */
|
||||
hb_direction_t target_direction;
|
||||
hb_bool_t applied_position_complex;
|
||||
};
|
||||
|
||||
static void
|
||||
hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_map_t *map = &c->plan->map;
|
||||
|
||||
hb_mask_t global_mask = map->get_global_mask ();
|
||||
c->buffer->reset_masks (global_mask);
|
||||
|
||||
if (c->plan->shaper->setup_masks)
|
||||
c->plan->shaper->setup_masks (c->plan, c->buffer, c->font);
|
||||
|
||||
for (unsigned int i = 0; i < c->num_user_features; i++)
|
||||
{
|
||||
const hb_feature_t *feature = &c->user_features[i];
|
||||
if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
|
||||
unsigned int shift;
|
||||
hb_mask_t mask = map->get_mask (feature->tag, &shift);
|
||||
c->buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Main shaper */
|
||||
|
||||
|
||||
/* Prepare */
|
||||
|
||||
static void
|
||||
@ -286,63 +266,79 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
|
||||
|
||||
/* Substitute */
|
||||
|
||||
static void
|
||||
hb_mirror_chars (hb_ot_shape_context_t *c)
|
||||
static inline void
|
||||
hb_ot_mirror_chars (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_unicode_funcs_t *unicode = c->buffer->unicode;
|
||||
|
||||
if (HB_DIRECTION_IS_FORWARD (c->target_direction))
|
||||
return;
|
||||
|
||||
hb_unicode_funcs_t *unicode = c->buffer->unicode;
|
||||
hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m'));
|
||||
|
||||
unsigned int count = c->buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
hb_codepoint_t codepoint = unicode->mirroring (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 */
|
||||
c->buffer->info[i].mask |= rtlm_mask;
|
||||
else
|
||||
c->buffer->info[i].codepoint = codepoint;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hb_map_glyphs (hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
static inline void
|
||||
hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_codepoint_t glyph;
|
||||
hb_ot_map_t *map = &c->plan->map;
|
||||
|
||||
if (unlikely (!buffer->len))
|
||||
return;
|
||||
hb_mask_t global_mask = map->get_global_mask ();
|
||||
c->buffer->reset_masks (global_mask);
|
||||
|
||||
buffer->clear_output ();
|
||||
if (c->plan->shaper->setup_masks)
|
||||
c->plan->shaper->setup_masks (c->plan, c->buffer, c->font);
|
||||
|
||||
unsigned int count = buffer->len - 1;
|
||||
for (buffer->idx = 0; buffer->idx < count;) {
|
||||
if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
|
||||
font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &glyph);
|
||||
buffer->replace_glyphs (2, 1, &glyph);
|
||||
} else {
|
||||
font->get_glyph (buffer->cur().codepoint, 0, &glyph);
|
||||
buffer->replace_glyph (glyph);
|
||||
for (unsigned int i = 0; i < c->num_user_features; i++)
|
||||
{
|
||||
const hb_feature_t *feature = &c->user_features[i];
|
||||
if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
|
||||
unsigned int shift;
|
||||
hb_mask_t mask = map->get_mask (feature->tag, &shift);
|
||||
c->buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
|
||||
}
|
||||
}
|
||||
if (likely (buffer->idx < buffer->len)) {
|
||||
font->get_glyph (buffer->cur().codepoint, 0, &glyph);
|
||||
buffer->replace_glyph (glyph);
|
||||
}
|
||||
buffer->swap_buffers ();
|
||||
}
|
||||
|
||||
static void
|
||||
hb_substitute_default (hb_ot_shape_context_t *c)
|
||||
static inline void
|
||||
hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
|
||||
{
|
||||
hb_mirror_chars (c);
|
||||
|
||||
hb_map_glyphs (c->font, c->buffer);
|
||||
/* Normalization process sets up glyph_index(), we just copy it. */
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
buffer->info[i].codepoint = buffer->info[i].glyph_index();
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
hb_ot_substitute_default (hb_ot_shape_context_t *c)
|
||||
{
|
||||
if (c->plan->shaper->preprocess_text)
|
||||
c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
|
||||
|
||||
hb_ot_mirror_chars (c);
|
||||
|
||||
HB_BUFFER_ALLOCATE_VAR (c->buffer, glyph_index);
|
||||
|
||||
_hb_ot_shape_normalize (c->font, c->buffer,
|
||||
c->plan->shaper->normalization_preference ?
|
||||
c->plan->shaper->normalization_preference (c->plan) :
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT);
|
||||
|
||||
hb_ot_shape_setup_masks (c);
|
||||
|
||||
hb_ot_map_glyphs_fast (c->buffer);
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (c->buffer, glyph_index);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
|
||||
{
|
||||
unsigned int count = c->buffer->len;
|
||||
@ -353,7 +349,7 @@ hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static inline void
|
||||
hb_ot_substitute_complex (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_layout_substitute_start (c->font, c->buffer);
|
||||
@ -369,11 +365,17 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c)
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_ot_substitute (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_substitute_default (c);
|
||||
hb_ot_substitute_complex (c);
|
||||
}
|
||||
|
||||
/* Position */
|
||||
|
||||
static void
|
||||
hb_position_default (hb_ot_shape_context_t *c)
|
||||
static inline void
|
||||
hb_ot_position_default (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_layout_position_start (c->font, c->buffer);
|
||||
|
||||
@ -390,21 +392,10 @@ hb_position_default (hb_ot_shape_context_t *c)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hb_zero_mark_advances (hb_ot_shape_context_t *c)
|
||||
{
|
||||
unsigned int count = c->buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (_hb_glyph_info_get_general_category (&c->buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
|
||||
{
|
||||
c->buffer->pos[i].x_advance = 0;
|
||||
c->buffer->pos[i].y_advance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static inline bool
|
||||
hb_ot_position_complex (hb_ot_shape_context_t *c)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (hb_ot_layout_has_positioning (c->face))
|
||||
{
|
||||
@ -427,23 +418,22 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
|
||||
&c->buffer->pos[i].y_offset);
|
||||
}
|
||||
|
||||
c->applied_position_complex = true;
|
||||
} else
|
||||
hb_zero_mark_advances (c);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
hb_ot_layout_position_finish (c->font, c->buffer, c->plan->shaper->zero_width_attached_marks);
|
||||
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
hb_position_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED)
|
||||
static inline void
|
||||
hb_ot_position_complex_fallback (hb_ot_shape_context_t *c)
|
||||
{
|
||||
/* TODO Mark pos */
|
||||
_hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
hb_truetype_kern (hb_ot_shape_context_t *c)
|
||||
static inline void
|
||||
hb_ot_truetype_kern (hb_ot_shape_context_t *c)
|
||||
{
|
||||
/* TODO Check for kern=0 */
|
||||
unsigned int count = c->buffer->len;
|
||||
@ -467,14 +457,34 @@ hb_truetype_kern (hb_ot_shape_context_t *c)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_truetype_kern (c);
|
||||
hb_ot_truetype_kern (c);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hb_ot_position (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_ot_position_default (c);
|
||||
|
||||
hb_bool_t fallback = !hb_ot_position_complex (c);
|
||||
|
||||
if (fallback)
|
||||
hb_ot_position_complex_fallback (c);
|
||||
|
||||
if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
|
||||
hb_buffer_reverse (c->buffer);
|
||||
|
||||
if (fallback)
|
||||
hb_position_complex_fallback_visual (c);
|
||||
}
|
||||
|
||||
|
||||
/* Post-process */
|
||||
|
||||
static void
|
||||
hb_hide_zerowidth (hb_ot_shape_context_t *c)
|
||||
hb_ot_hide_zerowidth (hb_ot_shape_context_t *c)
|
||||
{
|
||||
hb_codepoint_t space;
|
||||
if (!c->font->get_glyph (' ', 0, &space))
|
||||
@ -491,7 +501,7 @@ hb_hide_zerowidth (hb_ot_shape_context_t *c)
|
||||
}
|
||||
|
||||
|
||||
/* Do it! */
|
||||
/* Pull it all together! */
|
||||
|
||||
static void
|
||||
hb_ot_shape_internal (hb_ot_shape_context_t *c)
|
||||
@ -507,43 +517,14 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
|
||||
c->buffer->clear_output ();
|
||||
|
||||
hb_set_unicode_props (c->buffer);
|
||||
|
||||
hb_form_clusters (c->buffer);
|
||||
|
||||
hb_ensure_native_direction (c->buffer);
|
||||
|
||||
_hb_ot_shape_normalize (c->font, c->buffer,
|
||||
c->plan->shaper->normalization_preference ?
|
||||
c->plan->shaper->normalization_preference (c->plan) :
|
||||
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT);
|
||||
hb_ot_substitute (c);
|
||||
hb_ot_position (c);
|
||||
|
||||
hb_ot_shape_setup_masks (c);
|
||||
|
||||
/* SUBSTITUTE */
|
||||
{
|
||||
hb_substitute_default (c);
|
||||
|
||||
hb_ot_substitute_complex (c);
|
||||
}
|
||||
|
||||
/* POSITION */
|
||||
{
|
||||
hb_position_default (c);
|
||||
|
||||
hb_ot_position_complex (c);
|
||||
|
||||
hb_bool_t position_fallback = !c->applied_position_complex;
|
||||
if (position_fallback)
|
||||
hb_position_complex_fallback (c);
|
||||
|
||||
if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
|
||||
hb_buffer_reverse (c->buffer);
|
||||
|
||||
if (position_fallback)
|
||||
hb_position_complex_fallback_visual (c);
|
||||
}
|
||||
|
||||
hb_hide_zerowidth (c);
|
||||
hb_ot_hide_zerowidth (c);
|
||||
|
||||
HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props1);
|
||||
HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props0);
|
||||
@ -568,6 +549,16 @@ _hb_ot_shape (hb_shape_plan_t *shape_plan,
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void
|
||||
hb_ot_map_glyphs_dumb (hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
font->get_glyph (buffer->cur().codepoint, 0, &buffer->cur().codepoint);
|
||||
}
|
||||
|
||||
void
|
||||
hb_ot_shape_glyphs_closure (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
@ -584,13 +575,13 @@ hb_ot_shape_glyphs_closure (hb_font_t *font,
|
||||
|
||||
/* TODO: normalization? have shapers do closure()? */
|
||||
/* TODO: Deal with mirrored chars? */
|
||||
hb_map_glyphs (font, buffer);
|
||||
hb_ot_map_glyphs_dumb (font, buffer);
|
||||
|
||||
/* Seed it. It's user's responsibility to have cleard glyphs
|
||||
* if that's what they desire. */
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
hb_set_add (glyphs, buffer->info[i].codepoint);
|
||||
glyphs->add (buffer->info[i].codepoint);
|
||||
|
||||
/* And find transitive closure. */
|
||||
hb_set_t copy;
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright © 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.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_SHAPE_H
|
||||
#define HB_OT_SHAPE_H
|
||||
|
||||
#include "hb-common.h"
|
||||
#include "hb-shape.h"
|
||||
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
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_END_DECLS
|
||||
|
||||
#endif /* HB_OT_SHAPE_H */
|
@ -66,14 +66,17 @@
|
||||
|
||||
|
||||
#undef MIN
|
||||
template <typename Type> static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
|
||||
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; }
|
||||
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])))
|
||||
template <typename Type, unsigned int n>
|
||||
static inline unsigned int ARRAY_LENGTH (const Type (&a)[n]) { return n; }
|
||||
|
||||
#define HB_STMT_START do
|
||||
#define HB_STMT_END while (0)
|
||||
@ -788,6 +791,22 @@ hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
|
||||
hb_bubble_sort (array, len, compar, (int *) NULL);
|
||||
}
|
||||
|
||||
static inline hb_bool_t
|
||||
hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
|
||||
{
|
||||
/* Pain because we don't know whether s is nul-terminated. */
|
||||
char buf[64];
|
||||
strncpy (buf, s, MIN (ARRAY_LENGTH (buf) - 1, len));
|
||||
buf[MIN (ARRAY_LENGTH (buf) - 1, len)] = '\0';
|
||||
|
||||
char *end;
|
||||
errno = 0;
|
||||
unsigned long v = strtoul (buf, &end, base);
|
||||
if (errno) return false;
|
||||
if (*end) return false;
|
||||
*out = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HB_PRIVATE_HH */
|
||||
|
@ -54,9 +54,9 @@ struct hb_set_digest_common_bits_t
|
||||
}
|
||||
|
||||
inline void add_range (hb_codepoint_t a, hb_codepoint_t b) {
|
||||
/* TODO Speedup. */
|
||||
for (unsigned int i = a; i < b + 1; i++)
|
||||
add (i);
|
||||
/* The negation here stands for ~(x-1). */
|
||||
mask &= -(1 << _hb_bit_storage (a ^ b));
|
||||
value &= mask;
|
||||
}
|
||||
|
||||
inline bool may_have (hb_codepoint_t g) const {
|
||||
@ -83,9 +83,13 @@ struct hb_set_digest_lowest_bits_t
|
||||
}
|
||||
|
||||
inline void add_range (hb_codepoint_t a, hb_codepoint_t b) {
|
||||
/* TODO Speedup. */
|
||||
for (unsigned int i = a; i < b + 1; i++)
|
||||
add (i);
|
||||
if (b - a >= sizeof (mask_t) * 8 - 1)
|
||||
mask = (mask_t) -1;
|
||||
else {
|
||||
mask_t ma = mask_for (a);
|
||||
mask_t mb = mask_for (b);
|
||||
mask |= mb + (mb - ma) - (mb < ma);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool may_have (hb_codepoint_t g) const {
|
||||
|
@ -37,7 +37,7 @@
|
||||
#undef HB_SHAPER_IMPLEMENT
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
|
||||
const hb_feature_t *user_features,
|
||||
unsigned int num_user_features,
|
||||
@ -190,11 +190,11 @@ hb_shape_plan_execute (hb_shape_plan *shape_plan,
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static long
|
||||
static unsigned int
|
||||
hb_shape_plan_hash (const hb_shape_plan_t *shape_plan)
|
||||
{
|
||||
return hb_segment_properties_hash (&shape_plan->props) +
|
||||
shape_plan->default_shaper_list ? 0 : (long) shape_plan->shaper_func;
|
||||
shape_plan->default_shaper_list ? 0 : (intptr_t) shape_plan->shaper_func;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -47,7 +47,7 @@ hb_shape_plan_create (hb_face_t *face,
|
||||
unsigned int num_user_features,
|
||||
const char * const *shaper_list);
|
||||
|
||||
hb_shape_plan_t *
|
||||
HB_INTERNAL hb_shape_plan_t *
|
||||
hb_shape_plan_create_cached (hb_face_t *face,
|
||||
const hb_segment_properties_t *props,
|
||||
const hb_feature_t *user_features,
|
||||
|
@ -29,7 +29,7 @@
|
||||
#endif /* HB_SHAPER_LIST_HH */ /* Dummy header guards */
|
||||
|
||||
/* v--- Add new shapers in the right place here. */
|
||||
#ifdef HAVE_GRAPHITE
|
||||
#ifdef HAVE_GRAPHITE2
|
||||
HB_SHAPER_IMPLEMENT (graphite2)
|
||||
#endif
|
||||
#ifdef HAVE_UNISCRIBE
|
||||
|
@ -51,7 +51,7 @@ _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_blob = Sanitizer<hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
|
||||
tt->hhea = Sanitizer<hhea>::lock_instance (tt->hhea_blob);
|
||||
|
||||
return tt;
|
||||
@ -76,168 +76,4 @@ _get_hhea (hb_face_t *face)
|
||||
* 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
|
||||
|
||||
|
@ -80,53 +80,13 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
hb_codepoint_t *ab)
|
||||
{
|
||||
*ab = 0;
|
||||
/* XXX, this belongs to indic normalizer. */
|
||||
if ((FLAG (general_category (a)) &
|
||||
(FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) |
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))))
|
||||
return false;
|
||||
/* XXX, add composition-exclusion exceptions to Indic shaper. */
|
||||
if (a == 0x09AF && b == 0x09BC) { *ab = 0x09DF; return true; }
|
||||
if (unlikely (!a || !b)) return false;
|
||||
return func.compose (this, a, b, ab, user_data.compose);
|
||||
}
|
||||
|
||||
inline hb_bool_t decompose (hb_codepoint_t ab,
|
||||
hb_codepoint_t *a, hb_codepoint_t *b)
|
||||
{
|
||||
/* XXX FIXME, move these to complex shapers and propagage to normalizer.*/
|
||||
switch (ab) {
|
||||
case 0x0AC9 : return false;
|
||||
|
||||
case 0x0931 : return false;
|
||||
case 0x0B94 : return false;
|
||||
|
||||
/* These ones have Unicode decompositions, but we do it
|
||||
* this way to be close to what Uniscribe does. */
|
||||
case 0x0DDA : *a = 0x0DD9; *b= 0x0DDA; return true;
|
||||
case 0x0DDC : *a = 0x0DD9; *b= 0x0DDC; return true;
|
||||
case 0x0DDD : *a = 0x0DD9; *b= 0x0DDD; return true;
|
||||
case 0x0DDE : *a = 0x0DD9; *b= 0x0DDE; return true;
|
||||
|
||||
case 0x0F77 : *a = 0x0FB2; *b= 0x0F81; return true;
|
||||
case 0x0F79 : *a = 0x0FB3; *b= 0x0F81; return true;
|
||||
case 0x17BE : *a = 0x17C1; *b= 0x17BE; return true;
|
||||
case 0x17BF : *a = 0x17C1; *b= 0x17BF; return true;
|
||||
case 0x17C0 : *a = 0x17C1; *b= 0x17C0; return true;
|
||||
case 0x17C4 : *a = 0x17C1; *b= 0x17C4; return true;
|
||||
case 0x17C5 : *a = 0x17C1; *b= 0x17C5; return true;
|
||||
case 0x1925 : *a = 0x1920; *b= 0x1923; return true;
|
||||
case 0x1926 : *a = 0x1920; *b= 0x1924; return true;
|
||||
case 0x1B3C : *a = 0x1B42; *b= 0x1B3C; return true;
|
||||
case 0x1112E : *a = 0x11127; *b= 0x11131; return true;
|
||||
case 0x1112F : *a = 0x11127; *b= 0x11132; return true;
|
||||
#if 0
|
||||
case 0x0B57 : *a = 0xno decomp, -> RIGHT; return true;
|
||||
case 0x1C29 : *a = 0xno decomp, -> LEFT; return true;
|
||||
case 0xA9C0 : *a = 0xno decomp, -> RIGHT; return true;
|
||||
case 0x111BF : *a = 0xno decomp, -> ABOVE; return true;
|
||||
#endif
|
||||
}
|
||||
*a = ab; *b = 0;
|
||||
return func.decompose (this, ab, a, b, user_data.decompose);
|
||||
}
|
||||
@ -223,17 +183,89 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
||||
};
|
||||
|
||||
|
||||
#ifdef HAVE_GLIB
|
||||
extern HB_INTERNAL const hb_unicode_funcs_t _hb_glib_unicode_funcs;
|
||||
#define _hb_unicode_funcs_default _hb_glib_unicode_funcs
|
||||
#elif defined(HAVE_ICU)
|
||||
extern HB_INTERNAL const hb_unicode_funcs_t _hb_icu_unicode_funcs;
|
||||
#define _hb_unicode_funcs_default _hb_icu_unicode_funcs
|
||||
#else
|
||||
#define HB_UNICODE_FUNCS_NIL 1
|
||||
extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
|
||||
#define _hb_unicode_funcs_default _hb_unicode_funcs_nil
|
||||
#endif
|
||||
|
||||
|
||||
/* Modified combining marks */
|
||||
|
||||
/* Hebrew
|
||||
*
|
||||
* We permute the "fixed-position" classes 10-26 into the order
|
||||
* described in the SBL Hebrew manual:
|
||||
*
|
||||
* http://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
|
||||
*
|
||||
* (as recommended by:
|
||||
* http://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering-t6751.0.html)
|
||||
*
|
||||
* More details here:
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=662055
|
||||
*/
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC10 22 /* sheva */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC11 15 /* hataf segol */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC12 16 /* hataf patah */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC13 17 /* hataf qamats */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC14 23 /* hiriq */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC23 13 /* rafe */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC24 10 /* shin dot */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC25 11 /* sin dot */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC26 26 /* point varika */
|
||||
|
||||
/*
|
||||
* Arabic
|
||||
*
|
||||
* Modify to move Shadda (ccc=33) before other marks. See:
|
||||
* http://unicode.org/faq/normalization.html#8
|
||||
* http://unicode.org/faq/normalization.html#9
|
||||
*/
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC27 28 /* fathatan */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC28 29 /* dammatan */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC29 30 /* kasratan */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC30 31 /* fatha */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC31 32 /* damma */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC32 33 /* kasra */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC33 27 /* shadda */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC34 34 /* sukun */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC35 35 /* superscript alef */
|
||||
|
||||
/* Syriac */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC36 36 /* superscript alaph */
|
||||
|
||||
/* Telugu
|
||||
*
|
||||
* Modify Telugu length marks (ccc=84, ccc=91).
|
||||
* These are the only matras in the main Indic scripts range that have
|
||||
* a non-zero ccc. That makes them reorder with the Halant that is
|
||||
* ccc=9. Just zero them, we don't need them in our Indic shaper.
|
||||
*/
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */
|
||||
|
||||
/* Thai
|
||||
*
|
||||
* Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9).
|
||||
* Assign 3, which is unassigned otherwise.
|
||||
* Uniscribe does this reordering too.
|
||||
*/
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC107 107 /* mai * */
|
||||
|
||||
/* Lao */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
|
||||
|
||||
/* Tibetan */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC130 130 /* sign i */
|
||||
#define HB_MODIFIED_COMBINING_CLASS_CCC132 132 /* sign u */
|
||||
|
||||
|
||||
#endif /* HB_UNICODE_PRIVATE_HH */
|
||||
|
@ -109,12 +109,44 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED
|
||||
}
|
||||
|
||||
|
||||
#define HB_UNICODE_FUNCS_IMPLEMENT_SET \
|
||||
HB_UNICODE_FUNCS_IMPLEMENT (glib) \
|
||||
HB_UNICODE_FUNCS_IMPLEMENT (icu) \
|
||||
HB_UNICODE_FUNCS_IMPLEMENT (nil) \
|
||||
/* ^--- Add new callbacks before nil */
|
||||
|
||||
#define hb_nil_get_unicode_funcs hb_unicode_funcs_get_empty
|
||||
|
||||
/* Prototype them all */
|
||||
#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
|
||||
extern "C" hb_unicode_funcs_t *hb_##set##_get_unicode_funcs (void);
|
||||
HB_UNICODE_FUNCS_IMPLEMENT_SET
|
||||
#undef HB_UNICODE_FUNCS_IMPLEMENT
|
||||
|
||||
|
||||
hb_unicode_funcs_t *
|
||||
hb_unicode_funcs_get_default (void)
|
||||
{
|
||||
return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_default);
|
||||
#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
|
||||
return hb_##set##_get_unicode_funcs ();
|
||||
|
||||
#ifdef HAVE_GLIB
|
||||
HB_UNICODE_FUNCS_IMPLEMENT(glib)
|
||||
#elif defined(HAVE_ICU)
|
||||
HB_UNICODE_FUNCS_IMPLEMENT(icu)
|
||||
#else
|
||||
#define HB_UNICODE_FUNCS_NIL 1
|
||||
HB_UNICODE_FUNCS_IMPLEMENT(nil)
|
||||
#endif
|
||||
|
||||
#undef HB_UNICODE_FUNCS_IMPLEMENT
|
||||
}
|
||||
|
||||
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
|
||||
#pragma message("Could not find any Unicode functions implementation, you have to provide your own.")
|
||||
#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS.")
|
||||
#endif
|
||||
|
||||
hb_unicode_funcs_t *
|
||||
hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
|
||||
{
|
||||
@ -140,7 +172,6 @@ hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
|
||||
}
|
||||
|
||||
|
||||
extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
|
||||
const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
|
||||
HB_OBJECT_HEADER_STATIC,
|
||||
|
||||
@ -287,6 +318,7 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
|
||||
}
|
||||
|
||||
|
||||
/* See hb-unicode-private.hh for details. */
|
||||
const uint8_t
|
||||
_hb_modified_combining_class[256] =
|
||||
{
|
||||
@ -298,58 +330,37 @@ _hb_modified_combining_class[256] =
|
||||
9, /* HB_UNICODE_COMBINING_CLASS_VIRAMA */
|
||||
|
||||
/* Hebrew */
|
||||
|
||||
/*
|
||||
* We permute the "fixed-position" classes 10-26 into the order
|
||||
* described in the SBL Hebrew manual:
|
||||
*
|
||||
* http://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
|
||||
*
|
||||
* (as recommended by:
|
||||
* http://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering-t6751.0.html)
|
||||
*
|
||||
* More details here:
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=662055
|
||||
*/
|
||||
22, /* HB_UNICODE_COMBINING_CLASS_CCC10 sheva */
|
||||
15, /* HB_UNICODE_COMBINING_CLASS_CCC11 hataf segol */
|
||||
16, /* HB_UNICODE_COMBINING_CLASS_CCC12 hataf patah*/
|
||||
17, /* HB_UNICODE_COMBINING_CLASS_CCC13 hataf qamats */
|
||||
23, /* HB_UNICODE_COMBINING_CLASS_CCC14 hiriq */
|
||||
18, /* HB_UNICODE_COMBINING_CLASS_CCC15 tsere */
|
||||
19, /* HB_UNICODE_COMBINING_CLASS_CCC16 segol */
|
||||
20, /* HB_UNICODE_COMBINING_CLASS_CCC17 patah */
|
||||
21, /* HB_UNICODE_COMBINING_CLASS_CCC18 qamats */
|
||||
14, /* HB_UNICODE_COMBINING_CLASS_CCC19 holam */
|
||||
24, /* HB_UNICODE_COMBINING_CLASS_CCC20 qubuts */
|
||||
12, /* HB_UNICODE_COMBINING_CLASS_CCC21 dagesh */
|
||||
25, /* HB_UNICODE_COMBINING_CLASS_CCC22 meteg */
|
||||
13, /* HB_UNICODE_COMBINING_CLASS_CCC23 rafe */
|
||||
10, /* HB_UNICODE_COMBINING_CLASS_CCC24 shin dot */
|
||||
11, /* HB_UNICODE_COMBINING_CLASS_CCC25 sin dot */
|
||||
|
||||
26, /* HB_UNICODE_COMBINING_CLASS_CCC26 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC10,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC11,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC12,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC13,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC14,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC15,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC16,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC17,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC18,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC19,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC20,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC21,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC22,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC23,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC24,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC25,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC26,
|
||||
|
||||
/* Arabic */
|
||||
|
||||
/*
|
||||
* Modify to move Shadda (ccc=33) before other marks. See:
|
||||
* http://unicode.org/faq/normalization.html#8
|
||||
* http://unicode.org/faq/normalization.html#9
|
||||
*/
|
||||
28, /* HB_UNICODE_COMBINING_CLASS_CCC27 */
|
||||
29, /* HB_UNICODE_COMBINING_CLASS_CCC28 */
|
||||
30, /* HB_UNICODE_COMBINING_CLASS_CCC29 */
|
||||
31, /* HB_UNICODE_COMBINING_CLASS_CCC30 */
|
||||
32, /* HB_UNICODE_COMBINING_CLASS_CCC31 */
|
||||
33, /* HB_UNICODE_COMBINING_CLASS_CCC32 */
|
||||
27, /* HB_UNICODE_COMBINING_CLASS_CCC33 shadda */
|
||||
|
||||
34, /* HB_UNICODE_COMBINING_CLASS_CCC34 */
|
||||
35, /* HB_UNICODE_COMBINING_CLASS_CCC35 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC27,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC28,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC29,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC30,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC31,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC32,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC33,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC34,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC35,
|
||||
|
||||
/* Syriac */
|
||||
36, /* HB_UNICODE_COMBINING_CLASS_CCC36 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC36,
|
||||
|
||||
37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
@ -357,41 +368,28 @@ _hb_modified_combining_class[256] =
|
||||
80, 81, 82, 83,
|
||||
|
||||
/* Telugu */
|
||||
|
||||
/*
|
||||
* Modify Telugu length marks (ccc=84, ccc=91).
|
||||
* These are the only matras in the main Indic scripts range that have
|
||||
* a non-zero ccc. That makes them reorder with the Halant that is
|
||||
* ccc=9. Just zero them, we don't need them in our Indic shaper.
|
||||
*/
|
||||
0, /* HB_UNICODE_COMBINING_CLASS_CCC84 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC84,
|
||||
85, 86, 87, 88, 89, 90,
|
||||
0, /* HB_UNICODE_COMBINING_CLASS_CCC91 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC91,
|
||||
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
|
||||
|
||||
/* Thai */
|
||||
|
||||
/*
|
||||
* Modify U+0E38 and U+0E39 (ccc=104) to be reordered before U+0E3A (ccc=9).
|
||||
* Uniscribe does this too.
|
||||
*/
|
||||
3, /* HB_UNICODE_COMBINING_CLASS_CCC103 */
|
||||
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC103,
|
||||
104, 105, 106,
|
||||
107, /* HB_UNICODE_COMBINING_CLASS_CCC107 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC107,
|
||||
108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
|
||||
|
||||
/* Lao */
|
||||
118, /* HB_UNICODE_COMBINING_CLASS_CCC118 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC118,
|
||||
119, 120, 121,
|
||||
122, /* HB_UNICODE_COMBINING_CLASS_CCC122 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC122,
|
||||
123, 124, 125, 126, 127, 128,
|
||||
|
||||
/* Tibetan */
|
||||
129, /* HB_UNICODE_COMBINING_CLASS_CCC129 */
|
||||
130, /* HB_UNICODE_COMBINING_CLASS_CCC130 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC129,
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC130,
|
||||
131,
|
||||
132, /* HB_UNICODE_COMBINING_CLASS_CCC133 */
|
||||
HB_MODIFIED_COMBINING_CLASS_CCC132,
|
||||
133, 134, 135, 136, 137, 138, 139,
|
||||
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2012 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_UNISCRIBE_PRIVATE_HH
|
||||
#define HB_UNISCRIBE_PRIVATE_HH
|
||||
|
||||
#include "hb-private.hh"
|
||||
|
||||
#include "hb-uniscribe.h"
|
||||
|
||||
|
||||
HB_INTERNAL hb_bool_t
|
||||
_hb_uniscribe_shape (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
const hb_feature_t *features,
|
||||
unsigned int num_features);
|
||||
|
||||
|
||||
#endif /* HB_UNISCRIBE_PRIVATE_HH */
|
@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#define HB_SHAPER uniscribe
|
||||
#include "hb-shaper-impl-private.hh"
|
||||
@ -197,15 +198,15 @@ _hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
|
||||
struct hb_uniscribe_shaper_shape_plan_data_t {};
|
||||
|
||||
hb_uniscribe_shaper_shape_plan_data_t *
|
||||
_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
|
||||
const hb_feature_t *user_features,
|
||||
unsigned int num_user_features)
|
||||
_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
|
||||
const hb_feature_t *user_features HB_UNUSED,
|
||||
unsigned int num_user_features HB_UNUSED)
|
||||
{
|
||||
return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
}
|
||||
|
||||
void
|
||||
_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data)
|
||||
_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
@ -37,11 +37,3 @@
|
||||
#if defined(HB_ATOMIC_INT_NIL) || defined(HB_MUTEX_IMPL_NIL)
|
||||
#pragma message("To suppress these warnings, define HB_NO_MT.")
|
||||
#endif
|
||||
|
||||
|
||||
#include "hb-unicode-private.hh"
|
||||
|
||||
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
|
||||
#pragma message("Could not find any Unicode functions implementation, you have to provide your own.")
|
||||
#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS.")
|
||||
#endif
|
||||
|
@ -88,7 +88,16 @@ main (int argc, char **argv)
|
||||
hb_blob_destroy (blob);
|
||||
blob = NULL;
|
||||
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_funcs (font);
|
||||
#endif
|
||||
|
||||
unsigned int len = argc - 3;
|
||||
hb_codepoint_t glyphs[2] = {strtol (argv[3], NULL, 0), argc > 4 ? strtol (argv[4], NULL, 0) : (hb_codepoint_t) -1};
|
||||
hb_codepoint_t glyphs[2];
|
||||
if (!hb_font_glyph_from_string (font, argv[3], -1, &glyphs[0]) ||
|
||||
(argc > 4 &&
|
||||
!hb_font_glyph_from_string (font, argv[4], -1, &glyphs[1])))
|
||||
return 2;
|
||||
return !hb_ot_layout_would_substitute_lookup (face, glyphs, len, strtol (argv[2], NULL, 0));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user