// -*- related-file-name: "../../libefont/otfgpos.cc" -*- #ifndef EFONT_OTFGPOS_HH #define EFONT_OTFGPOS_HH #include #include namespace Efont { namespace OpenType { class GposLookup; class Positioning; class Gpos { public: Gpos(const Data &, ErrorHandler * = 0) throw (Error); // default destructor const ScriptList &script_list() const { return _script_list; } const FeatureList &feature_list() const { return _feature_list; } int nlookups() const; GposLookup lookup(unsigned) const; enum { HEADERSIZE = 10 }; private: ScriptList _script_list; FeatureList _feature_list; Data _lookup_list; }; class GposLookup { public: GposLookup(const Data &) throw (Error); int type() const { return _type; } uint16_t flags() const { return _d.u16(2); } bool unparse_automatics(Vector &, ErrorHandler * = 0) const; enum { HEADERSIZE = 6, RECSIZE = 2, L_SINGLE = 1, L_PAIR = 2, L_CURSIVE = 3, L_MARKTOBASE = 4, L_MARKTOLIGATURE = 5, L_MARKTOMARK = 6, L_CONTEXT = 7, L_CHAIN = 8, L_EXTENSION = 9 }; private: Data _d; int _type; Data subtable(int i) const; }; class GposValue { public: static inline int size(uint16_t format); static inline int16_t xplacement(uint16_t format, const Data &); static inline int16_t yplacement(uint16_t format, const Data &); static inline int16_t xadvance(uint16_t format, const Data &); static inline int16_t yadvance(uint16_t format, const Data &); enum { F_XPLACEMENT = 0x0001, F_YPLACEMENT = 0x0002, F_XADVANCE = 0x0004, F_YADVANCE = 0x0008, F_XPLACEMENT_DEVICE = 0x0010, F_YPLACEMENT_DEVICE = 0x0020, F_XADVANCE_DEVICE = 0x0040, F_YADVANCE_DEVICE = 0x0080 }; private: static const int nibble_bitcount_x2[]; }; class GposSingle { public: GposSingle(const Data &) throw (Error); // default destructor Coverage coverage() const throw (); void unparse(Vector &) const; enum { F2_HEADERSIZE = 8 }; private: Data _d; }; class GposPair { public: GposPair(const Data &) throw (Error); // default destructor Coverage coverage() const throw (); void unparse(Vector &) const; enum { F1_HEADERSIZE = 10, F1_RECSIZE = 2, PAIRSET_HEADERSIZE = 2, PAIRVALUE_HEADERSIZE = 2, F2_HEADERSIZE = 16 }; private: Data _d; }; struct Position { Glyph g; int pdx, pdy; // placement int adx, ady; // advance inline Position(); inline Position(Glyph, uint16_t format, const Data &); inline Position(uint16_t format, const Data &); inline Position(Glyph, const Position &); inline Position(Glyph g, int pdx, int pdy, int adx, int ady); bool empty() const { return pdx == 0 && pdy == 0 && adx == 0 && ady == 0; } operator bool() const { return !empty(); } bool h_empty() const { return pdx == 0 && pdy == 0 && adx == 0; } bool placed() const { return pdx != 0 || pdy != 0; } void unparse(StringAccum &, const Vector * = 0) const; String unparse(const Vector * = 0) const; }; class Positioning { public: Positioning(); // single positioning inline Positioning(const Position &); // pair positioning inline Positioning(const Position &, const Position &); bool context_in(const Coverage &) const; bool context_in(const GlyphSet &) const; // types inline operator bool() const; inline bool is_single() const; inline bool is_pair() const; inline bool is_pairkern() const; // extract data const Position &left() const { return _left; } Glyph left_glyph() const { return _left.g; } const Position &right() const { return _right; } Glyph right_glyph() const { return _right.g; } inline void all_in_glyphs(Vector &gs) const; void unparse(StringAccum &, const Vector * = 0) const; String unparse(const Vector * = 0) const; private: Position _left; Position _right; }; inline int GposValue::size(uint16_t format) { return (nibble_bitcount_x2[format & 15] + nibble_bitcount_x2[(format>>4) & 15]); } inline int16_t GposValue::xplacement(uint16_t format, const Data &d) { if (format & F_XPLACEMENT) return d.s16(0); else return 0; } inline int16_t GposValue::yplacement(uint16_t format, const Data &d) { if (format & F_YPLACEMENT) return d.s16((format & F_XPLACEMENT ? 2 : 0)); else return 0; } inline int16_t GposValue::xadvance(uint16_t format, const Data &d) { if (format & F_XADVANCE) return d.s16(nibble_bitcount_x2[format & (F_XADVANCE - 1)]); else return 0; } inline int16_t GposValue::yadvance(uint16_t format, const Data &d) { if (format & F_YADVANCE) return d.s16(nibble_bitcount_x2[format & (F_YADVANCE - 1)]); else return 0; } inline Position::Position() : g(0) { } inline Position::Position(Glyph g_, uint16_t format, const Data &value) : g(g_), pdx(GposValue::xplacement(format, value)), pdy(GposValue::yplacement(format, value)), adx(GposValue::xadvance(format, value)), ady(GposValue::yadvance(format, value)) { } inline Position::Position(uint16_t format, const Data &value) : g(0), pdx(GposValue::xplacement(format, value)), pdy(GposValue::yplacement(format, value)), adx(GposValue::xadvance(format, value)), ady(GposValue::yadvance(format, value)) { } inline Position::Position(Glyph g_, const Position &p) : g(g_), pdx(p.pdx), pdy(p.pdy), adx(p.adx), ady(p.ady) { } inline Position::Position(Glyph g_, int pdx_, int pdy_, int adx_, int ady_) : g(g_), pdx(pdx_), pdy(pdy_), adx(adx_), ady(ady_) { } inline Positioning::Positioning(const Position &left) : _left(left) { } inline Positioning::Positioning(const Position &left, const Position &right) : _left(left), _right(right) { } inline Positioning::operator bool() const { return _left.g != 0; } inline bool Positioning::is_single() const { return _left.g != 0 && _right.g == 0; } inline bool Positioning::is_pair() const { return _left.g != 0 && _right.g != 0; } inline bool Positioning::is_pairkern() const { return _left.g != 0 && !_left.placed() && _right.g != 0 && _right.h_empty(); } inline void Positioning::all_in_glyphs(Vector &gs) const { gs.clear(); if (_left.g != 0) gs.push_back(_left.g); if (_right.g != 0) gs.push_back(_right.g); } }} #endif