diff --git a/src/hb-ot-layout-gdef-private.h b/src/hb-ot-layout-gdef-private.h index 39d2d8751..5d4759f93 100644 --- a/src/hb-ot-layout-gdef-private.h +++ b/src/hb-ot-layout-gdef-private.h @@ -231,6 +231,12 @@ DEFINE_NULL_ASSERT_SIZE (LigCaretList, 4); struct GDEF { static const hb_tag_t Tag = HB_TAG ('G','D','E','F'); + static const hb_ot_layout_class_t UnclassifiedGlyph = 0; + static const hb_ot_layout_class_t BaseGlyph = 1; + static const hb_ot_layout_class_t LigatureGlyph = 2; + static const hb_ot_layout_class_t MarkGlyph = 3; + static const hb_ot_layout_class_t ComponentGlyph = 4; + STATIC_DEFINE_GET_FOR_DATA (GDEF); /* XXX check version here? */ @@ -240,12 +246,12 @@ struct GDEF { DEFINE_ACCESSOR (ClassDef, get_mark_attach_class_def, markAttachClassDef); /* Returns 0 if not found. */ - inline int get_glyph_class (hb_ot_layout_glyph_t glyph_id) const { + inline hb_ot_layout_class_t get_glyph_class (hb_ot_layout_glyph_t glyph_id) const { return get_glyph_class_def ().get_class (glyph_id); } /* Returns 0 if not found. */ - inline int get_mark_attachment_type (hb_ot_layout_glyph_t glyph_id) const { + inline hb_ot_layout_class_t get_mark_attachment_type (hb_ot_layout_glyph_t glyph_id) const { return get_mark_attach_class_def ().get_class (glyph_id); } diff --git a/src/hb-ot-layout-private.h b/src/hb-ot-layout-private.h index 8327197e4..55f14f8ab 100644 --- a/src/hb-ot-layout-private.h +++ b/src/hb-ot-layout-private.h @@ -35,20 +35,32 @@ #include "hb-ot-layout.h" typedef uint16_t hb_ot_layout_class_t; +typedef uint16_t hb_ot_layout_glyph_properties_t; typedef int hb_ot_layout_coverage_t; /* -1 is not covered, >= 0 otherwise */ struct GDEF; struct GSUB; struct GPOS; -HB_BEGIN_DECLS(); - struct _HB_OT_Layout { const GDEF *gdef; const GSUB *gsub; const GPOS *gpos; + + struct { + uint8_t *klasses; + unsigned int len; + } new_gdef; + }; + +HB_BEGIN_DECLS(); + +static hb_ot_layout_glyph_properties_t +_hb_ot_layout_get_glyph_properties (HB_OT_Layout *layout, + hb_ot_layout_glyph_t glyph); + HB_END_DECLS(); #endif /* HB_OT_LAYOUT_PRIVATE_H */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 827aa23ed..5fc9f8f57 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -34,6 +34,8 @@ #include "hb-ot-layout-gsub-private.h" #include +#include + HB_OT_Layout * hb_ot_layout_create (const char *font_data, @@ -57,18 +59,86 @@ hb_ot_layout_destroy (HB_OT_Layout *layout) free (layout); } -hb_ot_layout_glyph_properties_t -hb_ot_layout_get_glyph_properties (HB_OT_Layout *layout, - hb_ot_layout_glyph_t glyph) +static hb_ot_layout_glyph_properties_t +_hb_ot_layout_get_glyph_properties (HB_OT_Layout *layout, + hb_ot_layout_glyph_t glyph) { + hb_ot_layout_class_t klass; + /* TODO old harfbuzz doesn't always parse mark attachments as it says it was + * introduced without a version bump, so it may not be safe */ + klass = layout->gdef->get_mark_attachment_type (glyph); + if (klass) + return klass << 8; + + klass = layout->gdef->get_glyph_class (glyph); + + if (!klass && glyph < layout->new_gdef.len) + klass = layout->new_gdef.klasses[glyph]; + + switch (klass) { + default: + case GDEF::UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED; + case GDEF::BaseGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH; + case GDEF::LigatureGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE; + case GDEF::MarkGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_MARK; + case GDEF::ComponentGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT; + } +} + +hb_ot_layout_glyph_class_t +hb_ot_layout_get_glyph_class (HB_OT_Layout *layout, + hb_ot_layout_glyph_t glyph) +{ + hb_ot_layout_glyph_properties_t properties; + hb_ot_layout_class_t klass; + + properties = _hb_ot_layout_get_glyph_properties (layout, glyph); + + if (properties & 0xFF) + return HB_OT_LAYOUT_GLYPH_CLASS_MARK; + + return (hb_ot_layout_glyph_class_t) properties; } void -hb_ot_layout_set_glyph_properties (HB_OT_Layout *layout, - hb_ot_layout_glyph_t glyph, - hb_ot_layout_glyph_properties_t properties) +hb_ot_layout_set_glyph_class (HB_OT_Layout *layout, + hb_ot_layout_glyph_t glyph, + hb_ot_layout_glyph_class_t klass) { + /* TODO optimize this, similar to old harfbuzz code for example */ + /* TODO our semantics are a bit different from old harfbuzz code too */ + hb_ot_layout_class_t gdef_klass; + int len = layout->new_gdef.len; + + if (glyph >= len) { + int new_len; + uint8_t *new_klasses; + + new_len = len == 0 ? 120 : 2 * len; + if (new_len > 65535) + new_len = 65535; + new_klasses = (uint8_t *) realloc (layout->new_gdef.klasses, new_len * sizeof (uint8_t)); + + if (G_UNLIKELY (!new_klasses)) + return; + + memset (new_klasses + len, 0, new_len - len); + + layout->new_gdef.klasses = new_klasses; + layout->new_gdef.len = new_len; + } + + switch (klass) { + default: + case HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED: gdef_klass = GDEF::UnclassifiedGlyph; break; + case HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH: gdef_klass = GDEF::BaseGlyph; break; + case HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE: gdef_klass = GDEF::LigatureGlyph; break; + case HB_OT_LAYOUT_GLYPH_CLASS_MARK: gdef_klass = GDEF::MarkGlyph; break; + case HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT: gdef_klass = GDEF::ComponentGlyph; break; + } + + layout->new_gdef.klasses[glyph] = gdef_klass; + return; } - diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 8419d36b1..e0eb054e7 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -38,9 +38,20 @@ typedef uint32_t hb_tag_t; ((const char *) s)[2], \ ((const char *) s)[3])) -typedef uint16_t hb_ot_layout_glyph_properties_t; +typedef enum { + HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED = 0x0000, + HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH = 0x0002, + HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE = 0x0004, + HB_OT_LAYOUT_GLYPH_CLASS_MARK = 0x0008, + HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT = 0x0010 +} hb_ot_layout_glyph_class_t; + typedef uint16_t hb_ot_layout_glyph_t; +/* + * HB_OT_Layout + */ + typedef struct _HB_OT_Layout HB_OT_Layout; HB_OT_Layout * @@ -56,14 +67,14 @@ hb_ot_layout_create_sanitize (char *data, make_writable_func); */ -hb_ot_layout_glyph_properties_t -hb_ot_layout_get_glyph_properties (HB_OT_Layout *layout, - hb_ot_layout_glyph_t glyph); +hb_ot_layout_glyph_class_t +hb_ot_layout_get_glyph_class (HB_OT_Layout *layout, + hb_ot_layout_glyph_t glyph); void -hb_ot_layout_set_glyph_properties (HB_OT_Layout *layout, - hb_ot_layout_glyph_t glyph, - hb_ot_layout_glyph_properties_t properties); +hb_ot_layout_set_glyph_class (HB_OT_Layout *layout, + hb_ot_layout_glyph_t glyph, + hb_ot_layout_glyph_class_t klass); HB_END_DECLS();