[harfbuzz/GSUB] towards a partially working GSUB
This commit is contained in:
parent
30bd763fa2
commit
5a0b791184
|
@ -59,7 +59,7 @@
|
|||
|
||||
/* Internal API */
|
||||
|
||||
static HB_Error
|
||||
/*static XXX */ HB_Error
|
||||
hb_buffer_ensure( HB_Buffer buffer,
|
||||
HB_UInt size )
|
||||
{
|
||||
|
|
|
@ -78,7 +78,7 @@ HB_BEGIN_HEADER
|
|||
|
||||
|
||||
#define ALLOC(_ptr,_size) \
|
||||
( (_ptr) = _hb_alloc( _size, &error ), error != 0 )
|
||||
( *(void**)&(_ptr) = _hb_alloc( _size, &error ), error != 0 )
|
||||
|
||||
#define REALLOC(_ptr,_newsz) \
|
||||
( (_ptr) = _hb_realloc( (_ptr), (_newsz), &error ), error != 0 )
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#define HB_INTERNAL static
|
||||
#include "harfbuzz-buffer.c"
|
||||
#include "harfbuzz-gdef.c"
|
||||
#include "harfbuzz-gsub.c"
|
||||
#include "harfbuzz-gpos.c"
|
||||
#include "harfbuzz-impl.c"
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#define DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP(Type, name) \
|
||||
inline const Type& name (hb_codepoint_t glyph) { \
|
||||
const Coverage &c = get_coverage (); \
|
||||
hb_ot_layout_coverage_t c_index = c.get_coverage (glyph); \
|
||||
unsigned int c_index = c.get_coverage (glyph); \
|
||||
return (*this)[c_index]; \
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ struct LigCaretList {
|
|||
DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (LigGlyph, get_lig_glyph);
|
||||
|
||||
private:
|
||||
/* AttachPoint tables, in Coverage Index order */
|
||||
/* LigGlyph tables, in Coverage Index order */
|
||||
DEFINE_OFFSET_ARRAY_TYPE (LigGlyph, ligGlyph, ligGlyphCount);
|
||||
DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||
* Copyright (C) 2007,2008,2009 Red Hat, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||
*
|
||||
|
@ -35,7 +35,7 @@
|
|||
#include "harfbuzz-buffer-private.h" /* XXX */
|
||||
|
||||
#define DEFINE_GET_GLYPH_COVERAGE(name) \
|
||||
inline hb_ot_layout_coverage_t get_##name (hb_codepoint_t glyph) const { \
|
||||
inline unsigned int get_##name (hb_codepoint_t glyph) const { \
|
||||
const Coverage &c = get_coverage (); \
|
||||
return c.get_coverage (glyph); \
|
||||
}
|
||||
|
@ -46,6 +46,12 @@
|
|||
unsigned int context_length, \
|
||||
unsigned int nesting_level_left, \
|
||||
unsigned int lookup_flag) const
|
||||
#define SUBTABLE_SUBSTITUTE_CHAIN(obj) \
|
||||
obj.substitute (layout, \
|
||||
buffer, \
|
||||
context_length, \
|
||||
nesting_level_left, \
|
||||
lookup_flag)
|
||||
|
||||
struct SingleSubstFormat1 {
|
||||
|
||||
|
@ -55,9 +61,163 @@ struct SingleSubstFormat1 {
|
|||
DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
|
||||
DEFINE_GET_GLYPH_COVERAGE (glyph_coverage);
|
||||
|
||||
inline bool single_substitute (hb_codepoint_t &glyph_id) const {
|
||||
|
||||
unsigned int index;
|
||||
|
||||
index = get_glyph_coverage (glyph_id);
|
||||
if (NOT_COVERED == index)
|
||||
return false;
|
||||
|
||||
glyph_id += deltaGlyphID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
case 2:
|
||||
if ( index >= ss->ssf.ssf2.GlyphCount )
|
||||
return ERR(HB_Err_Invalid_SubTable);
|
||||
value = ss->ssf.ssf2.Substitute[index];
|
||||
if ( REPLACE_Glyph( buffer, value, nesting_level ) )
|
||||
return error;
|
||||
break;
|
||||
#endif
|
||||
|
||||
private:
|
||||
USHORT substFormat; /* Format identifier--format = 1 */
|
||||
Offset coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
SHORT deltaGlyphID; /* Add to original GlyphID to get
|
||||
* substitute GlyphID */
|
||||
};
|
||||
ASSERT_SIZE (SingleSubstFormat1, 6);
|
||||
|
||||
struct SingleSubstFormat2 {
|
||||
|
||||
friend struct SingleSubst;
|
||||
|
||||
private:
|
||||
DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
|
||||
DEFINE_GET_GLYPH_COVERAGE (glyph_coverage);
|
||||
|
||||
inline bool single_substitute (hb_codepoint_t &glyph_id) const {
|
||||
|
||||
unsigned int index;
|
||||
|
||||
index = get_glyph_coverage (glyph_id);
|
||||
|
||||
if (index >= glyphCount)
|
||||
return false;
|
||||
|
||||
glyph_id = substitute[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT substFormat; /* Format identifier--format = 2 */
|
||||
Offset coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
USHORT glyphCount; /* Number of GlyphIDs in the Substitute
|
||||
* array */
|
||||
GlyphID substitute[]; /* Array of substitute
|
||||
* GlyphIDs--ordered by Coverage Index */
|
||||
};
|
||||
ASSERT_SIZE (SingleSubstFormat2, 6);
|
||||
|
||||
struct SingleSubst {
|
||||
|
||||
friend struct SubstLookupSubTable;
|
||||
|
||||
unsigned int get_size (void) const {
|
||||
switch (u.substFormat) {
|
||||
case 1: return sizeof (u.format1);
|
||||
case 2: return sizeof (u.format2);
|
||||
default:return sizeof (u.substFormat);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
inline SUBTABLE_SUBSTITUTE {
|
||||
|
||||
hb_codepoint_t glyph_id;
|
||||
hb_ot_layout_coverage_t index;
|
||||
unsigned int property;
|
||||
|
||||
HB_UNUSED (nesting_level_left);
|
||||
|
||||
if (HB_UNLIKELY (context_length < 1))
|
||||
return false;
|
||||
|
||||
if (!_hb_ot_layout_check_glyph_property (layout, IN_CURITEM (), lookup_flag, &property))
|
||||
return false;
|
||||
|
||||
glyph_id = IN_CURGLYPH ();
|
||||
|
||||
switch (u.substFormat) {
|
||||
case 1: if (!u.format1.single_substitute (glyph_id)) return false;
|
||||
case 2: if (!u.format2.single_substitute (glyph_id)) return false;
|
||||
default:return false;
|
||||
}
|
||||
|
||||
_hb_buffer_replace_output_glyph (buffer, glyph_id, context_length == NO_CONTEXT);
|
||||
|
||||
if ( _hb_ot_layout_has_new_glyph_classes (layout) )
|
||||
{
|
||||
/* we inherit the old glyph class to the substituted glyph */
|
||||
_hb_ot_layout_set_glyph_property (layout, glyph_id, property);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT substFormat; /* Format identifier */
|
||||
SingleSubstFormat1 format1;
|
||||
SingleSubstFormat2 format2;
|
||||
} u;
|
||||
};
|
||||
DEFINE_NULL (SingleSubst, 2);
|
||||
|
||||
|
||||
struct Sequence {
|
||||
|
||||
friend struct MultipleSubstFormat1;
|
||||
|
||||
private:
|
||||
/* GlyphID tables, in Coverage Index order */
|
||||
DEFINE_OFFSET_ARRAY_TYPE (GlyphID, substitute, glyphCount);
|
||||
|
||||
inline void set_glyph_class (hb_ot_layout_t *layout, unsigned int property) const {
|
||||
unsigned int n, count = glyphCount;
|
||||
|
||||
for (n = 0; n < count; n++)
|
||||
_hb_ot_layout_set_glyph_property (layout, substitute[n], property);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT glyphCount; /* Number of GlyphIDs in the Substitute
|
||||
* array. This should always be
|
||||
* greater than 0. */
|
||||
GlyphID substitute[]; /* String of GlyphIDs to substitute */
|
||||
};
|
||||
DEFINE_NULL_ASSERT_SIZE (Sequence, 2);
|
||||
|
||||
struct MultipleSubstFormat1 {
|
||||
|
||||
friend struct MultipleSubst;
|
||||
|
||||
private:
|
||||
/* Sequence tables, in Coverage Index order */
|
||||
DEFINE_OFFSET_ARRAY_TYPE (Sequence, sequence, sequenceCount);
|
||||
DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
|
||||
DEFINE_GET_GLYPH_COVERAGE (glyph_coverage);
|
||||
|
||||
inline SUBTABLE_SUBSTITUTE {
|
||||
|
||||
hb_codepoint_t glyph_id;
|
||||
unsigned int index;
|
||||
unsigned int property;
|
||||
|
||||
HB_UNUSED (nesting_level_left);
|
||||
|
@ -71,77 +231,27 @@ struct SingleSubstFormat1 {
|
|||
glyph_id = IN_CURGLYPH ();
|
||||
|
||||
index = get_glyph_coverage (glyph_id);
|
||||
if (-1 == index)
|
||||
if (index >= sequenceCount)
|
||||
return false;
|
||||
|
||||
glyph_id += deltaGlyphID;
|
||||
_hb_buffer_replace_output_glyph (buffer, glyph_id, context_length == NO_CONTEXT);
|
||||
const Sequence &seq = (*this)[index];
|
||||
_hb_buffer_add_output_glyph_ids (buffer, 1,
|
||||
seq.glyphCount, seq.substitute,
|
||||
0xFFFF, 0xFFFF);
|
||||
|
||||
if ( _hb_ot_layout_has_new_glyph_classes (layout) )
|
||||
{
|
||||
/* we inherit the old glyph class to the substituted glyph */
|
||||
_hb_ot_layout_set_glyph_property (layout, glyph_id, property);
|
||||
/* this is a guess only ... */
|
||||
|
||||
if ( property == HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE )
|
||||
property = HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
|
||||
|
||||
seq.set_glyph_class (layout, property);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
switch ( ss->SubstFormat )
|
||||
{
|
||||
case 1:
|
||||
value = (IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
|
||||
if ( REPLACE_Glyph( buffer, value, nesting_level ) )
|
||||
return error;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if ( index >= ss->ssf.ssf2.GlyphCount )
|
||||
return ERR(HB_Err_Invalid_SubTable);
|
||||
value = ss->ssf.ssf2.Substitute[index];
|
||||
if ( REPLACE_Glyph( buffer, value, nesting_level ) )
|
||||
return error;
|
||||
break;
|
||||
|
||||
default:
|
||||
return ERR(HB_Err_Invalid_SubTable);
|
||||
}
|
||||
|
||||
if ( _hb_ot_layout_has_new_glyph_classes (layout) )
|
||||
{
|
||||
/* we inherit the old glyph class to the substituted glyph */
|
||||
|
||||
hb_ot_layout_set_glyph_class (layout, value, properties);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
USHORT substFormat; /* Format identifier--format = 1 */
|
||||
Offset coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
SHORT deltaGlyphID; /* Add to original GlyphID to get
|
||||
* substitute GlyphID */
|
||||
};
|
||||
ASSERT_SIZE (SingleSubstFormat1, 6);
|
||||
|
||||
struct SingleSubstFormat2 {
|
||||
/* TODO */
|
||||
|
||||
private:
|
||||
USHORT substFormat; /* Format identifier--format = 2 */
|
||||
Offset coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
USHORT glyphCount; /* Number of GlyphIDs in the Substitute
|
||||
* array */
|
||||
GlyphID substitute[]; /* Array of substitute
|
||||
* GlyphIDs--ordered by Coverage Index */
|
||||
};
|
||||
ASSERT_SIZE (SingleSubstFormat2, 6);
|
||||
|
||||
struct MultipleSubstFormat1 {
|
||||
/* TODO */
|
||||
|
||||
private:
|
||||
USHORT substFormat; /* Format identifier--format = 1 */
|
||||
Offset coverage; /* Offset to Coverage table--from
|
||||
|
@ -155,16 +265,42 @@ struct MultipleSubstFormat1 {
|
|||
};
|
||||
ASSERT_SIZE (MultipleSubstFormat1, 6);
|
||||
|
||||
struct Sequence {
|
||||
struct MultipleSubst {
|
||||
|
||||
unsigned int get_size (void) const {
|
||||
switch (u.substFormat) {
|
||||
case 1: return sizeof (u.format1);
|
||||
default:return sizeof (u.substFormat);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
inline SUBTABLE_SUBSTITUTE {
|
||||
switch (u.substFormat) {
|
||||
case 1: return SUBTABLE_SUBSTITUTE_CHAIN(u.format1);
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT substFormat; /* Format identifier */
|
||||
MultipleSubstFormat1 format1;
|
||||
} u;
|
||||
};
|
||||
DEFINE_NULL (MultipleSubst, 2);
|
||||
|
||||
|
||||
struct AlternateSet {
|
||||
/* TODO */
|
||||
|
||||
private:
|
||||
USHORT glyphCount; /* Number of GlyphIDs in the Substitute
|
||||
* array. This should always be
|
||||
* greater than 0. */
|
||||
GlyphID substitute[]; /* String of GlyphIDs to substitute */
|
||||
USHORT glyphCount; /* Number of GlyphIDs in the Alternate
|
||||
* array */
|
||||
GlyphID alternate[]; /* Array of alternate GlyphIDs--in
|
||||
* arbitrary order */
|
||||
};
|
||||
DEFINE_NULL_ASSERT_SIZE (Sequence, 2);
|
||||
DEFINE_NULL_ASSERT_SIZE (AlternateSet, 2);
|
||||
|
||||
struct AlternateSubstFormat1 {
|
||||
/* TODO */
|
||||
|
@ -181,16 +317,30 @@ struct AlternateSubstFormat1 {
|
|||
};
|
||||
ASSERT_SIZE (AlternateSubstFormat1, 6);
|
||||
|
||||
struct AlternateSet {
|
||||
|
||||
struct Ligature {
|
||||
/* TODO */
|
||||
|
||||
private:
|
||||
USHORT glyphCount; /* Number of GlyphIDs in the Alternate
|
||||
* array */
|
||||
GlyphID alternate[]; /* Array of alternate GlyphIDs--in
|
||||
* arbitrary order */
|
||||
GlyphID ligGlyph; /* GlyphID of ligature to substitute */
|
||||
USHORT compCount; /* Number of components in the ligature */
|
||||
GlyphID component[]; /* Array of component GlyphIDs--start
|
||||
* with the second component--ordered
|
||||
* in writing direction */
|
||||
};
|
||||
DEFINE_NULL_ASSERT_SIZE (AlternateSet, 2);
|
||||
DEFINE_NULL_ASSERT_SIZE (Ligature, 4);
|
||||
|
||||
struct LigatureSet {
|
||||
/* TODO */
|
||||
|
||||
private:
|
||||
USHORT ligatureCount; /* Number of Ligature tables */
|
||||
Offset ligature[]; /* Array of offsets to Ligature
|
||||
* tables--from beginning of
|
||||
* LigatureSet table--ordered by
|
||||
* preference */
|
||||
};
|
||||
DEFINE_NULL_ASSERT_SIZE (LigatureSet, 2);
|
||||
|
||||
struct LigatureSubstFormat1 {
|
||||
/* TODO */
|
||||
|
@ -207,29 +357,6 @@ struct LigatureSubstFormat1 {
|
|||
};
|
||||
ASSERT_SIZE (LigatureSubstFormat1, 6);
|
||||
|
||||
struct LigatureSet {
|
||||
/* TODO */
|
||||
|
||||
private:
|
||||
USHORT ligatureCount; /* Number of Ligature tables */
|
||||
Offset ligature[]; /* Array of offsets to Ligature
|
||||
* tables--from beginning of
|
||||
* LigatureSet table--ordered by
|
||||
* preference */
|
||||
};
|
||||
DEFINE_NULL_ASSERT_SIZE (LigatureSet, 2);
|
||||
|
||||
struct Ligature {
|
||||
/* TODO */
|
||||
|
||||
private:
|
||||
GlyphID ligGlyph; /* GlyphID of ligature to substitute */
|
||||
USHORT compCount; /* Number of components in the ligature */
|
||||
GlyphID component[]; /* Array of component GlyphIDs--start
|
||||
* with the second component--ordered
|
||||
* in writing direction */
|
||||
};
|
||||
DEFINE_NULL_ASSERT_SIZE (Ligature, 4);
|
||||
|
||||
struct SubstLookupRecord {
|
||||
/* TODO */
|
||||
|
@ -533,6 +660,17 @@ ASSERT_SIZE (ReverseChainSingleSubstFormat1, 10);
|
|||
* SubstLookup
|
||||
*/
|
||||
|
||||
enum {
|
||||
GSUB_Single = 1,
|
||||
GSUB_Multiple = 2,
|
||||
GSUB_Alternate = 3,
|
||||
GSUB_Ligature = 4,
|
||||
GSUB_Context = 5,
|
||||
GSUB_ChainingContext = 6,
|
||||
GSUB_Extension = 7,
|
||||
GSUB_ReverseChainingContextSingle = 8,
|
||||
};
|
||||
|
||||
struct SubstLookupSubTable {
|
||||
DEFINE_NON_INSTANTIABLE(SubstLookupSubTable);
|
||||
|
||||
|
@ -543,14 +681,14 @@ struct SubstLookupSubTable {
|
|||
// case 1: return u.format1.get_size ();
|
||||
// case 2: return u.format2.get_size ();
|
||||
/*
|
||||
case Single:
|
||||
case Multiple:
|
||||
case Alternate:
|
||||
case Ligature:
|
||||
case Context:
|
||||
case ChainingContext:
|
||||
case Extension:
|
||||
case ReverseChainingContextSingle:
|
||||
case GSUB_Single:
|
||||
case GSUB_Multiple:
|
||||
case GSUB_Alternate:
|
||||
case GSUB_Ligature:
|
||||
case GSUB_Context:
|
||||
case GSUB_ChainingContext:
|
||||
case GSUB_Extension:
|
||||
case GSUB_ReverseChainingContextSingle:
|
||||
*/
|
||||
default:return sizeof (LookupSubTable);
|
||||
}
|
||||
|
@ -562,13 +700,25 @@ struct SubstLookupSubTable {
|
|||
unsigned int nesting_level_left,
|
||||
unsigned int lookup_type,
|
||||
unsigned int lookup_flag) const {
|
||||
switch (lookup_type) {
|
||||
case GSUB_Single: return SUBTABLE_SUBSTITUTE_CHAIN (u.singleSubst);
|
||||
/*
|
||||
case GSUB_Multiple:
|
||||
case GSUB_Alternate:
|
||||
case GSUB_Ligature:
|
||||
case GSUB_Context:
|
||||
case GSUB_ChainingContext:
|
||||
case GSUB_Extension:
|
||||
case GSUB_ReverseChainingContextSingle:
|
||||
*/
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT substFormat;
|
||||
CoverageFormat1 format1;
|
||||
CoverageFormat2 format2;
|
||||
SingleSubst singleSubst;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
@ -576,25 +726,16 @@ struct SubstLookup : Lookup {
|
|||
|
||||
DEFINE_NON_INSTANTIABLE(SubstLookup);
|
||||
|
||||
static const unsigned int Single = 1;
|
||||
static const unsigned int Multiple = 2;
|
||||
static const unsigned int Alternate = 3;
|
||||
static const unsigned int Ligature = 4;
|
||||
static const unsigned int Context = 5;
|
||||
static const unsigned int ChainingContext = 6;
|
||||
static const unsigned int Extension = 7;
|
||||
static const unsigned int ReverseChainingContextSingle = 8;
|
||||
|
||||
inline const SubstLookupSubTable& get_subtable (unsigned int i) const {
|
||||
return *(SubstLookupSubTable*)&(((Lookup *)this)->get_subtable (i));
|
||||
}
|
||||
|
||||
/* Like get_type(), but looks through extension lookups.
|
||||
* Never returns SubstLookup::Extension */
|
||||
* Never returns Extension */
|
||||
inline unsigned int get_effective_type (void) const {
|
||||
unsigned int type = get_type ();
|
||||
|
||||
if (HB_UNLIKELY (type == Extension)) {
|
||||
if (HB_UNLIKELY (type == GSUB_Extension)) {
|
||||
/* Return lookup type of first extension subtable.
|
||||
* The spec says all of them should have the same type.
|
||||
* XXX check for that somehow */
|
||||
|
@ -606,15 +747,16 @@ struct SubstLookup : Lookup {
|
|||
|
||||
inline bool is_reverse (void) const {
|
||||
switch (get_effective_type ()) {
|
||||
case ReverseChainingContextSingle: return true;
|
||||
default: return false;
|
||||
case GSUB_ReverseChainingContextSingle: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool substitute (hb_ot_layout_t *layout,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int context_length,
|
||||
unsigned int nesting_level_left) const {
|
||||
inline bool substitute_once (hb_ot_layout_t *layout,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int context_length,
|
||||
unsigned int nesting_level_left) const {
|
||||
|
||||
unsigned int lookup_type = get_type ();
|
||||
unsigned int lookup_flag = get_flag ();
|
||||
|
||||
|
@ -630,6 +772,47 @@ struct SubstLookup : Lookup {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool substitute_string (hb_ot_layout_t *layout,
|
||||
hb_buffer_t *buffer,
|
||||
hb_ot_layout_feature_mask_t mask) const {
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if (!is_reverse ()) {
|
||||
|
||||
/* in/out forward substitution */
|
||||
_hb_buffer_clear_output (buffer);
|
||||
buffer->in_pos = 0;
|
||||
while (buffer->in_pos < buffer->in_length) {
|
||||
|
||||
if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
|
||||
substitute_once (layout, buffer, NO_CONTEXT, MAX_NESTING_LEVEL))
|
||||
ret = true;
|
||||
else
|
||||
_hb_buffer_copy_output_glyph (buffer);
|
||||
|
||||
}
|
||||
if (ret)
|
||||
_hb_buffer_swap (buffer);
|
||||
|
||||
} else {
|
||||
|
||||
/* in-place backward substitution */
|
||||
buffer->in_pos = buffer->in_length - 1;
|
||||
do {
|
||||
|
||||
if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
|
||||
substitute_once (layout, buffer, NO_CONTEXT, MAX_NESTING_LEVEL))
|
||||
ret = true;
|
||||
else
|
||||
buffer->in_pos--;
|
||||
|
||||
} while (buffer->in_pos);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
DEFINE_NULL_ALIAS (SubstLookup, Lookup);
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
|
||||
#define NO_INDEX ((unsigned int) 0xFFFF)
|
||||
#define NO_CONTEXT ((unsigned int) -1)
|
||||
#define NOT_COVERED ((unsigned int) -1)
|
||||
#define MAX_NESTING_LEVEL 32
|
||||
|
||||
|
||||
/*
|
||||
* Int types
|
||||
|
@ -717,16 +720,16 @@ struct CoverageFormat1 {
|
|||
/* GlyphIDs, in sorted numerical order */
|
||||
DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount);
|
||||
|
||||
inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
|
||||
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
|
||||
GlyphID gid;
|
||||
if (HB_UNLIKELY (glyph_id > 65535))
|
||||
return -1;
|
||||
return NOT_COVERED;
|
||||
gid = glyph_id;
|
||||
// TODO: bsearch
|
||||
for (unsigned int i = 0; i < glyphCount; i++)
|
||||
if (gid == glyphArray[i])
|
||||
return i;
|
||||
return -1;
|
||||
return NOT_COVERED;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -741,10 +744,10 @@ struct CoverageRangeRecord {
|
|||
friend struct CoverageFormat2;
|
||||
|
||||
private:
|
||||
inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
|
||||
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
|
||||
if (glyph_id >= start && glyph_id <= end)
|
||||
return startCoverageIndex + (glyph_id - start);
|
||||
return -1;
|
||||
return NOT_COVERED;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -763,14 +766,14 @@ struct CoverageFormat2 {
|
|||
/* CoverageRangeRecords, in sorted numerical start order */
|
||||
DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount);
|
||||
|
||||
inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
|
||||
inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
|
||||
// TODO: bsearch
|
||||
for (unsigned int i = 0; i < rangeCount; i++) {
|
||||
int coverage = rangeRecord[i].get_coverage (glyph_id);
|
||||
if (coverage >= 0)
|
||||
return coverage;
|
||||
}
|
||||
return -1;
|
||||
return NOT_COVERED;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -793,11 +796,11 @@ struct Coverage {
|
|||
}
|
||||
}
|
||||
|
||||
hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const {
|
||||
switch (u.coverageFormat) {
|
||||
case 1: return u.format1.get_coverage(glyph_id);
|
||||
case 2: return u.format2.get_coverage(glyph_id);
|
||||
default:return -1;
|
||||
default:return NOT_COVERED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -990,4 +993,14 @@ struct GSUBGPOS {
|
|||
};
|
||||
DEFINE_NULL_ASSERT_SIZE (GSUBGPOS, 10);
|
||||
|
||||
/* XXX */
|
||||
#include "harfbuzz-impl.h"
|
||||
HB_INTERNAL HB_Error
|
||||
_hb_buffer_add_output_glyph_ids( HB_Buffer buffer,
|
||||
HB_UShort num_in,
|
||||
HB_UShort num_out,
|
||||
const GlyphID *glyph_data,
|
||||
HB_UShort component,
|
||||
HB_UShort ligID );
|
||||
|
||||
#endif /* HB_OT_LAYOUT_OPEN_PRIVATE_H */
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
|
||||
typedef unsigned int hb_ot_layout_class_t;
|
||||
typedef int hb_ot_layout_coverage_t; /* -1 is not covered, >= 0 otherwise */
|
||||
|
||||
/* XXX #define HB_OT_LAYOUT_INTERNAL static */
|
||||
#define HB_OT_LAYOUT_INTERNAL
|
||||
|
@ -64,6 +63,11 @@ _hb_ot_layout_check_glyph_property (hb_ot_layout_t *layout,
|
|||
unsigned int lookup_flags,
|
||||
unsigned int *property);
|
||||
|
||||
/* XXX */
|
||||
HB_Error
|
||||
hb_buffer_ensure( HB_Buffer buffer,
|
||||
HB_UInt size );
|
||||
|
||||
HB_END_DECLS();
|
||||
|
||||
#endif /* HB_OT_LAYOUT_PRIVATE_H */
|
||||
|
|
|
@ -544,42 +544,82 @@ hb_ot_layout_substitute_lookup (hb_ot_layout_t *layout,
|
|||
{
|
||||
const GSUB &gsub = *(layout->gsub);
|
||||
const SubstLookup &l = gsub.get_lookup (lookup_index);
|
||||
unsigned int lookup_type = l.get_type ();
|
||||
unsigned int nesting_level_left = HB_OT_LAYOUT_MAX_NESTING_LEVEL;
|
||||
unsigned int context_length = NO_CONTEXT;
|
||||
bool handled, ret = false;
|
||||
|
||||
if (!l.is_reverse ()) {
|
||||
return l.substitute_string (layout, buffer, mask);
|
||||
}
|
||||
|
||||
/* in/out forward substitution */
|
||||
_hb_buffer_clear_output (buffer);
|
||||
buffer->in_pos = 0;
|
||||
while (buffer->in_pos < buffer->in_length) {
|
||||
|
||||
if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
|
||||
l.substitute (layout, buffer, context_length, nesting_level_left))
|
||||
ret = true;
|
||||
else
|
||||
_hb_buffer_copy_output_glyph (buffer);
|
||||
|
||||
}
|
||||
_hb_buffer_swap (buffer);
|
||||
/* XXX dupped, until he old code can be removed */
|
||||
|
||||
} else {
|
||||
static HB_Error
|
||||
hb_buffer_duplicate_out_buffer( HB_Buffer buffer )
|
||||
{
|
||||
if ( !buffer->alt_string )
|
||||
{
|
||||
HB_Error error;
|
||||
|
||||
/* in-place backward substitution */
|
||||
buffer->in_pos = buffer->in_length - 1;
|
||||
do {
|
||||
if ( ALLOC_ARRAY( buffer->alt_string, buffer->allocated, HB_GlyphItemRec ) )
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
|
||||
l.substitute (layout, buffer, context_length, nesting_level_left))
|
||||
ret = true;
|
||||
else
|
||||
buffer->in_pos--;
|
||||
buffer->out_string = buffer->alt_string;
|
||||
memcpy( buffer->out_string, buffer->in_string, buffer->out_length * sizeof (buffer->out_string[0]) );
|
||||
buffer->separate_out = TRUE;
|
||||
|
||||
} while (buffer->in_pos);
|
||||
return HB_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HB_INTERNAL HB_Error
|
||||
_hb_buffer_add_output_glyph_ids( HB_Buffer buffer,
|
||||
HB_UShort num_in,
|
||||
HB_UShort num_out,
|
||||
const GlyphID *glyph_data,
|
||||
HB_UShort component,
|
||||
HB_UShort ligID )
|
||||
{
|
||||
HB_Error error;
|
||||
HB_UShort i;
|
||||
HB_UInt properties;
|
||||
HB_UInt cluster;
|
||||
|
||||
error = hb_buffer_ensure( buffer, buffer->out_pos + num_out );
|
||||
if ( error )
|
||||
return error;
|
||||
|
||||
if ( !buffer->separate_out )
|
||||
{
|
||||
error = hb_buffer_duplicate_out_buffer( buffer );
|
||||
if ( error )
|
||||
return error;
|
||||
}
|
||||
|
||||
properties = buffer->in_string[buffer->in_pos].properties;
|
||||
cluster = buffer->in_string[buffer->in_pos].cluster;
|
||||
if ( component == 0xFFFF )
|
||||
component = buffer->in_string[buffer->in_pos].component;
|
||||
if ( ligID == 0xFFFF )
|
||||
ligID = buffer->in_string[buffer->in_pos].ligID;
|
||||
|
||||
for ( i = 0; i < num_out; i++ )
|
||||
{
|
||||
HB_GlyphItem item = &buffer->out_string[buffer->out_pos + i];
|
||||
|
||||
item->gindex = glyph_data[i];
|
||||
item->properties = properties;
|
||||
item->cluster = cluster;
|
||||
item->component = component;
|
||||
item->ligID = ligID;
|
||||
item->gproperty = HB_GLYPH_PROPERTY_UNKNOWN;
|
||||
}
|
||||
|
||||
return ret;
|
||||
buffer->in_pos += num_in;
|
||||
buffer->out_pos += num_out;
|
||||
|
||||
buffer->out_length = buffer->out_pos;
|
||||
|
||||
return HB_Err_Ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -93,8 +93,6 @@ typedef enum {
|
|||
|
||||
typedef uint32_t hb_ot_layout_feature_mask_t;
|
||||
|
||||
#define HB_OT_LAYOUT_MAX_NESTING_LEVEL 100
|
||||
|
||||
#define HB_OT_LAYOUT_NO_SCRIPT_INDEX ((unsigned int) 0xFFFF)
|
||||
#define HB_OT_LAYOUT_NO_FEATURE_INDEX ((unsigned int) 0xFFFF)
|
||||
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX ((unsigned int) 0xFFFF)
|
||||
|
|
Loading…
Reference in New Issue