@@ -162,20 +162,15 @@ function markSubtable(glyphSink, type, st, cfg) {
162162 case "gsub_single" :
163163 for ( const k in st ) if ( glyphSink . has ( k ) && st [ k ] ) simplyAdd ( glyphSink , st [ k ] ) ;
164164 break ;
165+ case "gsub_alternate" :
166+ if ( cfg && cfg . ignoreAltSub ) break ;
167+ // falls through
165168 case "gsub_multiple" :
166169 for ( const k in st )
167170 if ( glyphSink . has ( k ) && st [ k ] ) {
168171 for ( const gTo of st [ k ] ) simplyAdd ( glyphSink , gTo ) ;
169172 }
170173 break ;
171- case "gsub_alternate" :
172- if ( ! cfg || ! cfg . ignoreAltSub ) {
173- for ( const k in st )
174- if ( glyphSink . has ( k ) && st [ k ] ) {
175- for ( const gTo of st [ k ] ) simplyAdd ( glyphSink , gTo ) ;
176- }
177- }
178- break ;
179174 case "gsub_ligature" :
180175 for ( const sub of st . substitutions ) {
181176 let check = true ;
@@ -228,22 +223,108 @@ function sweepOtl(gsub, glyphSink) {
228223 }
229224}
230225
231- function sweepSubtable ( st , type , glyphSink ) {
226+ function sweepSubtable ( st , type , gs ) {
232227 switch ( type ) {
233- case "gsub_ligature" : {
234- if ( ! st . substitutions ) return false ;
235- let newSubst = [ ] ;
236- for ( const rule of st . substitutions ) {
237- let include = true ;
238- if ( ! glyphSink . has ( rule . to ) ) include = false ;
239- for ( const from of rule . from ) if ( ! glyphSink . has ( from ) ) include = false ;
240- if ( include ) newSubst . push ( rule ) ;
241- }
242- st . substitutions = newSubst ;
228+ case "gsub_single" :
229+ return sweep_GsubSingle ( st , gs ) ;
230+ case "gsub_multiple" :
231+ case "gsub_alternate" :
232+ return sweep_GsubMultiple ( st , gs ) ;
233+ case "gsub_ligature" :
234+ return sweep_GsubLigature ( st , gs ) ;
235+ case "gsub_chaining" :
236+ return sweep_GsubChaining ( st , gs ) ;
237+ case "gsub_reverse" :
238+ return sweep_gsubReverse ( st , gs ) ;
239+ default :
243240 return true ;
241+ }
242+ }
243+
244+ function sweep_GsubSingle ( st , gs ) {
245+ let nonEmpty = false ;
246+ let from = Object . keys ( st ) ;
247+ for ( const gidFrom of from ) {
248+ if ( ! gs . has ( gidFrom ) || ! gs . has ( st [ gidFrom ] ) ) {
249+ delete st [ gidFrom ] ;
250+ } else {
251+ nonEmpty = true ;
244252 }
245- default : {
246- return true ;
253+ }
254+ return nonEmpty ;
255+ }
256+
257+ function sweep_GsubMultiple ( st , gs ) {
258+ let nonEmpty = false ;
259+ let from = Object . keys ( st ) ;
260+ for ( const gidFrom of from ) {
261+ let include = gs . has ( gidFrom ) ;
262+ if ( st [ gidFrom ] ) {
263+ for ( const gidTo of st [ gidFrom ] ) {
264+ include = include && gs . has ( gidTo ) ;
265+ }
266+ } else {
267+ include = false ;
268+ }
269+ if ( ! include ) {
270+ delete st [ gidFrom ] ;
271+ } else {
272+ nonEmpty = true ;
273+ }
274+ }
275+ return nonEmpty ;
276+ }
277+
278+ function sweep_GsubLigature ( st , gs ) {
279+ if ( ! st . substitutions ) return false ;
280+ let newSubst = [ ] ;
281+ for ( const rule of st . substitutions ) {
282+ let include = true ;
283+ if ( ! gs . has ( rule . to ) ) include = false ;
284+ for ( const from of rule . from ) if ( ! gs . has ( from ) ) include = false ;
285+ if ( include ) newSubst . push ( rule ) ;
286+ }
287+ st . substitutions = newSubst ;
288+ return true ;
289+ }
290+
291+ function sweep_GsubChaining ( st , gs ) {
292+ const newMatch = [ ] ;
293+ for ( let j = 0 ; j < st . match . length ; j ++ ) {
294+ newMatch [ j ] = [ ] ;
295+ for ( let k = 0 ; k < st . match [ j ] . length ; k ++ ) {
296+ const gidFrom = st . match [ j ] [ k ] ;
297+ if ( gs . has ( gidFrom ) ) {
298+ newMatch [ j ] . push ( gidFrom ) ;
299+ }
300+ }
301+ if ( ! newMatch [ j ] . length ) return false ;
302+ }
303+ st . match = newMatch ;
304+ return true ;
305+ }
306+
307+ function sweep_gsubReverse ( st , gs ) {
308+ const newMatch = [ ] ,
309+ newTo = [ ] ;
310+ for ( let j = 0 ; j < st . match . length ; j ++ ) {
311+ newMatch [ j ] = [ ] ;
312+ for ( let k = 0 ; k < st . match [ j ] . length ; k ++ ) {
313+ const gidFrom = st . match [ j ] [ k ] ;
314+ let include = gs . has ( gidFrom ) ;
315+ if ( j === st . inputIndex ) {
316+ include = include && gs . has ( st . to [ k ] ) ;
317+ if ( include ) {
318+ newMatch [ j ] . push ( gidFrom ) ;
319+ newTo . push ( st . to [ k ] ) ;
320+ }
321+ } else {
322+ if ( include ) newMatch [ j ] . push ( gidFrom ) ;
323+ }
247324 }
325+ if ( ! newMatch [ j ] . length ) return false ;
248326 }
327+ st . match = newMatch ;
328+ st . to = newTo ;
329+ return true ;
249330}
0 commit comments