Class: Mathtype::RecordTmpl

Inherits:
BinData::Record
  • Object
show all
Includes:
Snapshot
Defined in:
lib/records/tmpl.rb

Constant Summary collapse

EXPOSED_IN_SNAPSHOT =
%i(selector variation template_specific_options nudge
subobject_list)
SELECTORS =
{
  # Fences (parentheses, etc.):
  0 => "tmANGLE",
  1 => "tmPAREN",
  2 => "tmBRACE",
  3 => "tmBRACK",
  4 => "tmBAR",
  5 => "tmDBAR",
  6 => "tmFLOOR",
  7 => "tmCEILING",
  8 => "tmOBRACK",
  # Intervals:
  9 => "tmINTERVAL",
  # Radicals (square and nth roots):
  10 => "tmROOT",
  # Fractions:
  11 => "tmFRACT",
  # Over and Underbars:
  12 => "tmUBAR",
  13 => "tmOBAR",
  # Arrows:
  14  => "tmARROW",
  # Integrals (see Limit Variations):
  15  => "tmINTEG",
  # Sums, products, coproducts, unions, intersections, etc. (see Limit Variations):
  16 => "tmSUM",
  17 => "tmPROD",
  18 => "tmCOPROD",
  19 => "tmUNION",
  20 => "tmINTER",
  21 => "tmINTOP",
  22 => "tmSUMOP",
  # Limits (see Limit Variations):
  23 => "tmLIM",
  # Horizontal braces and brackets:
  24 => "tmHBRACE",
  25 => "tmHBRACK",
  # Long division:
  26 => "tmLDIV",
  # Subscripts and superscripts:
  27 => "tmSUB",
  28 => "tmSUP",
  29 => "tmSUBSUP",
  # Dirac bra-ket notation:
  30 => "tmDIRAC",
  # Vectors:
  31 => "tmVEC",
  # Hats, arcs, tilde, joint status:
  32 => "tmTILDE",
  33 => "tmHAT",
  34 => "tmARC",
  35 => "tmJSTATUS",
  # Overstrikes (cross-outs):
  36 => "tmSTRIKE",
  # Boxes:
  37 => "tmBOX"
}
DIGIT_MODE_VARIATIONS =

When options overlap in the binary space, ordinary bitmasks are not the correct tool to use for detection. We use digit position and presence instead.

[9]
VARIATIONS =

Top-level keys are template identifiers, defined in TEMPLATES. Second-level keys are bits for certain variations, negative keys mean that the variation is present if the bit is absent.

{
  # Fences (parentheses, etc.):
  0..8 => {
    0x0001 => "tvFENCE_L", # left fence is present
    0x0002 => "tvFENCE_R", # right fence is present
  },

  # Intervals:
  9 => {
    # 0x0000 => "tvINTV_LEFT_LP", #  left fence is left parenthesis
    # 0x0001 => "tvINTV_LEFT_RP", #  left fence is right parenthesis
    # 0x0002 => "tvINTV_LEFT_LB", #  left fence is left bracket
    # 0x0003 => "tvINTV_LEFT_RB", #  left fence is right bracket
    # 0x0004 => "tvINTV_RIGHT_LP", # right fence is left parenthesis # WARNING: DOCUMENTATION SAYS 0x0000?
    # 0x0010 => "tvINTV_RIGHT_RP", # right fence is right parenthesis
    # 0x0020 => "tvINTV_RIGHT_LB", # right fence is left bracket
    # 0x0030 => "tvINTV_RIGHT_RB", # right fence is right bracket
    # Replaced above to match MathML translator
    0x0002 => {
      0x0020 => "tvINTV_LBLB", # left bracket, left bracket
      0x0010 => "tvINTV_LBRP", # left bracket, right parenthesis
    },
    0x0003 => {
      0x0030 => "tvINTV_RBRB", # right bracket, right bracket
      0x0020 => "tvINTV_RBLB", # right bracket, left bracket
    },
    0x0000 => {
      0x0030 => "tvINTV_LPRB", # left parenthesis, right bracket
    }
  },

  # Radicals (square and nth roots):
  10 => {
    0 => "tvROOT_SQ", # square root
    1 => "tvROOT_NTH", # nth root
  },

  # Fractions:
  11 => {
    0x0001 => "tvFR_SMALL", #  subscript-size slots (piece fraction)
    0x0002 => "tvFR_SLASH", #  fraction bar is a slash
    0x0004 => "tvFR_BASE", # num. and denom. are baseline aligned
  },

  # Over and Underbars:
  12..13 => {
    0x0001 => "tvBAR_DOUBLE", #  bar is doubled, else single
  },

  # Arrows:
  14 => {
    0x0000 => "tvAR_SINGLE", # single arrow
    0x0001 => "tvAR_DOUBLE", # double arrow
    0x0010 => {
      0x0001 => "tvAR_LOS", # if double, large over small,
      0x0002 => "tvAR_LOS", # if harpoon, large over small,
      0x0000 => "tvAR_LEFT" # if single, arrow points left
    },
    0x0020 => {
      0x0001 => "tvAR_SOL", # if double, small over large
      0x0002 => "tvAR_SOL", # if harpoon, small over large
      0x0000 => "tvAR_RIGHT", # if single, arrow points right
    },
    0x0002 => "tvAR_HARPOON", # harpoon
    0x0004 => { # top slot is present
      0x0008 => "tvAR_TOPBOTTOM", # both slots are present
      0x0004 => "tvAR_TOP"
    },
    0x0008 => { # bottom slot is present
      0x0004 => "tvAR_TOPBOTTOM", # both slots are present
      0x0008 => "tvAR_BOTTOM"
    }
  },

  # Integrals (see Limit Variations):
  15 => {
    0x0001 => "tvINT_1", # single integral sign
    0x0002 => "tvINT_2", # double integral sign
    0x0003 => "tvINT_3", # triple integral sign
    0x0004 => "tvINT_LOOP", # has loop w/o arrows
    0x0008 => "tvINT_CW_LOOP", # has clockwise loop
    0x000C => "tvINT_CCW_LOOP", # has counter-clockwise loop
    0x0100 => "tvINT_EXPAND", #  integral signs expand
  },

  # Limit variations
  15..23 => {
    0x0010 => "tvBO_LOWER", # lower limit is present
    0x0020 => "tvBO_UPPER", # upper limit is present
    0x0040 => "tvBO_SUM", # summation-style limit positions,
    -0x0040 => "tvBO_INT" # else integral-style
  },

  # Sums, products, coproducts, unions, intersections, etc. (see Limit Variations):
  23 => {
    0 => "tvSUBAR", # single underbar
    1 => "tvDUBAR", # double underbar
  },

  # Horizontal braces and brackets:
  24..25 => {
    0x0001 => "tvHB_TOP", #  slot is on the top, else on the bottom
  },

  # Long division:
  26 => {
    0x0001 => "tvLD_UPPER", #  upper slot is present
  },

  # Subscripts and superscripts:
  27..29 => {
    0x0001 => "tvSU_PRECEDES", # script precedes scripted item, else follows
  },

  # Dirac bra-ket notation:
  30 => {
    0x0001 => "tvDI_LEFT", # left part is present
    0x0002 => "tvDI_RIGHT", #  right part is present
  },

  # Vectors:
  31 => {
    0x0001 => "tvVE_LEFT", # arrow points left
    0x0002 => "tvVE_RIGHT", #  arrow points right
    0x0004 => "tvVE_UNDER", #  arrow under slot, else over slot
    0x0008 => "tvVE_HARPOON", #  harpoon
  },

  # Hats, arcs, tilde, joint status:
  32..35 => {},

  # Overstrikes (cross-outs):
  36 => {
    0x0001 => "tvST_HORIZ", #  line is horizontal, else slashes
    0x0002 => "tvST_UP", # if slashes, slash from lower-left to upper-right is present
    0x0004 => "tvST_DOWN", # if slashes, slash from upper-left to lower-right is present
  },

  # Boxes:
  37 => {
    0x0001 => "tvBX_ROUND", #  corners are round, else square
    0x0002 => "tvBX_LEFT", # left side is present
    0x0004 => "tvBX_RIGHT", #  right side is present
    0x0008 => "tvBX_TOP", #  top side is present
    0x0010 => "tvBX_BOTTOM", # bottom side is present
  }
}

Instance Method Summary collapse

Methods included from Snapshot

#snapshot

Instance Method Details

#check_bitmask(flag) ⇒ Object



468
469
470
471
472
473
474
# File 'lib/records/tmpl.rb', line 468

def check_bitmask(flag)
  if flag == 0
    @variation & 0xf == 0
  else
    @variation & flag == flag
  end
end

#check_digit(flag) ⇒ Object

E.g. is 0x3 present in 0x33



477
478
479
480
481
482
483
484
485
486
487
# File 'lib/records/tmpl.rb', line 477

def check_digit(flag)
  digits = if flag == 0
    1
  else
    (Math.log(flag+1)/Math.log(16)).ceil # digits in a hex number
  end
  mask = (15<<(4*digits-4)) # e.g. 0xf0
  variation_digit = (@variation & mask) >> (digits * 4 - 4)
  flag_digit = (flag & mask) >> (digits * 4 - 4)
  variation_digit == flag_digit
end

#check_flag(flag) ⇒ Object



459
460
461
462
463
464
465
466
# File 'lib/records/tmpl.rb', line 459

def check_flag(flag)
  case mode
  when :bitmask
    check_bitmask(flag)
  when :digit
    check_digit(flag)
  end
end

#modeObject



490
491
492
# File 'lib/records/tmpl.rb', line 490

def mode
  DIGIT_MODE_VARIATIONS.include?(selector) ? :digit : :bitmask
end

#process_variationsObject



439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
# File 'lib/records/tmpl.rb', line 439

def process_variations
  @variations.select do |flag, _|
    if flag < 0 # flag should NOT be active
      !check_flag(-flag)
    else # flag should be active
      check_flag(flag)
    end
  end.map do |flag, value|
    case value
    when Hash # Conditional variations
      result = value.detect do |conditional, _|
        check_flag(conditional)
      end
      result.last if result
    else
      value
    end
  end.uniq
end

#selectorObject



494
495
496
# File 'lib/records/tmpl.rb', line 494

def selector
  SELECTORS[_selector]
end

#variationObject



430
431
432
433
434
435
436
437
# File 'lib/records/tmpl.rb', line 430

def variation
  @variation = (_variation_first_byte & 0x7F) | (_variation_second_byte << 8)
  @variations = VARIATIONS.select do |selector, _|
    selector === _selector
  end.values.reduce(Hash.new, :merge)

  process_variations
end