From 2d15e72c75931398db5e027e660f1320bb979117 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 15 Apr 2009 19:50:16 -0400 Subject: [PATCH] Give it a start at GSUB --- src/hb-common.h | 5 +- src/hb-ot-layout-gdef-private.h | 24 ++++---- src/hb-ot-layout-gsub-private.h | 120 +++++++++++++++++++++++++++++++++++++++- src/hb-ot-layout-open-private.h | 51 ++++++++++------- src/hb-ot-layout-private.h | 2 +- src/hb-ot-layout.cc | 63 +++++++++++++++++++-- src/hb-ot-layout.h | 29 +++++++++- src/main.cc | 4 +- 8 files changed, 253 insertions(+), 45 deletions(-) diff --git a/src/hb-common.h b/src/hb-common.h index c60ad84..d404353 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -46,6 +46,9 @@ typedef uint32_t hb_tag_t; ((const char *) s)[2], \ ((const char *) s)[3])) -typedef uint16_t hb_glyph_t; +typedef uint32_t hb_codepoint_t; + +/* XXX */ +typedef struct HB_BufferRec_ hb_buffer_t; #endif /* HB_COMMON_H */ diff --git a/src/hb-ot-layout-gdef-private.h b/src/hb-ot-layout-gdef-private.h index 447ee0e..5418d8b 100644 --- a/src/hb-ot-layout-gdef-private.h +++ b/src/hb-ot-layout-gdef-private.h @@ -33,18 +33,18 @@ #define DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP(Type, name) \ - inline const Type& name (hb_glyph_t glyph_id) { \ + inline const Type& name (hb_codepoint_t glyph) { \ const Coverage &c = get_coverage (); \ - hb_ot_layout_coverage_t c_index = c.get_coverage (glyph_id); \ + hb_ot_layout_coverage_t c_index = c.get_coverage (glyph); \ return (*this)[c_index]; \ } struct GlyphClassDef : ClassDef { - static const uint16_t BaseGlyph = 0x0001u; - static const uint16_t LigatureGlyph = 0x0002u; - static const uint16_t MarkGlyph = 0x0003u; - static const uint16_t ComponentGlyph = 0x0004u; + static const unsigned int BaseGlyph = 0x0001u; + static const unsigned int LigatureGlyph = 0x0002u; + static const unsigned int MarkGlyph = 0x0003u; + static const unsigned int ComponentGlyph = 0x0004u; }; /* @@ -72,7 +72,7 @@ struct AttachList { friend struct GDEF; private: - /* const AttachPoint& get_attach_points (hb_glyph_t glyph_id); */ + /* const AttachPoint& get_attach_points (hb_codepoint_t glyph); */ DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (AttachPoint, get_attach_points); private: @@ -205,7 +205,7 @@ struct LigCaretList { friend struct GDEF; private: - /* const LigGlyph& get_lig_glyph (hb_glyph_t glyph_id); */ + /* const LigGlyph& get_lig_glyph (hb_codepoint_t glyph); */ DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (LigGlyph, get_lig_glyph); private: @@ -245,12 +245,12 @@ struct GDEF { DEFINE_GET_HAS_ACCESSOR (LigCaretList, lig_caret_list, ligCaretList); DEFINE_GET_HAS_ACCESSOR (ClassDef, mark_attachment_types, markAttachClassDef); - inline hb_ot_layout_class_t get_glyph_class (hb_glyph_t glyph_id) const { - return get_glyph_classes ().get_class (glyph_id); + inline hb_ot_layout_class_t get_glyph_class (hb_codepoint_t glyph) const { + return get_glyph_classes ().get_class (glyph); } - inline hb_ot_layout_class_t get_mark_attachment_type (hb_glyph_t glyph_id) const { - return get_mark_attachment_types ().get_class (glyph_id); + inline hb_ot_layout_class_t get_mark_attachment_type (hb_codepoint_t glyph) const { + return get_mark_attachment_types ().get_class (glyph); } /* TODO get_attach and get_lig_caret */ diff --git a/src/hb-ot-layout-gsub-private.h b/src/hb-ot-layout-gsub-private.h index 8ce7705..ae41090 100644 --- a/src/hb-ot-layout-gsub-private.h +++ b/src/hb-ot-layout-gsub-private.h @@ -34,7 +34,17 @@ struct SingleSubstFormat1 { - /* TODO */ + + friend struct SingleSubst; + + private: + inline bool substitute (hb_ot_layout_t *layout, + hb_buffer_t *buffer, + unsigned int context_length, + unsigned int nesting_level_left) const { +// if (get_coverage (IN_CURGLYPH())) +// return ; + } private: USHORT substFormat; /* Format identifier--format = 1 */ @@ -450,6 +460,108 @@ struct ReverseChainSingleSubstFormat1 { ASSERT_SIZE (ReverseChainSingleSubstFormat1, 10); /* + * SubstLookup + */ + +struct SubstLookupSubTable { + DEFINE_NON_INSTANTIABLE(SubstLookupSubTable); + + friend struct SubstLookup; + + unsigned int get_size (unsigned int lookup_type) const { + switch (lookup_type) { +// 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: + */ + default:return sizeof (LookupSubTable); + } + } + + inline bool substitute (hb_ot_layout_t *layout, + hb_buffer_t *buffer, + unsigned int context_length, + unsigned int nesting_level_left, + unsigned int lookup_type) const { + } + + private: + union { + USHORT substFormat; + CoverageFormat1 format1; + CoverageFormat2 format2; + } u; +}; + +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 */ + inline unsigned int get_effective_type (void) const { + unsigned int type = get_type (); + + if (HB_UNLIKELY (type == Extension)) { + /* Return lookup type of first extension subtable. + * The spec says all of them should have the same type. + * XXX check for that somehow */ +//XXX type = get_subtable(0).v.extension.get_type (); + } + + return type; + } + + inline bool is_reverse (void) const { + switch (get_effective_type ()) { + case 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 { + unsigned int lookup_type = get_type (); + + if (HB_UNLIKELY (nesting_level_left == 0)) + return false; + nesting_level_left--; + + for (unsigned int i = 0; i < get_subtable_count (); i++) + if (get_subtable (i).substitute (layout, buffer, + context_length, nesting_level_left, + lookup_type)) + return true; + + return false; + } +}; +DEFINE_NULL_ALIAS (SubstLookup, Lookup); + +/* * GSUB */ @@ -458,6 +570,12 @@ struct GSUB : GSUBGPOS { STATIC_DEFINE_GET_FOR_DATA (GSUB); /* XXX check version here? */ + + inline const SubstLookup& get_lookup (unsigned int i) const { + return *(SubstLookup*)&(((GSUBGPOS *)this)->get_lookup (i)); + } + + }; DEFINE_NULL_ALIAS (GSUB, GSUBGPOS); diff --git a/src/hb-ot-layout-open-private.h b/src/hb-ot-layout-open-private.h index 9d45f7c..66fd55e 100644 --- a/src/hb-ot-layout-open-private.h +++ b/src/hb-ot-layout-open-private.h @@ -35,6 +35,7 @@ #define NO_INDEX ((unsigned int) 0xFFFF) +#define NO_CONTEXT ((unsigned int) -1) /* * Int types @@ -191,7 +192,7 @@ /* makes class uninstantiable. should be used for union classes that don't * contain any complete type */ #define DEFINE_NON_INSTANTIABLE(Type) \ - private: inline Type() {} /* cannot be instantiated */ \ + protected: inline Type() {} /* cannot be instantiated */ \ public: // TODO use a global nul-array for most Null's @@ -236,6 +237,7 @@ + /* * * The OpenType Font File @@ -642,12 +644,12 @@ struct FeatureList { DEFINE_NULL_ASSERT_SIZE (FeatureList, 2); struct LookupFlag : USHORT { - static const uint16_t RightToLeft = 0x0001u; - static const uint16_t IgnoreBaseGlyphs = 0x0002u; - static const uint16_t IgnoreLigatures = 0x0004u; - static const uint16_t IgnoreMarks = 0x0008u; - static const uint16_t Reserved = 0x00F0u; - static const uint16_t MarkAttachmentType = 0xFF00u; + static const unsigned int RightToLeft = 0x0001u; + static const unsigned int IgnoreBaseGlyphs = 0x0002u; + static const unsigned int IgnoreLigatures = 0x0004u; + static const unsigned int IgnoreMarks = 0x0008u; + static const unsigned int Reserved = 0x00F0u; + static const unsigned int MarkAttachmentType = 0xFF00u; }; DEFINE_NULL_ASSERT_SIZE (LookupFlag, 2); @@ -661,8 +663,9 @@ DEFINE_NULL_ASSERT_SIZE (LookupSubTable, 2); struct Lookup { - /* SubTables, in the desired order */ - DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount); + DEFINE_NON_INSTANTIABLE(Lookup); + + DEFINE_ARRAY_INTERFACE (LookupSubTable, subtable); /* get_subtable_count(), get_subtable(i) */ inline bool is_right_to_left (void) const { return lookupFlag & LookupFlag::RightToLeft; } inline bool ignore_base_glyphs(void) const { return lookupFlag & LookupFlag::IgnoreBaseGlyphs; } @@ -670,10 +673,14 @@ struct Lookup { inline bool ignore_marks (void) const { return lookupFlag & LookupFlag::IgnoreMarks; } inline bool get_mark_attachment_type (void) const { return lookupFlag & LookupFlag::MarkAttachmentType; } - inline uint16_t get_type (void) const { return lookupType; } - inline uint16_t get_flag (void) const { return lookupFlag; } + inline unsigned int get_type (void) const { return lookupType; } + inline unsigned int get_flag (void) const { return lookupFlag; } private: + /* SubTables, in the desired order */ + DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount); + + protected: USHORT lookupType; /* Different enumerations for GSUB and GPOS */ USHORT lookupFlag; /* Lookup qualifiers */ USHORT subTableCount; /* Number of SubTables for this lookup */ @@ -710,8 +717,10 @@ struct CoverageFormat1 { /* GlyphIDs, in sorted numerical order */ DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount); - inline hb_ot_layout_coverage_t get_coverage (hb_glyph_t glyph_id) const { + inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const { GlyphID gid; + if (HB_UNLIKELY (glyph_id > 65535)) + return -1; gid = glyph_id; // TODO: bsearch for (unsigned int i = 0; i < glyphCount; i++) @@ -732,7 +741,7 @@ struct CoverageRangeRecord { friend struct CoverageFormat2; private: - inline hb_ot_layout_coverage_t get_coverage (hb_glyph_t glyph_id) const { + inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const { if (glyph_id >= start && glyph_id <= end) return startCoverageIndex + (glyph_id - start); return -1; @@ -754,7 +763,7 @@ struct CoverageFormat2 { /* CoverageRangeRecords, in sorted numerical start order */ DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount); - inline hb_ot_layout_coverage_t get_coverage (hb_glyph_t glyph_id) const { + inline hb_ot_layout_coverage_t 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); @@ -784,7 +793,7 @@ struct Coverage { } } - hb_ot_layout_coverage_t get_coverage (hb_glyph_t glyph_id) const { + hb_ot_layout_coverage_t 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); @@ -813,7 +822,7 @@ struct ClassDefFormat1 { /* GlyphIDs, in sorted numerical order */ DEFINE_ARRAY_TYPE (USHORT, classValueArray, glyphCount); - inline hb_ot_layout_class_t get_class (hb_glyph_t glyph_id) const { + inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const { if (glyph_id >= startGlyph && glyph_id - startGlyph < glyphCount) return classValueArray[glyph_id - startGlyph]; return 0; @@ -832,7 +841,7 @@ struct ClassRangeRecord { friend struct ClassDefFormat2; private: - inline hb_ot_layout_class_t get_class (hb_glyph_t glyph_id) const { + inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const { if (glyph_id >= start && glyph_id <= end) return classValue; return 0; @@ -853,9 +862,9 @@ struct ClassDefFormat2 { /* ClassRangeRecords, in sorted numerical start order */ DEFINE_ARRAY_TYPE (ClassRangeRecord, rangeRecord, rangeCount); - inline hb_ot_layout_class_t get_class (hb_glyph_t glyph_id) const { + inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const { // TODO: bsearch - for (int i = 0; i < rangeCount; i++) { + for (unsigned int i = 0; i < rangeCount; i++) { int classValue = rangeRecord[i].get_class (glyph_id); if (classValue > 0) return classValue; @@ -882,7 +891,7 @@ struct ClassDef { } } - hb_ot_layout_class_t get_class (hb_glyph_t glyph_id) const { + hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const { switch (u.classFormat) { case 1: return u.format1.get_class(glyph_id); case 2: return u.format2.get_class(glyph_id); @@ -949,7 +958,7 @@ DEFINE_NULL_ASSERT_SIZE (Device, 6); * GSUB/GPOS Common */ -typedef struct GSUBGPOS { +struct GSUBGPOS { static const hb_tag_t GSUBTag = HB_TAG ('G','S','U','B'); static const hb_tag_t GPOSTag = HB_TAG ('G','P','O','S'); diff --git a/src/hb-ot-layout-private.h b/src/hb-ot-layout-private.h index 8060e4f..a1be8aa 100644 --- a/src/hb-ot-layout-private.h +++ b/src/hb-ot-layout-private.h @@ -53,7 +53,7 @@ _hb_ot_layout_has_new_glyph_classes (hb_ot_layout_t *layout); HB_OT_LAYOUT_INTERNAL hb_ot_layout_glyph_properties_t _hb_ot_layout_get_glyph_properties (hb_ot_layout_t *layout, - hb_glyph_t glyph); + hb_codepoint_t glyph); HB_OT_LAYOUT_INTERNAL hb_bool_t _hb_ot_layout_check_glyph_properties (hb_ot_layout_t *layout, diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 1172248..68fd3e5 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -35,6 +35,8 @@ #include "hb-ot-layout-gdef-private.h" #include "hb-ot-layout-gsub-private.h" +/* XXX */ +#include "harfbuzz-buffer-private.h" #include #include @@ -50,6 +52,7 @@ struct _hb_ot_layout_t { unsigned int len; } new_gdef; + /* TODO add max-nesting-level here? */ }; hb_ot_layout_t * @@ -109,7 +112,7 @@ _hb_ot_layout_has_new_glyph_classes (hb_ot_layout_t *layout) HB_OT_LAYOUT_INTERNAL hb_ot_layout_glyph_properties_t _hb_ot_layout_get_glyph_properties (hb_ot_layout_t *layout, - hb_glyph_t glyph) + hb_codepoint_t glyph) { hb_ot_layout_class_t klass; @@ -186,7 +189,7 @@ _hb_ot_layout_check_glyph_properties (hb_ot_layout_t *layout, hb_ot_layout_glyph_class_t hb_ot_layout_get_glyph_class (hb_ot_layout_t *layout, - hb_glyph_t glyph) + hb_codepoint_t glyph) { hb_ot_layout_glyph_properties_t properties; hb_ot_layout_class_t klass; @@ -201,7 +204,7 @@ hb_ot_layout_get_glyph_class (hb_ot_layout_t *layout, void hb_ot_layout_set_glyph_class (hb_ot_layout_t *layout, - hb_glyph_t glyph, + hb_codepoint_t glyph, hb_ot_layout_glyph_class_t klass) { /* TODO optimize this, similar to old harfbuzz code for example */ @@ -243,7 +246,7 @@ hb_ot_layout_set_glyph_class (hb_ot_layout_t *layout, void hb_ot_layout_build_glyph_classes (hb_ot_layout_t *layout, uint16_t num_total_glyphs, - hb_glyph_t *glyphs, + hb_codepoint_t *glyphs, unsigned char *klasses, uint16_t count) { @@ -508,3 +511,55 @@ hb_ot_layout_feature_get_lookup_index (hb_ot_layout_t *layout, return f.get_lookup_index (num_lookup); } + +/* + * GSUB + */ + +hb_bool_t +hb_ot_layout_substitute_lookup (hb_ot_layout_t *layout, + hb_buffer_t *buffer, + unsigned int lookup_index, + hb_ot_layout_feature_mask_t mask) +{ + 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 ()) { + + /* 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; +} diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 447dac2..c29485c 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -67,17 +67,17 @@ hb_ot_layout_has_font_glyph_classes (hb_ot_layout_t *layout); hb_ot_layout_glyph_class_t hb_ot_layout_get_glyph_class (hb_ot_layout_t *layout, - hb_glyph_t glyph); + hb_codepoint_t glyph); void hb_ot_layout_set_glyph_class (hb_ot_layout_t *layout, - hb_glyph_t glyph, + hb_codepoint_t glyph, hb_ot_layout_glyph_class_t klass); void hb_ot_layout_build_glyph_classes (hb_ot_layout_t *layout, uint16_t num_total_glyphs, - hb_glyph_t *glyphs, + hb_codepoint_t *glyphs, unsigned char *klasses, uint16_t count); @@ -91,6 +91,10 @@ typedef enum { HB_OT_LAYOUT_TABLE_TYPE_NONE } hb_ot_layout_table_type_t; +typedef uint16_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) @@ -195,6 +199,25 @@ hb_ot_layout_feature_get_lookup_index (hb_ot_layout_t *layout, unsigned int feature_index, unsigned int num_lookup); +/* + * GSUB + */ + +hb_bool_t +hb_ot_layout_substitute_lookup (hb_ot_layout_t *layout, + hb_buffer_t *buffer, + unsigned int lookup_index, + hb_ot_layout_feature_mask_t mask); + + + + + + + + + + /* #define PANGO_OT_ALL_GLYPHS ((guint) 0xFFFF) diff --git a/src/main.cc b/src/main.cc index b149e11..4c24ff4 100644 --- a/src/main.cc +++ b/src/main.cc @@ -125,10 +125,10 @@ main (int argc, char **argv) feature.get_lookup_count()); int num_lookups = feature.get_lookup_count (); - printf (" %d lookup(s) found in language system\n", num_lookups); + printf (" %d lookup(s) found in feature\n", num_lookups); for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) { unsigned int lookup_index = feature.get_lookup_index (n_lookup); - printf (" Feature index %2d of %2d: %d\n", n_lookup, num_lookups, + printf (" Lookup index %2d of %2d: %d\n", n_lookup, num_lookups, feature.get_lookup_index (n_lookup)); } } -- 2.7.4