mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
checkin for entire port source tree
This commit is contained in:
212
port_src/output/zxing/datamatrix/encoder/c40_encoder.rs
Normal file
212
port_src/output/zxing/datamatrix/encoder/c40_encoder.rs
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Jeremias Maerki.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// package com::google::zxing::datamatrix::encoder;
|
||||
|
||||
#[derive(Encoder)]
|
||||
struct C40Encoder {
|
||||
}
|
||||
|
||||
impl C40Encoder {
|
||||
|
||||
pub fn get_encoding_mode(&self) -> i32 {
|
||||
return HighLevelEncoder::C40_ENCODATION;
|
||||
}
|
||||
|
||||
fn encode_maximal(&self, context: &EncoderContext) {
|
||||
let buffer: StringBuilder = StringBuilder::new();
|
||||
let last_char_size: i32 = 0;
|
||||
let backtrack_start_position: i32 = context.pos;
|
||||
let backtrack_buffer_length: i32 = 0;
|
||||
while context.has_more_characters() {
|
||||
let c: char = context.get_current_char();
|
||||
context.pos += 1;
|
||||
last_char_size = self.encode_char(c, &buffer);
|
||||
if buffer.length() % 3 == 0 {
|
||||
backtrack_start_position = context.pos;
|
||||
backtrack_buffer_length = buffer.length();
|
||||
}
|
||||
}
|
||||
if backtrack_buffer_length != buffer.length() {
|
||||
let unwritten: i32 = (buffer.length() / 3) * 2;
|
||||
// +1 for the latch to C40
|
||||
let cur_codeword_count: i32 = context.get_codeword_count() + unwritten + 1;
|
||||
context.update_symbol_info(cur_codeword_count);
|
||||
let available: i32 = context.get_symbol_info().get_data_capacity() - cur_codeword_count;
|
||||
let rest: i32 = buffer.length() % 3;
|
||||
if (rest == 2 && available != 2) || (rest == 1 && (last_char_size > 3 || available != 1)) {
|
||||
buffer.set_length(backtrack_buffer_length);
|
||||
context.pos = backtrack_start_position;
|
||||
}
|
||||
}
|
||||
if buffer.length() > 0 {
|
||||
context.write_codeword(HighLevelEncoder::LATCH_TO_C40);
|
||||
}
|
||||
self.handle_e_o_d(context, &buffer);
|
||||
}
|
||||
|
||||
pub fn encode(&self, context: &EncoderContext) {
|
||||
//step C
|
||||
let buffer: StringBuilder = StringBuilder::new();
|
||||
while context.has_more_characters() {
|
||||
let c: char = context.get_current_char();
|
||||
context.pos += 1;
|
||||
let last_char_size: i32 = self.encode_char(c, &buffer);
|
||||
let unwritten: i32 = (buffer.length() / 3) * 2;
|
||||
let cur_codeword_count: i32 = context.get_codeword_count() + unwritten;
|
||||
context.update_symbol_info(cur_codeword_count);
|
||||
let available: i32 = context.get_symbol_info().get_data_capacity() - cur_codeword_count;
|
||||
if !context.has_more_characters() {
|
||||
//Avoid having a single C40 value in the last triplet
|
||||
let removed: StringBuilder = StringBuilder::new();
|
||||
if (buffer.length() % 3) == 2 && available != 2 {
|
||||
last_char_size = self.backtrack_one_character(context, &buffer, &removed, last_char_size);
|
||||
}
|
||||
while (buffer.length() % 3) == 1 && (last_char_size > 3 || available != 1) {
|
||||
last_char_size = self.backtrack_one_character(context, &buffer, &removed, last_char_size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
let count: i32 = buffer.length();
|
||||
if (count % 3) == 0 {
|
||||
let new_mode: i32 = HighLevelEncoder::look_ahead_test(&context.get_message(), context.pos, &self.get_encoding_mode());
|
||||
if new_mode != self.get_encoding_mode() {
|
||||
// Return to ASCII encodation, which will actually handle latch to new mode
|
||||
context.signal_encoder_change(HighLevelEncoder::ASCII_ENCODATION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.handle_e_o_d(context, &buffer);
|
||||
}
|
||||
|
||||
fn backtrack_one_character(&self, context: &EncoderContext, buffer: &StringBuilder, removed: &StringBuilder, last_char_size: i32) -> i32 {
|
||||
let count: i32 = buffer.length();
|
||||
buffer.delete(count - last_char_size, count);
|
||||
context.pos -= 1;
|
||||
let c: char = context.get_current_char();
|
||||
last_char_size = self.encode_char(c, &removed);
|
||||
//Deal with possible reduction in symbol size
|
||||
context.reset_symbol_info();
|
||||
return last_char_size;
|
||||
}
|
||||
|
||||
fn write_next_triplet( context: &EncoderContext, buffer: &StringBuilder) {
|
||||
context.write_codewords(&::encode_to_codewords(&buffer));
|
||||
buffer.delete(0, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle "end of data" situations
|
||||
*
|
||||
* @param context the encoder context
|
||||
* @param buffer the buffer with the remaining encoded characters
|
||||
*/
|
||||
fn handle_e_o_d(&self, context: &EncoderContext, buffer: &StringBuilder) {
|
||||
let unwritten: i32 = (buffer.length() / 3) * 2;
|
||||
let rest: i32 = buffer.length() % 3;
|
||||
let cur_codeword_count: i32 = context.get_codeword_count() + unwritten;
|
||||
context.update_symbol_info(cur_codeword_count);
|
||||
let available: i32 = context.get_symbol_info().get_data_capacity() - cur_codeword_count;
|
||||
if rest == 2 {
|
||||
//Shift 1
|
||||
buffer.append('\0');
|
||||
while buffer.length() >= 3 {
|
||||
::write_next_triplet(context, &buffer);
|
||||
}
|
||||
if context.has_more_characters() {
|
||||
context.write_codeword(HighLevelEncoder::C40_UNLATCH);
|
||||
}
|
||||
} else if available == 1 && rest == 1 {
|
||||
while buffer.length() >= 3 {
|
||||
::write_next_triplet(context, &buffer);
|
||||
}
|
||||
if context.has_more_characters() {
|
||||
context.write_codeword(HighLevelEncoder::C40_UNLATCH);
|
||||
}
|
||||
// else no unlatch
|
||||
context.pos -= 1;
|
||||
} else if rest == 0 {
|
||||
while buffer.length() >= 3 {
|
||||
::write_next_triplet(context, &buffer);
|
||||
}
|
||||
if available > 0 || context.has_more_characters() {
|
||||
context.write_codeword(HighLevelEncoder::C40_UNLATCH);
|
||||
}
|
||||
} else {
|
||||
throw IllegalStateException::new("Unexpected case. Please report!");
|
||||
}
|
||||
context.signal_encoder_change(HighLevelEncoder::ASCII_ENCODATION);
|
||||
}
|
||||
|
||||
fn encode_char(&self, c: char, sb: &StringBuilder) -> i32 {
|
||||
if c == ' ' {
|
||||
sb.append('\3');
|
||||
return 1;
|
||||
}
|
||||
if c >= '0' && c <= '9' {
|
||||
sb.append((c - 48 + 4) as char);
|
||||
return 1;
|
||||
}
|
||||
if c >= 'A' && c <= 'Z' {
|
||||
sb.append((c - 65 + 14) as char);
|
||||
return 1;
|
||||
}
|
||||
if c < ' ' {
|
||||
//Shift 1 Set
|
||||
sb.append('\0');
|
||||
sb.append(c);
|
||||
return 2;
|
||||
}
|
||||
if c <= '/' {
|
||||
//Shift 2 Set
|
||||
sb.append('\1');
|
||||
sb.append((c - 33) as char);
|
||||
return 2;
|
||||
}
|
||||
if c <= '@' {
|
||||
//Shift 2 Set
|
||||
sb.append('\1');
|
||||
sb.append((c - 58 + 15) as char);
|
||||
return 2;
|
||||
}
|
||||
if c <= '_' {
|
||||
//Shift 2 Set
|
||||
sb.append('\1');
|
||||
sb.append((c - 91 + 22) as char);
|
||||
return 2;
|
||||
}
|
||||
if c <= 127 {
|
||||
//Shift 3 Set
|
||||
sb.append('\2');
|
||||
sb.append((c - 96) as char);
|
||||
return 2;
|
||||
}
|
||||
//Shift 2, Upper Shift
|
||||
sb.append("\1");
|
||||
let mut len: i32 = 2;
|
||||
len += self.encode_char((c - 128) as char, &sb);
|
||||
return len;
|
||||
}
|
||||
|
||||
fn encode_to_codewords( sb: &CharSequence) -> String {
|
||||
let v: i32 = (1600 * sb.char_at(0)) + (40 * sb.char_at(1)) + sb.char_at(2) + 1;
|
||||
let cw1: char = (v / 256) as char;
|
||||
let cw2: char = (v % 256) as char;
|
||||
return String::new( : vec![char; 2] = vec![cw1, cw2, ]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user