[harfbuzz/GSUB] towards a partially working GSUB

This commit is contained in:
Behdad Esfahbod 2009-04-16 04:45:30 -04:00
parent 30bd763fa2
commit 5a0b791184
9 changed files with 407 additions and 170 deletions

View File

@ -59,7 +59,7 @@
/* Internal API */ /* Internal API */
static HB_Error /*static XXX */ HB_Error
hb_buffer_ensure( HB_Buffer buffer, hb_buffer_ensure( HB_Buffer buffer,
HB_UInt size ) HB_UInt size )
{ {

View File

@ -78,7 +78,7 @@ HB_BEGIN_HEADER
#define ALLOC(_ptr,_size) \ #define ALLOC(_ptr,_size) \
( (_ptr) = _hb_alloc( _size, &error ), error != 0 ) ( *(void**)&(_ptr) = _hb_alloc( _size, &error ), error != 0 )
#define REALLOC(_ptr,_newsz) \ #define REALLOC(_ptr,_newsz) \
( (_ptr) = _hb_realloc( (_ptr), (_newsz), &error ), error != 0 ) ( (_ptr) = _hb_realloc( (_ptr), (_newsz), &error ), error != 0 )

View File

@ -24,7 +24,6 @@
#define HB_INTERNAL static #define HB_INTERNAL static
#include "harfbuzz-buffer.c" #include "harfbuzz-buffer.c"
#include "harfbuzz-gdef.c"
#include "harfbuzz-gsub.c" #include "harfbuzz-gsub.c"
#include "harfbuzz-gpos.c" #include "harfbuzz-gpos.c"
#include "harfbuzz-impl.c" #include "harfbuzz-impl.c"

View File

@ -35,7 +35,7 @@
#define DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP(Type, name) \ #define DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP(Type, name) \
inline const Type& name (hb_codepoint_t glyph) { \ inline const Type& name (hb_codepoint_t glyph) { \
const Coverage &c = get_coverage (); \ 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]; \ return (*this)[c_index]; \
} }
@ -209,7 +209,7 @@ struct LigCaretList {
DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (LigGlyph, get_lig_glyph); DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (LigGlyph, get_lig_glyph);
private: private:
/* AttachPoint tables, in Coverage Index order */ /* LigGlyph tables, in Coverage Index order */
DEFINE_OFFSET_ARRAY_TYPE (LigGlyph, ligGlyph, ligGlyphCount); DEFINE_OFFSET_ARRAY_TYPE (LigGlyph, ligGlyph, ligGlyphCount);
DEFINE_GET_ACCESSOR (Coverage, coverage, coverage); DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);

View File

@ -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. * This is part of HarfBuzz, an OpenType Layout engine library.
* *
@ -35,7 +35,7 @@
#include "harfbuzz-buffer-private.h" /* XXX */ #include "harfbuzz-buffer-private.h" /* XXX */
#define DEFINE_GET_GLYPH_COVERAGE(name) \ #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 (); \ const Coverage &c = get_coverage (); \
return c.get_coverage (glyph); \ return c.get_coverage (glyph); \
} }
@ -46,6 +46,12 @@
unsigned int context_length, \ unsigned int context_length, \
unsigned int nesting_level_left, \ unsigned int nesting_level_left, \
unsigned int lookup_flag) const unsigned int lookup_flag) const
#define SUBTABLE_SUBSTITUTE_CHAIN(obj) \
obj.substitute (layout, \
buffer, \
context_length, \
nesting_level_left, \
lookup_flag)
struct SingleSubstFormat1 { struct SingleSubstFormat1 {
@ -55,9 +61,163 @@ struct SingleSubstFormat1 {
DEFINE_GET_ACCESSOR (Coverage, coverage, coverage); DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
DEFINE_GET_GLYPH_COVERAGE (glyph_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 { inline SUBTABLE_SUBSTITUTE {
hb_codepoint_t glyph_id; 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; unsigned int property;
HB_UNUSED (nesting_level_left); HB_UNUSED (nesting_level_left);
@ -71,77 +231,27 @@ struct SingleSubstFormat1 {
glyph_id = IN_CURGLYPH (); glyph_id = IN_CURGLYPH ();
index = get_glyph_coverage (glyph_id); index = get_glyph_coverage (glyph_id);
if (-1 == index) if (index >= sequenceCount)
return false; return false;
glyph_id += deltaGlyphID; const Sequence &seq = (*this)[index];
_hb_buffer_replace_output_glyph (buffer, glyph_id, context_length == NO_CONTEXT); _hb_buffer_add_output_glyph_ids (buffer, 1,
seq.glyphCount, seq.substitute,
0xFFFF, 0xFFFF);
if ( _hb_ot_layout_has_new_glyph_classes (layout) ) if ( _hb_ot_layout_has_new_glyph_classes (layout) )
{ {
/* we inherit the old glyph class to the substituted glyph */ /* this is a guess only ... */
_hb_ot_layout_set_glyph_property (layout, glyph_id, property);
if ( property == HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE )
property = HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
seq.set_glyph_class (layout, property);
} }
return true; 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: private:
USHORT substFormat; /* Format identifier--format = 1 */ USHORT substFormat; /* Format identifier--format = 1 */
Offset coverage; /* Offset to Coverage table--from Offset coverage; /* Offset to Coverage table--from
@ -155,16 +265,42 @@ struct MultipleSubstFormat1 {
}; };
ASSERT_SIZE (MultipleSubstFormat1, 6); 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 */ /* TODO */
private: private:
USHORT glyphCount; /* Number of GlyphIDs in the Substitute USHORT glyphCount; /* Number of GlyphIDs in the Alternate
* array. This should always be * array */
* greater than 0. */ GlyphID alternate[]; /* Array of alternate GlyphIDs--in
GlyphID substitute[]; /* String of GlyphIDs to substitute */ * arbitrary order */
}; };
DEFINE_NULL_ASSERT_SIZE (Sequence, 2); DEFINE_NULL_ASSERT_SIZE (AlternateSet, 2);
struct AlternateSubstFormat1 { struct AlternateSubstFormat1 {
/* TODO */ /* TODO */
@ -181,16 +317,30 @@ struct AlternateSubstFormat1 {
}; };
ASSERT_SIZE (AlternateSubstFormat1, 6); ASSERT_SIZE (AlternateSubstFormat1, 6);
struct AlternateSet {
struct Ligature {
/* TODO */ /* TODO */
private: private:
USHORT glyphCount; /* Number of GlyphIDs in the Alternate GlyphID ligGlyph; /* GlyphID of ligature to substitute */
* array */ USHORT compCount; /* Number of components in the ligature */
GlyphID alternate[]; /* Array of alternate GlyphIDs--in GlyphID component[]; /* Array of component GlyphIDs--start
* arbitrary order */ * 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 { struct LigatureSubstFormat1 {
/* TODO */ /* TODO */
@ -207,29 +357,6 @@ struct LigatureSubstFormat1 {
}; };
ASSERT_SIZE (LigatureSubstFormat1, 6); 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 { struct SubstLookupRecord {
/* TODO */ /* TODO */
@ -533,6 +660,17 @@ ASSERT_SIZE (ReverseChainSingleSubstFormat1, 10);
* SubstLookup * 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 { struct SubstLookupSubTable {
DEFINE_NON_INSTANTIABLE(SubstLookupSubTable); DEFINE_NON_INSTANTIABLE(SubstLookupSubTable);
@ -543,14 +681,14 @@ struct SubstLookupSubTable {
// case 1: return u.format1.get_size (); // case 1: return u.format1.get_size ();
// case 2: return u.format2.get_size (); // case 2: return u.format2.get_size ();
/* /*
case Single: case GSUB_Single:
case Multiple: case GSUB_Multiple:
case Alternate: case GSUB_Alternate:
case Ligature: case GSUB_Ligature:
case Context: case GSUB_Context:
case ChainingContext: case GSUB_ChainingContext:
case Extension: case GSUB_Extension:
case ReverseChainingContextSingle: case GSUB_ReverseChainingContextSingle:
*/ */
default:return sizeof (LookupSubTable); default:return sizeof (LookupSubTable);
} }
@ -562,13 +700,25 @@ struct SubstLookupSubTable {
unsigned int nesting_level_left, unsigned int nesting_level_left,
unsigned int lookup_type, unsigned int lookup_type,
unsigned int lookup_flag) const { 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: private:
union { union {
USHORT substFormat; USHORT substFormat;
CoverageFormat1 format1; SingleSubst singleSubst;
CoverageFormat2 format2;
} u; } u;
}; };
@ -576,25 +726,16 @@ struct SubstLookup : Lookup {
DEFINE_NON_INSTANTIABLE(SubstLookup); 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 { inline const SubstLookupSubTable& get_subtable (unsigned int i) const {
return *(SubstLookupSubTable*)&(((Lookup *)this)->get_subtable (i)); return *(SubstLookupSubTable*)&(((Lookup *)this)->get_subtable (i));
} }
/* Like get_type(), but looks through extension lookups. /* Like get_type(), but looks through extension lookups.
* Never returns SubstLookup::Extension */ * Never returns Extension */
inline unsigned int get_effective_type (void) const { inline unsigned int get_effective_type (void) const {
unsigned int type = get_type (); unsigned int type = get_type ();
if (HB_UNLIKELY (type == Extension)) { if (HB_UNLIKELY (type == GSUB_Extension)) {
/* Return lookup type of first extension subtable. /* Return lookup type of first extension subtable.
* The spec says all of them should have the same type. * The spec says all of them should have the same type.
* XXX check for that somehow */ * XXX check for that somehow */
@ -606,15 +747,16 @@ struct SubstLookup : Lookup {
inline bool is_reverse (void) const { inline bool is_reverse (void) const {
switch (get_effective_type ()) { switch (get_effective_type ()) {
case ReverseChainingContextSingle: return true; case GSUB_ReverseChainingContextSingle: return true;
default: return false; default: return false;
} }
} }
inline bool substitute (hb_ot_layout_t *layout, inline bool substitute_once (hb_ot_layout_t *layout,
hb_buffer_t *buffer, hb_buffer_t *buffer,
unsigned int context_length, unsigned int context_length,
unsigned int nesting_level_left) const { unsigned int nesting_level_left) const {
unsigned int lookup_type = get_type (); unsigned int lookup_type = get_type ();
unsigned int lookup_flag = get_flag (); unsigned int lookup_flag = get_flag ();
@ -630,6 +772,47 @@ struct SubstLookup : Lookup {
return false; 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); DEFINE_NULL_ALIAS (SubstLookup, Lookup);

View File

@ -36,6 +36,9 @@
#define NO_INDEX ((unsigned int) 0xFFFF) #define NO_INDEX ((unsigned int) 0xFFFF)
#define NO_CONTEXT ((unsigned int) -1) #define NO_CONTEXT ((unsigned int) -1)
#define NOT_COVERED ((unsigned int) -1)
#define MAX_NESTING_LEVEL 32
/* /*
* Int types * Int types
@ -717,16 +720,16 @@ struct CoverageFormat1 {
/* GlyphIDs, in sorted numerical order */ /* GlyphIDs, in sorted numerical order */
DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount); 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; GlyphID gid;
if (HB_UNLIKELY (glyph_id > 65535)) if (HB_UNLIKELY (glyph_id > 65535))
return -1; return NOT_COVERED;
gid = glyph_id; gid = glyph_id;
// TODO: bsearch // TODO: bsearch
for (unsigned int i = 0; i < glyphCount; i++) for (unsigned int i = 0; i < glyphCount; i++)
if (gid == glyphArray[i]) if (gid == glyphArray[i])
return i; return i;
return -1; return NOT_COVERED;
} }
private: private:
@ -741,10 +744,10 @@ struct CoverageRangeRecord {
friend struct CoverageFormat2; friend struct CoverageFormat2;
private: 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) if (glyph_id >= start && glyph_id <= end)
return startCoverageIndex + (glyph_id - start); return startCoverageIndex + (glyph_id - start);
return -1; return NOT_COVERED;
} }
private: private:
@ -763,14 +766,14 @@ struct CoverageFormat2 {
/* CoverageRangeRecords, in sorted numerical start order */ /* CoverageRangeRecords, in sorted numerical start order */
DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount); 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 // TODO: bsearch
for (unsigned int i = 0; i < rangeCount; i++) { for (unsigned int i = 0; i < rangeCount; i++) {
int coverage = rangeRecord[i].get_coverage (glyph_id); int coverage = rangeRecord[i].get_coverage (glyph_id);
if (coverage >= 0) if (coverage >= 0)
return coverage; return coverage;
} }
return -1; return NOT_COVERED;
} }
private: 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) { switch (u.coverageFormat) {
case 1: return u.format1.get_coverage(glyph_id); case 1: return u.format1.get_coverage(glyph_id);
case 2: return u.format2.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); 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 */ #endif /* HB_OT_LAYOUT_OPEN_PRIVATE_H */

View File

@ -35,7 +35,6 @@
typedef unsigned int hb_ot_layout_class_t; 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 */ /* XXX #define HB_OT_LAYOUT_INTERNAL static */
#define HB_OT_LAYOUT_INTERNAL #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 lookup_flags,
unsigned int *property); unsigned int *property);
/* XXX */
HB_Error
hb_buffer_ensure( HB_Buffer buffer,
HB_UInt size );
HB_END_DECLS(); HB_END_DECLS();
#endif /* HB_OT_LAYOUT_PRIVATE_H */ #endif /* HB_OT_LAYOUT_PRIVATE_H */

View File

@ -544,42 +544,82 @@ hb_ot_layout_substitute_lookup (hb_ot_layout_t *layout,
{ {
const GSUB &gsub = *(layout->gsub); const GSUB &gsub = *(layout->gsub);
const SubstLookup &l = gsub.get_lookup (lookup_index); 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);
} else {
/* in-place backward substitution */
buffer->in_pos = buffer->in_length - 1;
do {
if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
l.substitute (layout, buffer, context_length, nesting_level_left))
ret = true;
else
buffer->in_pos--;
} while (buffer->in_pos);
}
return ret;
} }
/* XXX dupped, until he old code can be removed */
static HB_Error
hb_buffer_duplicate_out_buffer( HB_Buffer buffer )
{
if ( !buffer->alt_string )
{
HB_Error error;
if ( ALLOC_ARRAY( buffer->alt_string, buffer->allocated, HB_GlyphItemRec ) )
return error;
}
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;
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;
}
buffer->in_pos += num_in;
buffer->out_pos += num_out;
buffer->out_length = buffer->out_pos;
return HB_Err_Ok;
}

View File

@ -93,8 +93,6 @@ typedef enum {
typedef uint32_t hb_ot_layout_feature_mask_t; 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_SCRIPT_INDEX ((unsigned int) 0xFFFF)
#define HB_OT_LAYOUT_NO_FEATURE_INDEX ((unsigned int) 0xFFFF) #define HB_OT_LAYOUT_NO_FEATURE_INDEX ((unsigned int) 0xFFFF)
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX ((unsigned int) 0xFFFF) #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX ((unsigned int) 0xFFFF)