1 // -*- related-file-name: "../../libefont/otfgsub.cc" -*-
2 #ifndef EFONT_OTFGSUB_HH
3 #define EFONT_OTFGSUB_HH
4 #include <efont/otf.hh>
5 #include <efont/otfdata.hh>
6 namespace Efont { namespace OpenType {
7 class GsubLookup;
8 class Substitution;
9 
10 class Gsub { public:
11 
12     Gsub(const Data &, const Font *, ErrorHandler * = 0) throw (Error);
13     // default destructor
14 
script_list() const15     const ScriptList &script_list() const { return _script_list; }
feature_list() const16     const FeatureList &feature_list() const { return _feature_list; }
chaincontext_reverse_backtrack() const17     bool chaincontext_reverse_backtrack() const { return _chaincontext_reverse_backtrack; }
18 
19     int nlookups() const;
20     GsubLookup lookup(unsigned) const;
21 
22     enum { HEADERSIZE = 10 };
23 
24   private:
25 
26     ScriptList _script_list;
27     FeatureList _feature_list;
28     Data _lookup_list;
29     bool _chaincontext_reverse_backtrack;
30 
31 };
32 
33 class GsubLookup { public:
34     GsubLookup(const Data &) throw (Error);
type() const35     int type() const			{ return _type; }
flags() const36     uint16_t flags() const		{ return _d.u16(2); }
37     void mark_out_glyphs(const Gsub &gsub, Vector<bool> &gmap) const;
38     bool unparse_automatics(const Gsub &gsub, Vector<Substitution> &subs, const Coverage &limit) const;
39     bool apply(const Glyph *, int pos, int n, Substitution &) const;
40     enum {
41 	HEADERSIZE = 6, RECSIZE = 2,
42 	L_SINGLE = 1, L_MULTIPLE = 2, L_ALTERNATE = 3, L_LIGATURE = 4,
43 	L_CONTEXT = 5, L_CHAIN = 6, L_EXTENSION = 7, L_REVCHAIN = 8
44     };
45   private:
46     Data _d;
47     int _type;
48     Data subtable(int i) const;
49 };
50 
51 class GsubSingle { public:
52     GsubSingle(const Data &) throw (Error);
53     // default destructor
54     Coverage coverage() const throw ();
55     Glyph map(Glyph) const;
56     void mark_out_glyphs(Vector<bool> &gmap) const;
57     void unparse(Vector<Substitution> &subs, const Coverage &limit) const;
58     bool apply(const Glyph *, int pos, int n, Substitution &) const;
59     enum { HEADERSIZE = 6, FORMAT2_RECSIZE = 2 };
60   private:
61     Data _d;
62 };
63 
64 class GsubMultiple { public:
65     GsubMultiple(const Data &) throw (Error);
66     // default destructor
67     Coverage coverage() const throw ();
68     bool map(Glyph, Vector<Glyph> &) const;
69     void mark_out_glyphs(Vector<bool> &gmap) const;
70     void unparse(Vector<Substitution> &, bool alternate = false) const;
71     bool apply(const Glyph *, int pos, int n, Substitution &, bool alternate = false) const;
72     enum { HEADERSIZE = 6, RECSIZE = 2,
73 	   SEQ_HEADERSIZE = 2, SEQ_RECSIZE = 2 };
74   private:
75     Data _d;
76 };
77 
78 class GsubLigature { public:
79     GsubLigature(const Data &) throw (Error);
80     // default destructor
81     Coverage coverage() const throw ();
82     bool map(const Vector<Glyph> &, Glyph &, int &) const;
83     void mark_out_glyphs(Vector<bool> &gmap) const;
84     void unparse(Vector<Substitution> &) const;
85     bool apply(const Glyph *, int pos, int n, Substitution &) const;
86     enum { HEADERSIZE = 6, RECSIZE = 2,
87 	   SET_HEADERSIZE = 2, SET_RECSIZE = 2,
88 	   LIG_HEADERSIZE = 4, LIG_RECSIZE = 2 };
89   private:
90     Data _d;
91 };
92 
93 class GsubContext { public:
94     GsubContext(const Data &) throw (Error);
95     // default destructor
96     Coverage coverage() const throw ();
97     void mark_out_glyphs(const Gsub &gsub, Vector<bool> &gmap) const;
98     bool unparse(const Gsub &gsub, Vector<Substitution> &out_subs, const Coverage &limit) const;
99     enum { F3_HSIZE = 6, SUBRECSIZE = 4 };
100   private:
101     Data _d;
102     static void subruleset_mark_out_glyphs(const Data &data, int nsub, int subtab_offset, const Gsub &gsub, Vector<bool> &gmap);
103     static bool f1_unparse(const Data& data,
104                            int nsub, int subtab_offset,
105                            const Gsub& gsub, Vector<Substitution>& outsubs,
106                            Substitution prototype_sub);
107     static bool f3_unparse(const Data &data,
108 			   int nglyph, int glyphtab_offset, const Coverage &limit,
109 			   int nsub, int subtab_offset,
110 			   const Gsub &gsub, Vector<Substitution> &outsubs,
111 			   const Substitution &prototype_sub);
112     friend class GsubChainContext;
113 };
114 
115 class GsubChainContext { public:
116     GsubChainContext(const Data &) throw (Error);
117     // default destructor
118     Coverage coverage() const throw ();
119     void mark_out_glyphs(const Gsub &gsub, Vector<bool> &gmap) const;
120     bool unparse(const Gsub &gsub, Vector<Substitution> &subs, const Coverage &limit) const;
121     enum { F1_HEADERSIZE = 6, F1_RECSIZE = 2,
122 	   F1_SRS_HSIZE = 2, F1_SRS_RSIZE = 2,
123 	   F3_HSIZE = 4, F3_INPUT_HSIZE = 2, F3_LOOKAHEAD_HSIZE = 2, F3_SUBST_HSIZE = 2 };
124   private:
125     Data _d;
126     bool f1_unparse(const Gsub &gsub, Vector<Substitution> &subs, const Coverage &limit) const;
127     bool f3_unparse(const Gsub &gsub, Vector<Substitution> &subs, const Coverage &limit) const;
128 };
129 
130 class Substitution { public:
131 
132     Substitution();
133     Substitution(const Substitution &);
134 
135     // single substitution
136     Substitution(Glyph in, Glyph out);
137 
138     // multiple substitution
139     Substitution(Glyph in, const Vector<Glyph> &out, bool is_alternate = false);
140 
141     // ligature substitution
142     Substitution(Glyph in1, Glyph in2, Glyph out);
143     Substitution(const Vector<Glyph> &in, Glyph out);
144     Substitution(int nin, const Glyph *in, Glyph out);
145 
146     // space
147     Substitution(int nleft, int nin, int nout, int nright);
148 
149     ~Substitution();
150 
151     Substitution &operator=(const Substitution &);
152 
153     bool context_in(const Coverage &) const;
154     bool context_in(const GlyphSet &) const;
155 
156     // types
157     inline operator bool() const;
158     bool is_noop() const;
159     inline bool is_single() const;
160     inline bool is_multiple() const;
161     inline bool is_alternate() const;
162     inline bool is_ligature() const;
163     inline bool is_simple_context() const;
164     inline bool is_single_lcontext() const;
165     inline bool is_single_rcontext() const;
166     inline bool is_lcontext() const;
167     inline bool is_rcontext() const;
168 
169     // extract data
170     inline Glyph left_glyph() const;
171     inline int left_nglyphs() const;
172     inline Glyph *left_glyphptr();
173     inline const Glyph *left_glyphptr() const;
174 
175     inline Glyph in_glyph() const;
176     inline Glyph in_glyph(int pos) const;
177     inline bool in_glyphs(Vector<Glyph> &) const;
178     inline int in_nglyphs() const;
179     inline Glyph *in_glyphptr();
180     inline const Glyph *in_glyphptr() const;
181 
182     inline bool in_matches(int pos, Glyph) const;
183 
184     inline Glyph out_glyph() const;
185     inline Glyph out_glyph(int pos) const;
186     inline bool out_glyphs(Vector<Glyph> &) const;
187     inline Glyph *out_glyphptr();
188     inline const Glyph *out_glyphptr() const;
189 
190     inline int out_nglyphs() const;
191     inline Glyph right_glyph() const;
192     inline Glyph *right_glyphptr();
193     inline const Glyph *right_glyphptr() const;
194 
195     bool all_in_glyphs(Vector<Glyph> &gs) const;
196     bool all_out_glyphs(Vector<Glyph> &gs) const;
197 
198     // alter
199     void add_outer_left(Glyph);
200     void remove_outer_left();
201     Substitution in_out_append_glyph(Glyph) const;
202     bool out_alter(const Substitution &, int) throw ();
203     void add_outer_right(Glyph);
204     void remove_outer_right();
205 
206     void unparse(StringAccum &, const Vector<PermString> * = &debug_glyph_names) const;
207     String unparse(const Vector<PermString> * = &debug_glyph_names) const;
208 
209   private:
210 
211     enum { T_NONE = 0, T_GLYPH, T_GLYPHS, T_COVERAGE };
212     typedef union {
213 	Glyph gid;
214 	Glyph *gids;	// first entry is a count
215 	Coverage *coverage;
216     } Substitute;
217 
218     Substitute _left;
219     Substitute _in;
220     Substitute _out;
221     Substitute _right;
222 
223     uint8_t _left_is;
224     uint8_t _in_is;
225     uint8_t _out_is;
226     uint8_t _right_is;
227 
228     bool _alternate : 1;
229 
230     static void clear(Substitute &, uint8_t &);
231     static void assign_space(Substitute &, uint8_t &, int);
232     static void assign(Substitute &, uint8_t &, Glyph);
233     static void assign(Substitute &, uint8_t &, int, const Glyph *);
234     static void assign(Substitute &, uint8_t &, const Coverage &);
235     static void assign(Substitute &, uint8_t &, const Substitute &, uint8_t);
236     static void assign_append(Substitute &, uint8_t &, const Substitute &, uint8_t, const Substitute &, uint8_t);
237     static void assign_append(Substitute &, uint8_t &, const Substitute &, uint8_t, Glyph);
238     static bool substitute_in(const Substitute &, uint8_t, const Coverage &);
239     static bool substitute_in(const Substitute &, uint8_t, const GlyphSet &);
240 
241     static Glyph extract_glyph(const Substitute &, uint8_t) throw ();
242     static Glyph extract_glyph(const Substitute &, int which, uint8_t) throw ();
243     static bool extract_glyphs(const Substitute &, uint8_t, Vector<Glyph> &, bool coverage_ok) throw ();
244     static Glyph *extract_glyphptr(const Substitute &, uint8_t) throw ();
245     static int extract_nglyphs(const Substitute &, uint8_t, bool coverage_ok) throw ();
246     static bool matches(const Substitute &, uint8_t, int pos, Glyph) throw ();
247 
248     static void unparse_glyphids(StringAccum &, const Substitute &, uint8_t, const Vector<PermString> *) throw ();
249 
250 };
251 
Substitution()252 inline Substitution::Substitution()
253     : _left_is(T_NONE), _in_is(T_NONE), _out_is(T_NONE), _right_is(T_NONE)
254 {
255 }
256 
257 /* Single 1: u16 format, offset coverage, u16 glyphdelta
258    Single 2: u16 format, offset coverage, u16 count, glyph subst[]
259    Multiple 1: u16 format, offset coverage, u16 count, offset sequence[];
260      sequence is: u16 count, glyph subst[]
261    Alternate 1: u16 format, offset coverage, u16 count, offset alternates[];
262      alternate is: u16 count, glyph alts[]
263    Ligature 1: u16 format, offset coverage, u16 count, offset sets[];
264      set is: u16 count, offset ligatures[];
265      ligature is: glyph result, u16 count, glyph components[]
266 */
267 
operator bool() const268 inline Substitution::operator bool() const
269 {
270     return !(_left_is == T_NONE && _in_is == T_NONE && _out_is == T_NONE && _right_is == T_NONE);
271 }
272 
is_single() const273 inline bool Substitution::is_single() const
274 {
275     return _left_is == T_NONE && _in_is == T_GLYPH && _out_is == T_GLYPH && _right_is == T_NONE;
276 }
277 
is_multiple() const278 inline bool Substitution::is_multiple() const
279 {
280     return _left_is == T_NONE && _in_is == T_GLYPH && _out_is == T_GLYPHS && _right_is == T_NONE && !_alternate;
281 }
282 
is_alternate() const283 inline bool Substitution::is_alternate() const
284 {
285     return _left_is == T_NONE && _in_is == T_GLYPH && _out_is == T_GLYPHS && _right_is == T_NONE && _alternate;
286 }
287 
is_ligature() const288 inline bool Substitution::is_ligature() const
289 {
290     return _left_is == T_NONE && _in_is == T_GLYPHS && _out_is == T_GLYPH && _right_is == T_NONE;
291 }
292 
is_simple_context() const293 inline bool Substitution::is_simple_context() const
294 {
295     return _left_is != T_COVERAGE && (_in_is == T_GLYPH || _in_is == T_GLYPHS) && (_out_is == T_GLYPH || _out_is == T_GLYPHS) && _right_is != T_COVERAGE;
296 }
297 
is_single_lcontext() const298 inline bool Substitution::is_single_lcontext() const
299 {
300     return _left_is == T_GLYPH && _in_is == T_GLYPH && _out_is == T_GLYPH && _right_is == T_NONE;
301 }
302 
is_single_rcontext() const303 inline bool Substitution::is_single_rcontext() const
304 {
305     return _left_is == T_NONE && _in_is == T_GLYPH && _out_is == T_GLYPH && _right_is == T_GLYPH;
306 }
307 
left_glyph() const308 inline Glyph Substitution::left_glyph() const
309 {
310     return extract_glyph(_left, _left_is);
311 }
312 
left_nglyphs() const313 inline int Substitution::left_nglyphs() const
314 {
315     return extract_nglyphs(_left, _left_is, false);
316 }
317 
in_glyph() const318 inline Glyph Substitution::in_glyph() const
319 {
320     return extract_glyph(_in, _in_is);
321 }
322 
in_glyph(int which) const323 inline Glyph Substitution::in_glyph(int which) const
324 {
325     return extract_glyph(_in, which, _in_is);
326 }
327 
in_glyphs(Vector<Glyph> & v) const328 inline bool Substitution::in_glyphs(Vector<Glyph> &v) const
329 {
330     return extract_glyphs(_in, _in_is, v, true);
331 }
332 
in_nglyphs() const333 inline int Substitution::in_nglyphs() const
334 {
335     return extract_nglyphs(_in, _in_is, true);
336 }
337 
in_matches(int pos,Glyph g) const338 inline bool Substitution::in_matches(int pos, Glyph g) const
339 {
340     return matches(_in, _in_is, pos, g);
341 }
342 
out_glyph() const343 inline Glyph Substitution::out_glyph() const
344 {
345     return extract_glyph(_out, _out_is);
346 }
347 
out_glyph(int which) const348 inline Glyph Substitution::out_glyph(int which) const
349 {
350     return extract_glyph(_out, which, _out_is);
351 }
352 
out_glyphs(Vector<Glyph> & v) const353 inline bool Substitution::out_glyphs(Vector<Glyph> &v) const
354 {
355     return extract_glyphs(_out, _out_is, v, false);
356 }
357 
out_nglyphs() const358 inline int Substitution::out_nglyphs() const
359 {
360     return extract_nglyphs(_out, _out_is, false);
361 }
362 
right_glyph() const363 inline Glyph Substitution::right_glyph() const
364 {
365     return extract_glyph(_right, _right_is);
366 }
367 
left_glyphptr() const368 inline const Glyph *Substitution::left_glyphptr() const
369 {
370     return extract_glyphptr(_left, _left_is);
371 }
372 
left_glyphptr()373 inline Glyph *Substitution::left_glyphptr()
374 {
375     return extract_glyphptr(_left, _left_is);
376 }
377 
in_glyphptr() const378 inline const Glyph *Substitution::in_glyphptr() const
379 {
380     return extract_glyphptr(_in, _in_is);
381 }
382 
in_glyphptr()383 inline Glyph *Substitution::in_glyphptr()
384 {
385     return extract_glyphptr(_in, _in_is);
386 }
387 
out_glyphptr() const388 inline const Glyph *Substitution::out_glyphptr() const
389 {
390     return extract_glyphptr(_out, _out_is);
391 }
392 
out_glyphptr()393 inline Glyph *Substitution::out_glyphptr()
394 {
395     return extract_glyphptr(_out, _out_is);
396 }
397 
right_glyphptr() const398 inline const Glyph *Substitution::right_glyphptr() const
399 {
400     return extract_glyphptr(_right, _right_is);
401 }
402 
right_glyphptr()403 inline Glyph *Substitution::right_glyphptr()
404 {
405     return extract_glyphptr(_right, _right_is);
406 }
407 
operator <<(StringAccum & sa,const Substitution & sub)408 inline StringAccum &operator<<(StringAccum &sa, const Substitution &sub)
409 {
410     sub.unparse(sa);
411     return sa;
412 }
413 
414 }}
415 #endif
416