@@ -113,7 +113,8 @@ const MAX_SEQUENCE: usize = 32;
113113/// script/language pair.
114114#[ derive( Clone , Default ) ]
115115pub struct FeatureStore {
116- pub features : Vec < ( RawTag , FeatureBit , u8 ) > ,
116+ pub sub_features : Vec < ( RawTag , FeatureBit ) > ,
117+ pub pos_features : Vec < ( RawTag , FeatureBit ) > ,
117118 pub lookups : Vec < LookupData > ,
118119 pub subtables : Vec < SubtableData > ,
119120 pub coverage : Vec < u16 > ,
@@ -125,7 +126,8 @@ pub struct FeatureStore {
125126
126127impl FeatureStore {
127128 pub fn clear ( & mut self ) {
128- self . features . clear ( ) ;
129+ self . sub_features . clear ( ) ;
130+ self . pos_features . clear ( ) ;
129131 self . lookups . clear ( ) ;
130132 self . subtables . clear ( ) ;
131133 self . coverage . clear ( ) ;
@@ -135,21 +137,18 @@ impl FeatureStore {
135137 self . groups = FeatureGroups :: default ( ) ;
136138 }
137139
138- pub fn bit ( & self , feature : RawTag ) -> Option < FeatureBit > {
139- match self . features . binary_search_by ( |x| x. 0 . cmp ( & feature) ) {
140- Ok ( index) => Some ( self . features [ index] . 1 ) ,
140+ pub fn sub_bit ( & self , feature : RawTag ) -> Option < FeatureBit > {
141+ match self . sub_features . binary_search_by ( |x| x. 0 . cmp ( & feature) ) {
142+ Ok ( index) => Some ( self . sub_features [ index] . 1 ) ,
141143 _ => None ,
142144 }
143145 }
144146
145- pub fn mask ( & self , features : & [ RawTag ] ) -> FeatureMask {
146- let mut mask = FeatureMask :: default ( ) ;
147- for feature in features {
148- if let Some ( bit) = self . bit ( * feature) {
149- mask. set ( bit) ;
150- }
147+ pub fn pos_bit ( & self , feature : RawTag ) -> Option < FeatureBit > {
148+ match self . pos_features . binary_search_by ( |x| x. 0 . cmp ( & feature) ) {
149+ Ok ( index) => Some ( self . pos_features [ index] . 1 ) ,
150+ _ => None ,
151151 }
152- mask
153152 }
154153
155154 /// Returns new `basic` and `position` masks based on the
@@ -161,93 +160,164 @@ impl FeatureStore {
161160 pos_args : & mut Vec < u16 > ,
162161 dir : Direction ,
163162 ) -> ( FeatureMask , FeatureMask ) {
164- let sub_count = self . sub_count ;
163+ let sub_count = self . sub_features . len ( ) ;
165164 sub_args. clear ( ) ;
166165 sub_args. resize ( sub_count, 0 ) ;
167- let pos_count = self . features . len ( ) - sub_count ;
166+ let pos_count = self . pos_features . len ( ) ;
168167 pos_args. clear ( ) ;
169168 pos_args. resize ( pos_count, 0 ) ;
170169 let mut sub = self . groups . basic ;
171- let mut pos = self . groups . position ;
172170 if dir == Direction :: RightToLeft {
173171 sub |= self . groups . rtl
174172 }
175- for feature in features {
176- if let Ok ( index) = self . features . binary_search_by ( |x| x. 0 . cmp ( & feature. 0 ) ) {
177- let cached_feature = self . features [ index] ;
178- let mask = if cached_feature. 2 == 0 {
179- & mut sub
180- } else {
181- & mut pos
182- } ;
183- let bit_index = cached_feature. 1 as usize ;
184- if cached_feature. 2 == 0 {
185- sub_args[ bit_index] = feature. 1 ;
186- } else {
187- pos_args[ bit_index] = feature. 1 ;
188- }
189- if feature. 1 != 0 {
190- mask. set ( bit_index as u16 ) ;
173+ let sub = Self :: custom_masks_for_stage (
174+ & self . sub_features ,
175+ features,
176+ self . groups . basic ,
177+ sub_args. as_mut_slice ( ) ,
178+ ) ;
179+ let pos = Self :: custom_masks_for_stage (
180+ & self . pos_features ,
181+ features,
182+ self . groups . position ,
183+ pos_args. as_mut_slice ( ) ,
184+ ) ;
185+ ( sub, pos)
186+ }
187+
188+ fn custom_masks_for_stage (
189+ stage_features : & [ ( RawTag , FeatureBit ) ] ,
190+ requested_features : & [ ( RawTag , u16 ) ] ,
191+ mut mask : FeatureMask ,
192+ args : & mut [ u16 ] ,
193+ ) -> FeatureMask {
194+ for req_feature in requested_features {
195+ if let Ok ( index) =
196+ stage_features. binary_search_by ( |x| x. 0 . cmp ( & req_feature. 0 ) )
197+ {
198+ let stage_feature = stage_features[ index] ;
199+ let bit_ix = stage_feature. 1 ;
200+ let arg = req_feature. 1 ;
201+ args[ bit_ix as usize ] = arg;
202+ if arg != 0 {
203+ mask. set ( bit_ix) ;
191204 } else {
192- mask. clear ( bit_index as u16 ) ;
205+ mask. clear ( bit_ix ) ;
193206 }
194207 }
195208 }
196- ( sub , pos )
209+ mask
197210 }
198211
199212 pub fn groups ( & self , script : Script ) -> FeatureGroups {
200- let mut g = FeatureGroups {
201- vert : self . mask ( & [ VRT2 ] ) ,
202- rtl : self . mask ( & [ RTLM ] ) ,
203- ..Default :: default ( )
204- } ;
213+ let mut g = FeatureGroups :: default ( ) ;
214+ feature_masks ( self , Some ( & mut g. vert ) , Some ( & mut g. position ) , & [ VRT2 ] ) ;
215+ feature_masks ( self , Some ( & mut g. rtl ) , Some ( & mut g. position ) , & [ RTLM ] ) ;
205216 if g. vert . is_empty ( ) {
206- g. vert = self . mask ( & [ VERT ] ) ;
217+ feature_masks ( self , Some ( & mut g. vert ) , Some ( & mut g . position ) , & [ VERT ] ) ;
207218 }
208219 if script. is_complex ( ) {
209220 match script {
210221 Script :: Myanmar => {
211- g. default = self . mask ( & [ CALT , CCMP , LOCL , RVRN ] ) ;
212- g. reph = self . bit ( RPHF ) ;
213- g. pref = self . bit ( PREF ) ;
214- // g.ortho = self.mask(&[BLWF, PSTF]);
215- // g.basic = self.mask(&[ABVS, BLWS, PRES, PSTS]);
216- g. stage1 = self . mask ( & [ BLWF , PSTF ] ) ;
217- g. stage2 = self . mask ( & [ PRES , ABVS , BLWS , PSTS ] ) ;
218- g. position = self . mask ( & [ DIST , KERN , MARK , MKMK ] ) ;
222+ feature_masks (
223+ self ,
224+ Some ( & mut g. default ) ,
225+ Some ( & mut g. position ) ,
226+ & [ CALT , CCMP , LOCL , RVRN ] ,
227+ ) ;
228+ g. reph = self . sub_bit ( RPHF ) ;
229+ g. pref = self . sub_bit ( PREF ) ;
230+ feature_masks (
231+ self ,
232+ Some ( & mut g. stage1 ) ,
233+ Some ( & mut g. position ) ,
234+ & [ BLWF , PSTF ] ,
235+ ) ;
236+ feature_masks (
237+ self ,
238+ Some ( & mut g. stage2 ) ,
239+ Some ( & mut g. position ) ,
240+ & [ PRES , ABVS , BLWS , PSTS ] ,
241+ ) ;
242+ feature_masks (
243+ self ,
244+ Some ( & mut g. basic ) ,
245+ Some ( & mut g. position ) ,
246+ & [ DIST , KERN , MARK , MKMK ] ,
247+ ) ;
219248 }
220249 _ => {
221- g. default = self . mask ( & [ AKHN , CALT , CCMP , LOCL , NUKT , RVRN ] ) ;
222- g. reph = self . bit ( RPHF ) ;
223- g. pref = self . bit ( PREF ) ;
224- g. stage1 = self . mask ( & [ ABVF , BLWF , CJCT , HALF , PSTF , RKRF , VATU ] ) ;
225- g. stage2 = if script. is_joined ( ) {
226- self . mask ( & [ FIN2 , FIN3 , FINA , INIT , ISOL , MED2 , MEDI ] )
227- } else {
228- FeatureMask :: default ( )
229- } ;
230- g. basic = self . mask ( & [
231- ABVS , BLWS , CALT , CLIG , HALN , LIGA , PRES , PSTS , RCLT , RLIG ,
232- ] ) ;
233- g. position = self . mask ( & [ ABVM , BLWM , CURS , DIST , KERN , MARK , MKMK ] ) ;
250+ feature_masks (
251+ self ,
252+ Some ( & mut g. default ) ,
253+ Some ( & mut g. position ) ,
254+ & [ AKHN , CALT , CCMP , LOCL , NUKT , RVRN ] ,
255+ ) ;
256+ g. reph = self . sub_bit ( RPHF ) ;
257+ g. pref = self . sub_bit ( PREF ) ;
258+ feature_masks (
259+ self ,
260+ Some ( & mut g. stage1 ) ,
261+ Some ( & mut g. position ) ,
262+ & [ ABVF , BLWF , CJCT , HALF , PSTF , RKRF , VATU ] ,
263+ ) ;
264+ if script. is_joined ( ) {
265+ feature_masks (
266+ self ,
267+ Some ( & mut g. stage2 ) ,
268+ Some ( & mut g. position ) ,
269+ & [ FIN2 , FIN3 , FINA , INIT , ISOL , MED2 , MEDI ] ,
270+ ) ;
271+ }
272+ feature_masks (
273+ self ,
274+ Some ( & mut g. basic ) ,
275+ Some ( & mut g. position ) ,
276+ & [ ABVS , BLWS , CALT , CLIG , HALN , LIGA , PRES , PSTS , RCLT , RLIG ] ,
277+ ) ;
278+ feature_masks (
279+ self ,
280+ Some ( & mut g. basic ) ,
281+ Some ( & mut g. position ) ,
282+ & [ ABVM , BLWM , CURS , DIST , KERN , MARK , MKMK ] ,
283+ ) ;
234284 }
235285 }
236286 } else {
237287 match script {
238288 Script :: Hangul => {
239- g. basic = self . mask ( & [ CCMP , LJMO , RVRN , TJMO , VJMO ] ) ;
289+ feature_masks (
290+ self ,
291+ Some ( & mut g. basic ) ,
292+ Some ( & mut g. position ) ,
293+ & [ CCMP , LJMO , RVRN , TJMO , VJMO ] ,
294+ ) ;
240295 }
241296 _ => {
242- g. basic = if script. is_joined ( ) {
243- self . mask ( & [
244- CALT , CCMP , CLIG , FIN2 , FIN3 , FINA , INIT , ISOL , LIGA , LOCL ,
245- MED2 , MEDI , MSET , RLIG , RVRN ,
246- ] )
297+ if script. is_joined ( ) {
298+ feature_masks (
299+ self ,
300+ Some ( & mut g. basic ) ,
301+ Some ( & mut g. position ) ,
302+ & [
303+ CALT , CCMP , CLIG , FIN2 , FIN3 , FINA , INIT , ISOL , LIGA ,
304+ LOCL , MED2 , MEDI , MSET , RLIG , RVRN ,
305+ ] ,
306+ ) ;
247307 } else {
248- self . mask ( & [ CALT , CCMP , CLIG , LIGA , LOCL , RVRN ] )
308+ feature_masks (
309+ self ,
310+ Some ( & mut g. basic ) ,
311+ Some ( & mut g. position ) ,
312+ & [ CALT , CCMP , CLIG , LIGA , LOCL , RVRN ] ,
313+ ) ;
249314 } ;
250- g. position = self . mask ( & [ CURS , DIST , KERN , MARK , MKMK ] ) ;
315+ feature_masks (
316+ self ,
317+ Some ( & mut g. basic ) ,
318+ Some ( & mut g. position ) ,
319+ & [ CURS , DIST , KERN , MARK , MKMK ] ,
320+ ) ;
251321 }
252322 }
253323 }
@@ -276,6 +346,28 @@ impl FeatureStore {
276346 // }
277347}
278348
349+ fn feature_masks (
350+ store : & FeatureStore ,
351+ sub_mask : Option < & mut FeatureMask > ,
352+ pos_mask : Option < & mut FeatureMask > ,
353+ features : & [ RawTag ] ,
354+ ) {
355+ if let Some ( sub_mask) = sub_mask {
356+ for feature in features {
357+ if let Some ( bit) = store. sub_bit ( * feature) {
358+ sub_mask. set ( bit) ;
359+ }
360+ }
361+ }
362+ if let Some ( pos_mask) = pos_mask {
363+ for feature in features {
364+ if let Some ( bit) = store. pos_bit ( * feature) {
365+ pos_mask. set ( bit) ;
366+ }
367+ }
368+ }
369+ }
370+
279371/// Builder for a feature cache.
280372#[ derive( Default ) ]
281373pub struct FeatureStoreBuilder {
@@ -298,13 +390,14 @@ impl FeatureStoreBuilder {
298390 cache. clear ( ) ;
299391 if gsub. base != 0 {
300392 self . build_stage ( cache, & b, coords, gdef, gsub, 0 ) ;
393+ cache. sub_features . sort_unstable_by ( |a, b| a. 0 . cmp ( & b. 0 ) ) ;
301394 }
302- cache. sub_count = cache. features . len ( ) ;
395+ cache. sub_count = cache. sub_features . len ( ) ;
303396 cache. pos_start = cache. lookups . len ( ) ;
304397 if gpos. base != 0 {
305398 self . build_stage ( cache, & b, coords, gdef, gpos, 1 ) ;
399+ cache. pos_features . sort_unstable_by ( |a, b| a. 0 . cmp ( & b. 0 ) ) ;
306400 }
307- cache. features . sort_unstable_by ( |a, b| a. 0 . cmp ( & b. 0 ) ) ;
308401 }
309402
310403 fn build_stage (
@@ -329,6 +422,11 @@ impl FeatureStoreBuilder {
329422 if actual_count < count {
330423 cache. truncated = true ;
331424 }
425+ let features = if stage == 0 {
426+ & mut cache. sub_features
427+ } else {
428+ & mut cache. pos_features
429+ } ;
332430 for i in 0 ..actual_count {
333431 let findex = b. read_u16 ( lbase + 6 + i * 2 ) ? as usize ;
334432 let rec = fbase + 2 + findex * 6 ;
@@ -354,7 +452,7 @@ impl FeatureStoreBuilder {
354452 } else {
355453 0
356454 } ;
357- cache . features . push ( ( ftag, fbit, stage ) ) ;
455+ features. push ( ( ftag, fbit) ) ;
358456 let foffset = if let Some ( v) = vars {
359457 if let Some ( offset) = v. apply ( b, findex as u16 ) {
360458 offset
0 commit comments