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