Bug 782908 - Updated harfbuzz to current version r=jfkthame

This commit is contained in:
Jacek Caban 2012-08-18 10:16:43 +02:00
parent 409cf6bf73
commit 00b438ec82
58 changed files with 1727 additions and 1090 deletions

View File

@ -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.

View File

@ -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 \

View File

@ -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 \

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);
*/

View File

@ -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;

View File

@ -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 */

View File

@ -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)
{
}

View File

@ -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 */

View File

@ -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)
{
}

View File

@ -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); }

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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);
}

View File

@ -33,7 +33,6 @@
#include <unicode/uscript.h>
HB_BEGIN_DECLS

View File

@ -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 }

View File

@ -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));

View File

@ -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);

View File

@ -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++)

View File

@ -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);

View File

@ -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)

View File

@ -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);
}

View File

@ -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,

View File

@ -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];

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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 */
};

View File

@ -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,

View File

@ -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 */

View 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);
}

View File

@ -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,

View File

@ -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;

View File

@ -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]

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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 {

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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,

View File

@ -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 */

View File

@ -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)
{
}

View File

@ -29,7 +29,9 @@
#include "hb.h"
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif
#include <windows.h>
HB_BEGIN_DECLS

View File

@ -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

View File

@ -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));
}