123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- package aztec
- import (
- "github.com/boombuler/barcode/utils"
- )
- func highlevelEncode(data []byte) *utils.BitList {
- states := stateSlice{initialState}
- for index := 0; index < len(data); index++ {
- pairCode := 0
- nextChar := byte(0)
- if index+1 < len(data) {
- nextChar = data[index+1]
- }
- switch cur := data[index]; {
- case cur == '\r' && nextChar == '\n':
- pairCode = 2
- case cur == '.' && nextChar == ' ':
- pairCode = 3
- case cur == ',' && nextChar == ' ':
- pairCode = 4
- case cur == ':' && nextChar == ' ':
- pairCode = 5
- }
- if pairCode > 0 {
- // We have one of the four special PUNCT pairs. Treat them specially.
- // Get a new set of states for the two new characters.
- states = updateStateListForPair(states, data, index, pairCode)
- index++
- } else {
- // Get a new set of states for the new character.
- states = updateStateListForChar(states, data, index)
- }
- }
- minBitCnt := int((^uint(0)) >> 1)
- var result *state = nil
- for _, s := range states {
- if s.bitCount < minBitCnt {
- minBitCnt = s.bitCount
- result = s
- }
- }
- if result != nil {
- return result.toBitList(data)
- } else {
- return new(utils.BitList)
- }
- }
- func simplifyStates(states stateSlice) stateSlice {
- var result stateSlice = nil
- for _, newState := range states {
- add := true
- var newResult stateSlice = nil
- for _, oldState := range result {
- if add && oldState.isBetterThanOrEqualTo(newState) {
- add = false
- }
- if !(add && newState.isBetterThanOrEqualTo(oldState)) {
- newResult = append(newResult, oldState)
- }
- }
- if add {
- result = append(newResult, newState)
- } else {
- result = newResult
- }
- }
- return result
- }
- // We update a set of states for a new character by updating each state
- // for the new character, merging the results, and then removing the
- // non-optimal states.
- func updateStateListForChar(states stateSlice, data []byte, index int) stateSlice {
- var result stateSlice = nil
- for _, s := range states {
- if r := updateStateForChar(s, data, index); len(r) > 0 {
- result = append(result, r...)
- }
- }
- return simplifyStates(result)
- }
- // Return a set of states that represent the possible ways of updating this
- // state for the next character. The resulting set of states are added to
- // the "result" list.
- func updateStateForChar(s *state, data []byte, index int) stateSlice {
- var result stateSlice = nil
- ch := data[index]
- charInCurrentTable := charMap[s.mode][ch] > 0
- var stateNoBinary *state = nil
- for mode := mode_upper; mode <= mode_punct; mode++ {
- charInMode := charMap[mode][ch]
- if charInMode > 0 {
- if stateNoBinary == nil {
- // Only create stateNoBinary the first time it's required.
- stateNoBinary = s.endBinaryShift(index)
- }
- // Try generating the character by latching to its mode
- if !charInCurrentTable || mode == s.mode || mode == mode_digit {
- // If the character is in the current table, we don't want to latch to
- // any other mode except possibly digit (which uses only 4 bits). Any
- // other latch would be equally successful *after* this character, and
- // so wouldn't save any bits.
- res := stateNoBinary.latchAndAppend(mode, charInMode)
- result = append(result, res)
- }
- // Try generating the character by switching to its mode.
- if _, ok := shiftTable[s.mode][mode]; !charInCurrentTable && ok {
- // It never makes sense to temporarily shift to another mode if the
- // character exists in the current mode. That can never save bits.
- res := stateNoBinary.shiftAndAppend(mode, charInMode)
- result = append(result, res)
- }
- }
- }
- if s.bShiftByteCount > 0 || charMap[s.mode][ch] == 0 {
- // It's never worthwhile to go into binary shift mode if you're not already
- // in binary shift mode, and the character exists in your current mode.
- // That can never save bits over just outputting the char in the current mode.
- res := s.addBinaryShiftChar(index)
- result = append(result, res)
- }
- return result
- }
- // We update a set of states for a new character by updating each state
- // for the new character, merging the results, and then removing the
- // non-optimal states.
- func updateStateListForPair(states stateSlice, data []byte, index int, pairCode int) stateSlice {
- var result stateSlice = nil
- for _, s := range states {
- if r := updateStateForPair(s, data, index, pairCode); len(r) > 0 {
- result = append(result, r...)
- }
- }
- return simplifyStates(result)
- }
- func updateStateForPair(s *state, data []byte, index int, pairCode int) stateSlice {
- var result stateSlice
- stateNoBinary := s.endBinaryShift(index)
- // Possibility 1. Latch to MODE_PUNCT, and then append this code
- result = append(result, stateNoBinary.latchAndAppend(mode_punct, pairCode))
- if s.mode != mode_punct {
- // Possibility 2. Shift to MODE_PUNCT, and then append this code.
- // Every state except MODE_PUNCT (handled above) can shift
- result = append(result, stateNoBinary.shiftAndAppend(mode_punct, pairCode))
- }
- if pairCode == 3 || pairCode == 4 {
- // both characters are in DIGITS. Sometimes better to just add two digits
- digitState := stateNoBinary.
- latchAndAppend(mode_digit, 16-pairCode). // period or comma in DIGIT
- latchAndAppend(mode_digit, 1) // space in DIGIT
- result = append(result, digitState)
- }
- if s.bShiftByteCount > 0 {
- // It only makes sense to do the characters as binary if we're already
- // in binary mode.
- result = append(result, s.addBinaryShiftChar(index).addBinaryShiftChar(index+1))
- }
- return result
- }
|