summaryrefslogtreecommitdiff
path: root/Build/source/texk/lcdf-typetools/lcdf-typetools-src/otftotfm/glyphfilter.hh
blob: 4fc25ddadffcac7441453efd23cc927dc989aa44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#ifndef OTFTOTFM_GLYPHFILTER_HH
#define OTFTOTFM_GLYPHFILTER_HH
#include <efont/otf.hh>
#include <lcdf/vector.hh>
class Metrics;

class GlyphFilter { public:

    GlyphFilter()                       : _sorted(true) { }

    operator bool() const               { return _patterns.size() != 0; }

    inline bool allow_substitution(Efont::OpenType::Glyph glyph, const Vector<PermString>& glyph_names, uint32_t unicode) const;
    inline bool allow_alternate(Efont::OpenType::Glyph glyph, const Vector<PermString>& glyph_names, uint32_t unicode) const;

    void add_substitution_filter(const String&, bool is_exclude, ErrorHandler*);
    void add_alternate_filter(const String&, bool is_exclude, ErrorHandler*);

    friend bool operator==(const GlyphFilter&, const GlyphFilter&);
    inline bool check_eq(GlyphFilter&); // may alter both GlyphFilters

    GlyphFilter& operator+=(const GlyphFilter&);

    void unparse(StringAccum&) const;

    struct Pattern {
        uint16_t type;
        uint16_t data;
        union {
            struct {
                int mask;
                int value;
            } uniprop;
            struct {
                uint32_t low;
                uint32_t high;
            } unirange;
        } u;
        String pattern;
        Pattern(uint16_t type);
        static int compare(const Pattern&, const Pattern&);
    };

  private:

    enum { T_EXCLUDE = 1, T_NEGATE = 2, T_TYPEMASK = 3,
           T_SRC = 0, T_DST = 4 };
    enum { D_NAME, D_UNIPROP, D_UNIRANGE };

    Vector<Pattern> _patterns;
    bool _sorted;

    bool allow(Efont::OpenType::Glyph glyph, const Vector<PermString>& glyph_names, uint32_t unicode, int ptype) const;
    void add_pattern(const String&, int ptype, ErrorHandler*);
    void sort();

};

inline bool
GlyphFilter::allow_substitution(Efont::OpenType::Glyph glyph, const Vector<PermString>& glyph_names, uint32_t unicode) const
{
    return (!_patterns.size() || allow(glyph, glyph_names, unicode, T_SRC));
}

inline bool
GlyphFilter::allow_alternate(Efont::OpenType::Glyph glyph, const Vector<PermString>& glyph_names, uint32_t unicode) const
{
    return (!_patterns.size() || allow(glyph, glyph_names, unicode, T_DST));
}

inline bool operator==(const GlyphFilter::Pattern& a, const GlyphFilter::Pattern& b)
{
    return a.type == b.type && a.data == b.data && a.u.unirange.low == b.u.unirange.low && a.u.unirange.high == b.u.unirange.high && a.pattern == b.pattern;
}

inline bool operator<(const GlyphFilter::Pattern& a, const GlyphFilter::Pattern& b)
{
    return GlyphFilter::Pattern::compare(a, b) < 0;
}

inline bool operator!=(const GlyphFilter::Pattern& a, const GlyphFilter::Pattern& b)
{
    return !(a == b);
}

bool operator==(const GlyphFilter&, const GlyphFilter&);

inline bool operator!=(const GlyphFilter& a, const GlyphFilter& b)
{
    return !(a == b);
}

inline bool
GlyphFilter::check_eq(GlyphFilter& o)
{
    sort();
    o.sort();
    return *this == o;
}

GlyphFilter operator+(const GlyphFilter&, const GlyphFilter&);

inline StringAccum&
operator<<(StringAccum& sa, const GlyphFilter& gf)
{
    gf.unparse(sa);
    return sa;
}

#endif