Merge branch 'master' into cff-subset

This commit is contained in:
Michiharu Ariza 2018-10-10 18:36:35 -07:00
commit b5aa5dbb11
27 changed files with 499 additions and 263 deletions

View File

@ -27,6 +27,17 @@ jobs:
# Ignoring assembler complains, https://stackoverflow.com/a/39867021
- run: make 2>&1 | grep -v -e '^/var/folders/*' -e '^[[:space:]]*\.section' -e '^[[:space:]]*\^[[:space:]]*~*'
macos-notest-ios:
macos:
xcode: "10.0.0"
steps:
- checkout
- run: brew update-reset
- run: brew install cmake
# not needed to be a framework but we like to test that also
- run: cmake -DBUILD_FRAMEWORK=ON -H. -Bbuild -GXcode -DHB_IOS=ON
- run: cd build && xcodebuild -sdk iphoneos12.0 -configuration Release build -arch arm64
distcheck:
docker:
- image: ubuntu:17.10
@ -274,6 +285,7 @@ workflows:
# macOS
- macos-llvm-gcc-4.2
- macos-notest-apple-gcc-i686-4.2
- macos-notest-ios
# both autotools and cmake
- distcheck

View File

@ -82,12 +82,21 @@ if (HB_CHECK)
endif ()
endif ()
set (HB_DISABLE_SUBSET OFF)
set (HB_DISABLE_TESTS OFF)
option(HB_IOS "Apply iOS specific build flags" OFF)
if (HB_IOS)
# We should fix their issue and enable them
set (HB_DISABLE_SUBSET ON)
set (HB_DISABLE_TESTS ON)
set (HB_HAVE_CORETEXT OFF)
endif ()
include_directories(AFTER
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src
)
add_definitions(-DHAVE_OT)
add_definitions(-DHAVE_FALLBACK)
# We need PYTHON_EXECUTABLE to be set for running the tests...
@ -359,12 +368,32 @@ if (APPLE AND HB_HAVE_CORETEXT)
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-coretext.cc)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-coretext.h)
if (HB_IOS)
find_library(COREFOUNDATION CoreFoundation)
if (COREFOUNDATION)
list(APPEND THIRD_PARTY_LIBS ${COREFOUNDATION})
endif ()
mark_as_advanced(COREFOUNDATION)
find_library(CORETEXT CoreText)
if (CORETEXT)
list(APPEND THIRD_PARTY_LIBS ${CORETEXT})
endif ()
mark_as_advanced(CORETEXT)
find_library(COREGRAPHICS CoreGraphics)
if (COREGRAPHICS)
list(APPEND THIRD_PARTY_LIBS ${COREGRAPHICS})
endif ()
mark_as_advanced(COREGRAPHICS)
else ()
find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices)
if (APPLICATION_SERVICES_FRAMEWORK)
list(APPEND THIRD_PARTY_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
endif (APPLICATION_SERVICES_FRAMEWORK)
endif ()
mark_as_advanced(APPLICATION_SERVICES_FRAMEWORK)
endif ()
endif ()
if (WIN32 AND HB_HAVE_UNISCRIBE)
@ -527,12 +556,14 @@ add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_heade
target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
## Define harfbuzz-subset library
add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
add_dependencies(harfbuzz-subset harfbuzz)
target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
if (NOT HB_DISABLE_SUBSET)
add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
add_dependencies(harfbuzz-subset harfbuzz)
target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
if (BUILD_SHARED_LIBS)
if (BUILD_SHARED_LIBS)
set_target_properties(harfbuzz harfbuzz-subset PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)
endif ()
endif ()
if (UNIX OR MINGW)
@ -549,7 +580,9 @@ if (UNIX OR MINGW)
set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "m") # libm
set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C)
if (NOT HB_DISABLE_SUBSET)
set_target_properties(harfbuzz-subset PROPERTIES LINKER_LANGUAGE C)
endif ()
# No threadsafe statics as we do it ourselves
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics")
@ -828,8 +861,9 @@ if (UNIX AND CMAKE_GENERATOR STREQUAL "Ninja")
endif ()
## src/ executables
foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
if (NOT HB_DISABLE_TESTS)
## src/ executables
foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
set (prog_name ${prog})
if (${prog_name} STREQUAL "test")
# test can not be used as a valid executable name on cmake, lets special case it
@ -837,11 +871,11 @@ foreach (prog main test test-would-substitute test-size-params test-buffer-seria
endif ()
add_executable(${prog_name} ${PROJECT_SOURCE_DIR}/src/${prog}.cc)
target_link_libraries(${prog_name} harfbuzz ${THIRD_PARTY_LIBS})
endforeach ()
set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN")
endforeach ()
set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN")
## Tests
if (UNIX OR MINGW)
## Tests
if (UNIX OR MINGW)
if (BUILD_SHARED_LIBS)
# generate harfbuzz.def after build completion
add_custom_command(TARGET harfbuzz POST_BUILD
@ -871,8 +905,9 @@ if (UNIX OR MINGW)
PROPERTIES
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src
SKIP_RETURN_CODE 77)
endif ()
endif ()
# Needs to come last so that variables defined above are passed to
# subdirectories.
add_subdirectory(test)
# Needs to come last so that variables defined above are passed to
# subdirectories.
add_subdirectory(test)
endif ()

View File

@ -148,12 +148,6 @@ AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread)
dnl ==========================================================================
have_ot=true
if $have_ot; then
AC_DEFINE(HAVE_OT, 1, [Have native OpenType Layout backend])
fi
AM_CONDITIONAL(HAVE_OT, $have_ot)
have_fallback=true
if $have_fallback; then
AC_DEFINE(HAVE_FALLBACK, 1, [Have simple TrueType Layout backend])

View File

@ -29,11 +29,9 @@ HBSOURCES = $(HB_BASE_sources)
HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
HBHEADERS = $(HB_BASE_headers)
if HAVE_OT
HBSOURCES += $(HB_OT_sources)
HBSOURCES += $(HB_OT_RAGEL_GENERATED_sources)
HBHEADERS += $(HB_OT_headers)
endif
if HAVE_FALLBACK
HBSOURCES += $(HB_FALLBACK_sources)

View File

@ -260,6 +260,12 @@ struct Lookup
}
}
inline const T& get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
{
const T *v = get_value (glyph_id, num_glyphs);
return v ? *v : Null(T);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);

View File

@ -44,21 +44,38 @@ namespace AAT {
using namespace OT;
struct KerxSubTableHeader
{
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this)));
}
public:
HBUINT32 length;
HBUINT32 coverage;
HBUINT32 tupleCount;
public:
DEFINE_SIZE_STATIC (12);
};
struct KerxSubTableFormat0
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{
hb_glyph_pair_t pair = {left, right};
int i = pairs.bsearch (pair);
if (i == -1)
return 0;
return pairs[i].get_kerning ();
return i == -1 ? 0 : pairs[i].get_kerning ();
}
inline bool apply (hb_aat_apply_context_t *c) const
{
TRACE_APPLY (this);
if (!c->plan->requested_kerning)
return false;
hb_kern_machine_t<KerxSubTableFormat0> machine (*this);
machine.kern (c->font, c->buffer, c->plan->kern_mask);
@ -73,10 +90,11 @@ struct KerxSubTableFormat0
}
protected:
KerxSubTableHeader header;
BinSearchArrayOf<KernPair, HBUINT32>
pairs; /* Sorted kern records. */
public:
DEFINE_SIZE_ARRAY (16, pairs);
DEFINE_SIZE_ARRAY (28, pairs);
};
struct KerxSubTableFormat1
@ -85,6 +103,9 @@ struct KerxSubTableFormat1
{
TRACE_APPLY (this);
if (!c->plan->requested_kerning)
return false;
/* TODO */
return_trace (true);
@ -98,23 +119,24 @@ struct KerxSubTableFormat1
}
protected:
KerxSubTableHeader header;
StateTable<HBUINT16> stateHeader;
LOffsetTo<ArrayOf<HBUINT16> > valueTable;
public:
DEFINE_SIZE_STATIC (20);
DEFINE_SIZE_STATIC (32);
};
struct KerxSubTableFormat2
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
const char *end, unsigned int num_glyphs) const
unsigned int num_glyphs) const
{
unsigned int l = *(this+leftClassTable).get_value (left, num_glyphs);
unsigned int r = *(this+rightClassTable).get_value (right, num_glyphs);
unsigned int l = (this+leftClassTable).get_value_or_null (left, num_glyphs);
unsigned int r = (this+rightClassTable).get_value_or_null (right, num_glyphs);
unsigned int offset = l + r;
const FWORD *v = &StructAtOffset<FWORD> (&(this+array), offset);
if (unlikely ((const char *) v < (const char *) &array ||
(const char *) v > (const char *) end - 2))
(const char *) v + v->static_size - (const char *) this <= header.length))
return 0;
return *v;
}
@ -123,8 +145,10 @@ struct KerxSubTableFormat2
{
TRACE_APPLY (this);
if (!c->plan->requested_kerning)
return false;
accelerator_t accel (*this,
c->sanitizer.end,
c->face->get_num_glyphs ());
hb_kern_machine_t<accelerator_t> machine (accel);
machine.kern (c->font, c->buffer, c->plan->kern_mask);
@ -145,20 +169,20 @@ struct KerxSubTableFormat2
struct accelerator_t
{
const KerxSubTableFormat2 &table;
const char *end;
unsigned int num_glyphs;
inline accelerator_t (const KerxSubTableFormat2 &table_,
const char *end_, unsigned int num_glyphs_)
: table (table_), end (end_), num_glyphs (num_glyphs_) {}
unsigned int num_glyphs_)
: table (table_), num_glyphs (num_glyphs_) {}
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{
return table.get_kerning (left, right, end, num_glyphs);
return table.get_kerning (left, right, num_glyphs);
}
};
protected:
KerxSubTableHeader header;
HBUINT32 rowWidth; /* The width, in bytes, of a row in the table. */
LOffsetTo<Lookup<HBUINT16> >
leftClassTable; /* Offset from beginning of this subtable to
@ -166,11 +190,10 @@ struct KerxSubTableFormat2
LOffsetTo<Lookup<HBUINT16> >
rightClassTable;/* Offset from beginning of this subtable to
* right-hand class table. */
LOffsetTo<FWORD>
array; /* Offset from beginning of this subtable to
LOffsetTo<FWORD> array; /* Offset from beginning of this subtable to
* the start of the kerning array. */
public:
DEFINE_SIZE_STATIC (16);
DEFINE_SIZE_STATIC (28);
};
struct KerxSubTableFormat4
@ -193,17 +216,60 @@ struct KerxSubTableFormat4
}
protected:
KerxSubTableHeader header;
public:
DEFINE_SIZE_STATIC (1);
DEFINE_SIZE_STATIC (12);
};
struct KerxSubTableFormat6
{
enum Flags
{
ValuesAreLong = 0x00000001,
};
inline bool is_long (void) const { return flags & ValuesAreLong; }
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
unsigned int num_glyphs) const
{
if (is_long ())
{
const U::Long &t = u.l;
unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
unsigned int offset = l + r;
const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32));
if (unlikely ((const char *) v < (const char *) &t.array ||
(const char *) v + v->static_size - (const char *) this <= header.length))
return 0;
return *v;
}
else
{
const U::Short &t = u.s;
unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
unsigned int offset = l + r;
const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD));
if (unlikely ((const char *) v < (const char *) &t.array ||
(const char *) v + v->static_size - (const char *) this <= header.length))
return 0;
return *v;
}
}
inline bool apply (hb_aat_apply_context_t *c) const
{
TRACE_APPLY (this);
/* TODO */
if (!c->plan->requested_kerning)
return false;
accelerator_t accel (*this,
c->face->get_num_glyphs ());
hb_kern_machine_t<accelerator_t> machine (accel);
machine.kern (c->font, c->buffer, c->plan->kern_mask);
return_trace (true);
}
@ -212,30 +278,63 @@ struct KerxSubTableFormat6
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
rowIndexTable.sanitize (c, this) &&
columnIndexTable.sanitize (c, this) &&
kerningArray.sanitize (c, this) &&
kerningVector.sanitize (c, this)));
is_long () ?
(
u.l.rowIndexTable.sanitize (c, this) &&
u.l.columnIndexTable.sanitize (c, this) &&
u.l.array.sanitize (c, this)
) : (
u.s.rowIndexTable.sanitize (c, this) &&
u.s.columnIndexTable.sanitize (c, this) &&
u.s.array.sanitize (c, this)
)));
}
struct accelerator_t
{
const KerxSubTableFormat6 &table;
unsigned int num_glyphs;
inline accelerator_t (const KerxSubTableFormat6 &table_,
unsigned int num_glyphs_)
: table (table_), num_glyphs (num_glyphs_) {}
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{
return table.get_kerning (left, right, num_glyphs);
}
};
protected:
KerxSubTableHeader header;
HBUINT32 flags;
HBUINT16 rowCount;
HBUINT16 columnCount;
union U
{
struct Long
{
LOffsetTo<Lookup<HBUINT32> > rowIndexTable;
LOffsetTo<Lookup<HBUINT32> > columnIndexTable;
LOffsetTo<FWORD32> array;
} l;
struct Short
{
LOffsetTo<Lookup<HBUINT16> > rowIndexTable;
LOffsetTo<Lookup<HBUINT16> > columnIndexTable;
LOffsetTo<Lookup<HBUINT16> > kerningArray;
LOffsetTo<Lookup<HBUINT16> > kerningVector;
LOffsetTo<FWORD> array;
} s;
} u;
public:
DEFINE_SIZE_STATIC (24);
DEFINE_SIZE_STATIC (32);
};
struct KerxTable
{
friend struct kerx;
inline unsigned int get_size (void) const { return length; }
inline unsigned int get_type (void) const { return coverage & SubtableType; }
inline unsigned int get_size (void) const { return u.header.length; }
inline unsigned int get_type (void) const { return u.header.coverage & SubtableType; }
enum Coverage
{
@ -269,19 +368,16 @@ struct KerxTable
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (!length.sanitize (c) ||
length < min_size ||
!c->check_range (this, length))
if (!u.header.sanitize (c) ||
!c->check_range (this, u.header.length))
return_trace (false);
return_trace (dispatch (c));
}
protected:
HBUINT32 length;
HBUINT32 coverage;
HBUINT32 tupleCount;
union {
KerxSubTableHeader header;
KerxSubTableFormat0 format0;
KerxSubTableFormat1 format1;
KerxSubTableFormat2 format2;
@ -312,14 +408,15 @@ struct kerx
{
bool reverse;
if (table->u.header.coverage & (KerxTable::CrossStream | KerxTable::Variation) ||
table->u.header.tupleCount)
goto skip; /* We do NOT handle cross-stream or variation kerning. */
if (HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
bool (table->coverage & KerxTable::Vertical))
bool (table->u.header.coverage & KerxTable::Vertical))
goto skip;
if (table->coverage & KerxTable::CrossStream)
goto skip; /* We do NOT handle cross-stream kerning. None of Apple fonts use it. */
reverse = bool (table->coverage & KerxTable::Backwards) !=
reverse = bool (table->u.header.coverage & KerxTable::Backwards) !=
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
if (!c->buffer->message (c->font, "start kerx subtable %d", c->lookup_index))

View File

@ -54,6 +54,21 @@ _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
*blob = hb_ot_face_data (face)->morx.get_blob ();
return morx;
}
static inline const AAT::kerx&
_get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
{
if (blob)
*blob = hb_blob_get_empty ();
return Null(AAT::kerx);
}
const AAT::kerx& kerx = *(hb_ot_face_data (face)->kerx.get ());
if (blob)
*blob = hb_ot_face_data (face)->kerx.get_blob ();
return kerx;
}
hb_bool_t
hb_aat_layout_has_substitution (hb_face_t *face)
@ -73,19 +88,21 @@ hb_aat_layout_substitute (hb_ot_shape_plan_t *plan,
morx.apply (&c);
}
hb_bool_t
hb_aat_layout_has_positioning (hb_face_t *face)
{
return _get_kerx (face).has_data ();
}
void
hb_aat_layout_position (hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
#if 0
hb_blob_t *blob;
const AAT::ankr& ankr = _get_ankr (font->face, &blob);
const AAT::kerx& kerx = _get_kerx (font->face, &blob);
const AAT::trak& trak = _get_trak (font->face, &blob);
AAT::hb_aat_apply_context_t c (font, buffer, blob);
kerx.apply (&c, &ankr);
trak.apply (&c);
#endif
AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
kerx.apply (&c);
}

View File

@ -39,6 +39,9 @@ hb_aat_layout_substitute (hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
HB_INTERNAL hb_bool_t
hb_aat_layout_has_positioning (hb_face_t *face);
HB_INTERNAL void
hb_aat_layout_position (hb_ot_shape_plan_t *plan,
hb_font_t *font,

View File

@ -47,8 +47,27 @@ _hb_options_init (void)
u.i = 0;
u.opts.initialized = 1;
char *c = getenv ("HB_OPTIONS");
u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
const char *c = getenv ("HB_OPTIONS");
if (c)
{
while (*c)
{
const char *p = strchr (c, ':');
if (!p)
p = c + strlen (c);
#define OPTION(name, symbol) \
if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) u.opts.symbol = true;
OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
OPTION ("aat", aat);
#undef OPTION
c = *p ? p + 1 : p;
}
}
/* This is idempotent and threadsafe. */
_hb_options.set_relaxed (u.i);

View File

@ -43,9 +43,10 @@
struct hb_options_t
{
unsigned int unused : 1; /* In-case sign bit is here. */
unsigned int initialized : 1;
unsigned int uniscribe_bug_compatible : 1;
bool unused : 1; /* In-case sign bit is here. */
bool initialized : 1;
bool uniscribe_bug_compatible : 1;
bool aat : 1;
};
union hb_options_union_t {

View File

@ -257,6 +257,13 @@ struct hb_sanitize_context_t :
inline void set_max_ops (int max_ops_) { max_ops = max_ops_; }
/* TODO
* This set_object() thing is to use sanitize at runtime lookup
* application time. This is very distinct from the regular
* sanitizer operation, so, eventually, separate into another
* type and make hb_aat_apply_context_t use that one instead
* of abusing this one.
*/
template <typename T>
inline void set_object (const T& obj)
{

View File

@ -92,6 +92,9 @@ typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
typedef HBINT16 FWORD;
/* 32-bit signed integer (HBINT32) that describes a quantity in FUnits. */
typedef HBINT32 FWORD32;
/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
typedef HBUINT16 UFWORD;

View File

@ -191,6 +191,12 @@ struct KernSubTableFormat2
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
{
/* This subtable is disabled. It's not cleaer to me *exactly* where the offests are
* based from. I *think* they should be based from beginning of kern subtable wrapper,
* *NOT* "this". Since we know of no fonts that use this subtable, we are disabling
* it. Someday fix it and re-enable. Better yet, find fonts that use it... Meh,
* Windows doesn't implement it. Maybe just remove... */
return 0;
unsigned int l = (this+leftClassTable).get_class (left);
unsigned int r = (this+rightClassTable).get_class (right);
unsigned int offset = l + r;
@ -204,6 +210,7 @@ struct KernSubTableFormat2
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (true); /* Disabled. See above. */
return_trace (rowWidth.sanitize (c) &&
leftClassTable.sanitize (c, this) &&
rightClassTable.sanitize (c, this) &&

View File

@ -621,6 +621,64 @@ struct hb_ot_apply_context_t :
};
struct hb_get_subtables_context_t :
hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
{
template <typename Type>
static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
{
const Type *typed_obj = (const Type *) obj;
return typed_obj->apply (c);
}
typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
struct hb_applicable_t
{
template <typename T>
inline void init (const T &obj_, hb_apply_func_t apply_func_)
{
obj = &obj_;
apply_func = apply_func_;
digest.init ();
obj_.get_coverage ().add_coverage (&digest);
}
inline bool apply (OT::hb_ot_apply_context_t *c) const
{
return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
}
private:
const void *obj;
hb_apply_func_t apply_func;
hb_set_digest_t digest;
};
typedef hb_vector_t<hb_applicable_t, 2> array_t;
/* Dispatch interface. */
inline const char *get_name (void) { return "GET_SUBTABLES"; }
template <typename T>
inline return_t dispatch (const T &obj)
{
hb_applicable_t *entry = array.push();
entry->init (obj, apply_to<T>);
return HB_VOID;
}
static return_t default_return_value (void) { return HB_VOID; }
bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
hb_get_subtables_context_t (array_t &array_) :
array (array_),
debug_depth (0) {}
array_t &array;
unsigned int debug_depth;
};
typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
@ -2562,6 +2620,39 @@ struct Extension
* GSUB/GPOS Common
*/
struct hb_ot_layout_lookup_accelerator_t
{
template <typename TLookup>
inline void init (const TLookup &lookup)
{
digest.init ();
lookup.add_coverage (&digest);
subtables.init ();
OT::hb_get_subtables_context_t c_get_subtables (subtables);
lookup.dispatch (&c_get_subtables);
}
inline void fini (void)
{
subtables.fini ();
}
inline bool may_have (hb_codepoint_t g) const
{ return digest.may_have (g); }
inline bool apply (hb_ot_apply_context_t *c) const
{
for (unsigned int i = 0; i < subtables.len; i++)
if (subtables[i].apply (c))
return true;
return false;
}
private:
hb_set_digest_t digest;
hb_get_subtables_context_t::array_t subtables;
};
struct GSUBGPOS
{
inline bool has_data (void) const { return version.to_int () != 0; }

View File

@ -1094,7 +1094,7 @@ struct GSUBProxy
accels (hb_ot_face_data (face)->GSUB->accels) {}
const OT::GSUB &table;
const hb_ot_layout_lookup_accelerator_t *accels;
const OT::hb_ot_layout_lookup_accelerator_t *accels;
};
struct GPOSProxy
@ -1108,63 +1108,13 @@ struct GPOSProxy
accels (hb_ot_face_data (face)->GPOS->accels) {}
const OT::GPOS &table;
const hb_ot_layout_lookup_accelerator_t *accels;
const OT::hb_ot_layout_lookup_accelerator_t *accels;
};
struct hb_get_subtables_context_t :
hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
{
template <typename Type>
static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
{
const Type *typed_obj = (const Type *) obj;
return typed_obj->apply (c);
}
typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
struct hb_applicable_t
{
inline void init (const void *obj_, hb_apply_func_t apply_func_)
{
obj = obj_;
apply_func = apply_func_;
}
inline bool apply (OT::hb_ot_apply_context_t *c) const { return apply_func (obj, c); }
private:
const void *obj;
hb_apply_func_t apply_func;
};
typedef hb_auto_t<hb_vector_t<hb_applicable_t> > array_t;
/* Dispatch interface. */
inline const char *get_name (void) { return "GET_SUBTABLES"; }
template <typename T>
inline return_t dispatch (const T &obj)
{
hb_applicable_t *entry = array.push();
entry->init (&obj, apply_to<T>);
return HB_VOID;
}
static return_t default_return_value (void) { return HB_VOID; }
bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
hb_get_subtables_context_t (array_t &array_) :
array (array_),
debug_depth (0) {}
array_t &array;
unsigned int debug_depth;
};
static inline bool
apply_forward (OT::hb_ot_apply_context_t *c,
const hb_ot_layout_lookup_accelerator_t &accel,
const hb_get_subtables_context_t::array_t &subtables)
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
bool ret = false;
hb_buffer_t *buffer = c->buffer;
@ -1175,12 +1125,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
for (unsigned int i = 0; i < subtables.len; i++)
if (subtables[i].apply (c))
{
applied = true;
break;
}
applied = accel.apply (c);
}
if (applied)
@ -1193,8 +1138,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
static inline bool
apply_backward (OT::hb_ot_apply_context_t *c,
const hb_ot_layout_lookup_accelerator_t &accel,
const hb_get_subtables_context_t::array_t &subtables)
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
bool ret = false;
hb_buffer_t *buffer = c->buffer;
@ -1204,12 +1148,8 @@ apply_backward (OT::hb_ot_apply_context_t *c,
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
for (unsigned int i = 0; i < subtables.len; i++)
if (subtables[i].apply (c))
{
if (accel.apply (c))
ret = true;
break;
}
}
/* The reverse lookup doesn't "advance" cursor (for good reason). */
buffer->idx--;
@ -1223,7 +1163,7 @@ template <typename Proxy>
static inline void
apply_string (OT::hb_ot_apply_context_t *c,
const typename Proxy::Lookup &lookup,
const hb_ot_layout_lookup_accelerator_t &accel)
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
hb_buffer_t *buffer = c->buffer;
@ -1232,10 +1172,6 @@ apply_string (OT::hb_ot_apply_context_t *c,
c->set_lookup_props (lookup.get_props ());
hb_get_subtables_context_t::array_t subtables;
hb_get_subtables_context_t c_get_subtables (subtables);
lookup.dispatch (&c_get_subtables);
if (likely (!lookup.is_reverse ()))
{
/* in/out forward substitution/positioning */
@ -1244,7 +1180,7 @@ apply_string (OT::hb_ot_apply_context_t *c,
buffer->idx = 0;
bool ret;
ret = apply_forward (c, accel, subtables);
ret = apply_forward (c, accel);
if (ret)
{
if (!Proxy::inplace)
@ -1260,7 +1196,7 @@ apply_string (OT::hb_ot_apply_context_t *c,
buffer->remove_output ();
buffer->idx = buffer->len - 1;
apply_backward (c, accel, subtables);
apply_backward (c, accel);
}
}
@ -1319,7 +1255,7 @@ void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_
void
hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
const OT::SubstLookup &lookup,
const hb_ot_layout_lookup_accelerator_t &accel)
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
apply_string<GSUBProxy> (c, lookup, accel);
}

View File

@ -112,32 +112,16 @@ hb_ot_layout_substitute_start (hb_font_t *font,
hb_buffer_t *buffer);
struct hb_ot_layout_lookup_accelerator_t
{
template <typename TLookup>
inline void init (const TLookup &lookup)
{
digest.init ();
lookup.add_coverage (&digest);
}
inline void fini (void) {}
inline bool may_have (hb_codepoint_t g) const
{ return digest.may_have (g); }
private:
hb_set_digest_t digest;
};
namespace OT {
struct hb_ot_apply_context_t;
struct SubstLookup;
struct hb_ot_layout_lookup_accelerator_t;
}
HB_INTERNAL void
hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
const OT::SubstLookup &lookup,
const hb_ot_layout_lookup_accelerator_t &accel);
const OT::hb_ot_layout_lookup_accelerator_t &accel);
/* Should be called before all the position_lookup's are done. */

View File

@ -201,7 +201,7 @@ struct arabic_fallback_plan_t
hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
};
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)

View File

@ -460,6 +460,10 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
!font->has_glyph_h_kerning_func () :
!font->has_glyph_v_kerning_func ())
return;
hb_ot_shape_fallback_kern_driver_t driver (font, buffer);
hb_kern_machine_t<hb_ot_shape_fallback_kern_driver_t> machine (driver);
machine.kern (font, buffer, plan->kern_mask);

View File

@ -42,6 +42,17 @@
#include "hb-aat-layout.hh"
static bool
_hb_apply_morx (hb_face_t *face)
{
if (hb_options ().aat &&
hb_aat_layout_has_substitution (face))
return true;
return !hb_ot_layout_has_substitution (face) &&
hb_aat_layout_has_substitution (face);
}
void
hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
const int *coords,
@ -55,24 +66,56 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
plan.kern_mask = plan.map.get_mask (HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ?
HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
plan.kerning_requested = !!plan.kern_mask;
plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
plan.apply_morx = !hb_ot_layout_has_substitution (face) &&
hb_aat_layout_has_substitution (face);
hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ?
HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
plan.kern_mask = plan.map.get_mask (kern_tag);
plan.requested_kerning = !!plan.kern_mask;
bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
bool disable_gpos = plan.shaper->gpos_tag &&
plan.shaper->gpos_tag != plan.map.chosen_script[1];
plan.apply_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
plan.apply_kern = !plan.apply_gpos && hb_ot_layout_has_kerning (face);
plan.fallback_kerning = !plan.apply_gpos && !plan.apply_kern;
plan.fallback_mark_positioning = !plan.apply_gpos;
plan.fallback_glyph_classes = !hb_ot_layout_has_glyph_classes (face);
/*
* Decide who provides glyph classes. GDEF or Unicode.
*/
if (!hb_ot_layout_has_glyph_classes (face))
plan.fallback_glyph_classes = true;
/*
* Decide who does substitutions. GSUB, morx, or fallback.
*/
plan.apply_morx = _hb_apply_morx (face);
/*
* Decide who does positioning. GPOS, kerx, kern, or fallback.
*/
if (hb_options ().aat && hb_aat_layout_has_positioning (face))
plan.apply_kerx = true;
else if (!disable_gpos && hb_ot_layout_has_positioning (face))
plan.apply_gpos = true;
else if (hb_aat_layout_has_positioning (face))
plan.apply_kerx = true;
if (plan.requested_kerning)
{
if (plan.apply_kerx)
;/* kerx supercedes kern. */
else if (!has_gpos_kern)
{
if (hb_ot_layout_has_kerning (face))
plan.apply_kern = true;
else
plan.fallback_kerning = true;
}
}
plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
if (!plan.apply_gpos)
plan.fallback_mark_positioning = true;
}
@ -229,8 +272,7 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
/* Ugly that we have to do this here...
* If we are going to apply morx, choose default shaper. */
if (!hb_ot_layout_has_substitution (planner.face) &&
hb_aat_layout_has_substitution (planner.face))
if (_hb_apply_morx (planner.face))
planner.shaper = &_hb_ot_complex_shaper_default;
else
planner.shaper = hb_ot_shape_complex_categorize (&planner);
@ -792,6 +834,8 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
if (c->plan->apply_gpos)
c->plan->position (c->font, c->buffer);
else if (c->plan->apply_kerx)
hb_aat_layout_position (c->plan, c->font, c->buffer);
switch (c->plan->shaper->zero_width_marks)
{
@ -835,16 +879,12 @@ hb_ot_position (const hb_ot_shape_context_t *c)
/* Visual fallback goes here. */
if (!c->plan->kerning_requested)
;
else if (c->plan->apply_kern)
if (c->plan->apply_kern)
hb_ot_layout_kern (c->font, c->buffer, c->plan->kern_mask);
else if (c->plan->fallback_kerning)
_hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
_hb_buffer_deallocate_gsubgpos_vars (c->buffer);
//hb_aat_layout_position (c->font, c->buffer);
}
static inline void

View File

@ -43,14 +43,15 @@ struct hb_ot_shape_plan_t
hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask;
hb_mask_t kern_mask;
bool requested_kerning : 1;
bool has_frac : 1;
bool kerning_requested : 1;
bool has_gpos_mark : 1;
bool fallback_glyph_classes : 1;
bool fallback_kerning : 1;
bool fallback_mark_positioning : 1;
bool apply_morx : 1;
bool apply_kerx : 1;
bool apply_kern : 1;
bool apply_gpos : 1;

View File

@ -39,9 +39,7 @@ HB_SHAPER_IMPLEMENT (graphite2)
HB_SHAPER_IMPLEMENT (coretext_aat)
#endif
#ifdef HAVE_OT
HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
#endif
#ifdef HAVE_UNISCRIBE
HB_SHAPER_IMPLEMENT (uniscribe)

View File

@ -45,10 +45,8 @@
#include "hb.h"
#define HB_H_IN
#ifdef HAVE_OT
#include "hb-ot.h"
#define HB_OT_H_IN
#endif
#include <math.h>
#include <stdlib.h>

View File

@ -73,14 +73,13 @@ test_unicode_LDADD += $(top_builddir)/src/libharfbuzz-icu.la $(ICU_LIBS)
endif
if HAVE_OT
TEST_PROGS += \
test-ot-color \
test-ot-tag \
test-ot-extents-cff \
$(NULL)
if HAVE_PTHREAD
if HAVE_FREETYPE
TEST_PROGS += test-multithread
@ -100,7 +99,6 @@ test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
endif # HAVE_FREETYPE
endif # HAVE_OT
# Tests for header compilation
TEST_PROGS += \

View File

@ -32,6 +32,7 @@
#endif
#include <hb.h>
#include <hb-ot.h>
#ifdef HAVE_GLIB
#include <hb-glib.h>
@ -45,10 +46,6 @@
#include <hb-ft.h>
#endif
#ifdef HAVE_OT
#include <hb-ot.h>
#endif
#ifdef HAVE_UNISCRIBE
#include <hb-uniscribe.h>
#endif

View File

@ -52,14 +52,11 @@ hb_subset_LDADD = \
$(top_builddir)/src/libharfbuzz-subset.la
bin_PROGRAMS += hb-subset
if HAVE_OT
hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources)
bin_PROGRAMS += hb-ot-shape-closure
endif # HAVE_OT
endif # HAVE_GLIB
#if HAVE_OT
#if HAVE_FONTCONFIG
#hb_fc_list_SOURCES = \
# hb-fc.cc \
@ -72,6 +69,5 @@ endif # HAVE_GLIB
# $(NULL)
#bin_PROGRAMS += hb-fc-list
#endif # HAVE_FONTCONFIG
#endif # HAVE_OT
-include $(top_srcdir)/git.mk

View File

@ -29,9 +29,7 @@
#ifdef HAVE_FREETYPE
#include <hb-ft.h>
#endif
#ifdef HAVE_OT
#include <hb-ot.h>
#endif
static struct supported_font_funcs_t {
char name[4];
@ -41,9 +39,7 @@ static struct supported_font_funcs_t {
#ifdef HAVE_FREETYPE
{"ft", hb_ft_font_set_funcs},
#endif
#ifdef HAVE_OT
{"ot", hb_ot_font_set_funcs},
#endif
};

View File

@ -46,9 +46,7 @@
#endif
#include <hb.h>
#ifdef HAVE_OT
#include <hb-ot.h>
#endif
#include <glib.h>
#include <glib/gprintf.h>