@@ -251,6 +251,13 @@ class RecordTmpl < BinData::Record
251251 37 => "tmBOX"
252252 }
253253
254+
255+ # When options overlap in the binary space, ordinary bitmasks
256+ # are not the correct tool to use for detection. We use digit
257+ # position and presence instead.
258+
259+ DIGIT_MODE_VARIATIONS = [ 9 ]
260+
254261 # Top-level keys are template identifiers, defined in TEMPLATES.
255262 # Second-level keys are bits for certain variations, negative keys mean
256263 # that the variation is present if the bit is absent.
@@ -264,20 +271,26 @@ class RecordTmpl < BinData::Record
264271
265272 # Intervals:
266273 9 => {
267- 0x0000 => "tvINTV_LEFT_LP" , # left fence is left parenthesis
268- 0x0001 => "tvINTV_LEFT_RP" , # left fence is right parenthesis
269- 0x0002 => "tvINTV_LEFT_LB" , # left fence is left bracket
270- 0x0003 => "tvINTV_LEFT_RB" , # left fence is right bracket
271- 0x0004 => "tvINTV_RIGHT_LP" , # right fence is left parenthesis # WARNING: DOCUMENTATION SAYS 0x0000?
272- 0x0010 => "tvINTV_RIGHT_RP" , # right fence is right parenthesis
273- 0x0020 => "tvINTV_RIGHT_LB" , # right fence is left bracket
274- 0x0030 => "tvINTV_RIGHT_RB" , # right fence is right bracket
275- # Added to match MathML translator
276- 0x0022 => "tvINTV_LBLB" ,
277- 0x0033 => "tvINTV_RBRB" ,
278- 0x0023 => "tvINTV_RBLB" ,
279- 0x0012 => "tvINTV_LBRP" ,
280- 0x0030 => "tvINTV_LPRB"
274+ # 0x0000 => "tvINTV_LEFT_LP", # left fence is left parenthesis
275+ # 0x0001 => "tvINTV_LEFT_RP", # left fence is right parenthesis
276+ # 0x0002 => "tvINTV_LEFT_LB", # left fence is left bracket
277+ # 0x0003 => "tvINTV_LEFT_RB", # left fence is right bracket
278+ # 0x0004 => "tvINTV_RIGHT_LP", # right fence is left parenthesis # WARNING: DOCUMENTATION SAYS 0x0000?
279+ # 0x0010 => "tvINTV_RIGHT_RP", # right fence is right parenthesis
280+ # 0x0020 => "tvINTV_RIGHT_LB", # right fence is left bracket
281+ # 0x0030 => "tvINTV_RIGHT_RB", # right fence is right bracket
282+ # Replaced above to match MathML translator
283+ 0x0002 => {
284+ 0x0020 => "tvINTV_LBLB" , # left bracket, left bracket
285+ 0x0010 => "tvINTV_LBRP" , # left bracket, right parenthesis
286+ } ,
287+ 0x0003 => {
288+ 0x0030 => "tvINTV_RBRB" , # right bracket, right bracket
289+ 0x0020 => "tvINTV_RBLB" , # right bracket, left bracket
290+ } ,
291+ 0x0000 => {
292+ 0x0030 => "tvINTV_LPRB" , # left parenthesis, right bracket
293+ }
281294 } ,
282295
283296 # Radicals (square and nth roots):
@@ -415,28 +428,26 @@ class RecordTmpl < BinData::Record
415428 end
416429
417430 def variation
418- variation = ( _variation_first_byte & 0x7F ) | ( _variation_second_byte << 8 )
419- variations = VARIATIONS . select do |selector , _ |
431+ @ variation = ( _variation_first_byte & 0x7F ) | ( _variation_second_byte << 8 )
432+ @ variations = VARIATIONS . select do |selector , _ |
420433 selector === _selector
421434 end . values . reduce ( Hash . new , :merge )
422435
423- process_variations ( variation , variations )
436+ process_variations
424437 end
425438
426- def process_variations ( variation , variations )
427- variations . select do |bit , value |
428- # bit should NOT be active
429- if bit < 0
430- variation & -bit == 0
431- # bit should be active
432- else
433- variation & bit == bit
439+ def process_variations
440+ @variations . select do |flag , _ |
441+ if flag < 0 # flag should NOT be active
442+ !check_flag ( -flag )
443+ else # flag should be active
444+ check_flag ( flag )
434445 end
435- end . map do |bit , value |
446+ end . map do |flag , value |
436447 case value
437448 when Hash # Conditional variations
438- result = value . detect do |conditional , value |
439- variation & conditional == conditional
449+ result = value . detect do |conditional , _ |
450+ check_flag ( conditional )
440451 end
441452 result . last if result
442453 else
@@ -445,6 +456,41 @@ def process_variations(variation, variations)
445456 end . uniq
446457 end
447458
459+ def check_flag ( flag )
460+ case mode
461+ when :bitmask
462+ check_bitmask ( flag )
463+ when :digit
464+ check_digit ( flag )
465+ end
466+ end
467+
468+ def check_bitmask ( flag )
469+ if flag == 0
470+ @variation & 0xf == 0
471+ else
472+ @variation & flag == flag
473+ end
474+ end
475+
476+ # E.g. is 0x3 present in 0x33
477+ def check_digit ( flag )
478+ digits = if flag == 0
479+ 1
480+ else
481+ ( Math . log ( flag +1 ) /Math . log ( 16 ) ) . ceil # digits in a hex number
482+ end
483+ mask = ( 15 <<( 4 *digits -4 ) ) # e.g. 0xf0
484+ variation_digit = ( @variation & mask ) >> ( digits * 4 - 4 )
485+ flag_digit = ( flag & mask ) >> ( digits * 4 - 4 )
486+ variation_digit == flag_digit
487+ end
488+
489+
490+ def mode
491+ DIGIT_MODE_VARIATIONS . include? ( selector ) ? :digit : :bitmask
492+ end
493+
448494 def selector
449495 SELECTORS [ _selector ]
450496 end
0 commit comments