codabar_writer + test

This commit is contained in:
Henry Schimke
2022-12-10 12:46:03 -06:00
parent da16a67c04
commit b366e59e28
10 changed files with 521 additions and 368 deletions

View File

@@ -1,140 +0,0 @@
/*
* Copyright 2011 ZXing authors
*
* 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.oned;
import com.google.zxing.BarcodeFormat;
import java.util.Collection;
import java.util.Collections;
/**
* This class renders CodaBar as {@code boolean[]}.
*
* @author dsbnatut@gmail.com (Kazuki Nishiura)
*/
public final class CodaBarWriter extends OneDimensionalCodeWriter {
private static final char[] START_END_CHARS = {'A', 'B', 'C', 'D'};
private static final char[] ALT_START_END_CHARS = {'T', 'N', '*', 'E'};
private static final char[] CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED = {'/', ':', '+', '.'};
private static final char DEFAULT_GUARD = START_END_CHARS[0];
@Override
protected Collection<BarcodeFormat> getSupportedWriteFormats() {
return Collections.singleton(BarcodeFormat.CODABAR);
}
@Override
public boolean[] encode(String contents) {
if (contents.length() < 2) {
// Can't have a start/end guard, so tentatively add default guards
contents = DEFAULT_GUARD + contents + DEFAULT_GUARD;
} else {
// Verify input and calculate decoded length.
char firstChar = Character.toUpperCase(contents.charAt(0));
char lastChar = Character.toUpperCase(contents.charAt(contents.length() - 1));
boolean startsNormal = CodaBarReader.arrayContains(START_END_CHARS, firstChar);
boolean endsNormal = CodaBarReader.arrayContains(START_END_CHARS, lastChar);
boolean startsAlt = CodaBarReader.arrayContains(ALT_START_END_CHARS, firstChar);
boolean endsAlt = CodaBarReader.arrayContains(ALT_START_END_CHARS, lastChar);
if (startsNormal) {
if (!endsNormal) {
throw new IllegalArgumentException("Invalid start/end guards: " + contents);
}
// else already has valid start/end
} else if (startsAlt) {
if (!endsAlt) {
throw new IllegalArgumentException("Invalid start/end guards: " + contents);
}
// else already has valid start/end
} else {
// Doesn't start with a guard
if (endsNormal || endsAlt) {
throw new IllegalArgumentException("Invalid start/end guards: " + contents);
}
// else doesn't end with guard either, so add a default
contents = DEFAULT_GUARD + contents + DEFAULT_GUARD;
}
}
// The start character and the end character are decoded to 10 length each.
int resultLength = 20;
for (int i = 1; i < contents.length() - 1; i++) {
if (Character.isDigit(contents.charAt(i)) || contents.charAt(i) == '-' || contents.charAt(i) == '$') {
resultLength += 9;
} else if (CodaBarReader.arrayContains(CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED, contents.charAt(i))) {
resultLength += 10;
} else {
throw new IllegalArgumentException("Cannot encode : '" + contents.charAt(i) + '\'');
}
}
// A blank is placed between each character.
resultLength += contents.length() - 1;
boolean[] result = new boolean[resultLength];
int position = 0;
for (int index = 0; index < contents.length(); index++) {
char c = Character.toUpperCase(contents.charAt(index));
if (index == 0 || index == contents.length() - 1) {
// The start/end chars are not in the CodaBarReader.ALPHABET.
switch (c) {
case 'T':
c = 'A';
break;
case 'N':
c = 'B';
break;
case '*':
c = 'C';
break;
case 'E':
c = 'D';
break;
}
}
int code = 0;
for (int i = 0; i < CodaBarReader.ALPHABET.length; i++) {
// Found any, because I checked above.
if (c == CodaBarReader.ALPHABET[i]) {
code = CodaBarReader.CHARACTER_ENCODINGS[i];
break;
}
}
boolean color = true;
int counter = 0;
int bit = 0;
while (bit < 7) { // A character consists of 7 digit.
result[position] = color;
position++;
if (((code >> (6 - bit)) & 1) == 0 || counter == 1) {
color = !color; // Flip the color.
bit++;
counter = 0;
} else {
counter++;
}
}
if (index < contents.length() - 1) {
result[position] = false;
position++;
}
}
return result;
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2011 ZXing authors
*
* 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.oned;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.BitMatrixTestCase;
import org.junit.Assert;
import org.junit.Test;
/**
* @author dsbnatut@gmail.com (Kazuki Nishiura)
* @author Sean Owen
*/
public final class CodaBarWriterTestCase extends Assert {
@Test
public void testEncode() {
doTest("B515-3/B",
"00000" +
"1001001011" + "0110101001" + "0101011001" + "0110101001" + "0101001101" +
"0110010101" + "01101101011" + "01001001011" +
"00000");
}
@Test
public void testEncode2() {
doTest("T123T",
"00000" +
"1011001001" + "0101011001" + "0101001011" + "0110010101" + "01011001001" +
"00000");
}
@Test
public void testAltStartEnd() {
assertEquals(encode("T123456789-$T"), encode("A123456789-$A"));
}
private static void doTest(String input, CharSequence expected) {
BitMatrix result = encode(input);
assertEquals(expected, BitMatrixTestCase.matrixToString(result));
}
private static BitMatrix encode(String input) {
return new CodaBarWriter().encode(input, BarcodeFormat.CODABAR, 0, 0);
}
}

View File

@@ -1,158 +0,0 @@
/*
* Copyright 2011 ZXing authors
*
* 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.oned;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.Writer;
import com.google.zxing.common.BitMatrix;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Pattern;
/**
* <p>Encapsulates functionality and implementation that is common to one-dimensional barcodes.</p>
*
* @author dsbnatut@gmail.com (Kazuki Nishiura)
*/
public abstract class OneDimensionalCodeWriter implements Writer {
private static final Pattern NUMERIC = Pattern.compile("[0-9]+");
/**
* Encode the contents to boolean array expression of one-dimensional barcode.
* Start code and end code should be included in result, and side margins should not be included.
*
* @param contents barcode contents to encode
* @return a {@code boolean[]} of horizontal pixels (false = white, true = black)
*/
public abstract boolean[] encode(String contents);
/**
* Can be overwritten if the encode requires to read the hints map. Otherwise it defaults to {@code encode}.
* @param contents barcode contents to encode
* @param hints encoding hints
* @return a {@code boolean[]} of horizontal pixels (false = white, true = black)
*/
protected boolean[] encode(String contents, Map<EncodeHintType,?> hints) {
return encode(contents);
}
@Override
public final BitMatrix encode(String contents, BarcodeFormat format, int width, int height) {
return encode(contents, format, width, height, null);
}
/**
* Encode the contents following specified format.
* {@code width} and {@code height} are required size. This method may return bigger size
* {@code BitMatrix} when specified size is too small. The user can set both {@code width} and
* {@code height} to zero to get minimum size barcode. If negative value is set to {@code width}
* or {@code height}, {@code IllegalArgumentException} is thrown.
*/
@Override
public BitMatrix encode(String contents,
BarcodeFormat format,
int width,
int height,
Map<EncodeHintType,?> hints) {
if (contents.isEmpty()) {
throw new IllegalArgumentException("Found empty contents");
}
if (width < 0 || height < 0) {
throw new IllegalArgumentException("Negative size is not allowed. Input: "
+ width + 'x' + height);
}
Collection<BarcodeFormat> supportedFormats = getSupportedWriteFormats();
if (supportedFormats != null && !supportedFormats.contains(format)) {
throw new IllegalArgumentException("Can only encode " + supportedFormats +
", but got " + format);
}
int sidesMargin = getDefaultMargin();
if (hints != null && hints.containsKey(EncodeHintType.MARGIN)) {
sidesMargin = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString());
}
boolean[] code = encode(contents, hints);
return renderRXingResult(code, width, height, sidesMargin);
}
protected Collection<BarcodeFormat> getSupportedWriteFormats() {
return null;
}
/**
* @return a byte array of horizontal pixels (0 = white, 1 = black)
*/
private static BitMatrix renderRXingResult(boolean[] code, int width, int height, int sidesMargin) {
int inputWidth = code.length;
// Add quiet zone on both sides.
int fullWidth = inputWidth + sidesMargin;
int outputWidth = Math.max(width, fullWidth);
int outputHeight = Math.max(1, height);
int multiple = outputWidth / fullWidth;
int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
BitMatrix output = new BitMatrix(outputWidth, outputHeight);
for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
if (code[inputX]) {
output.setRegion(outputX, 0, multiple, outputHeight);
}
}
return output;
}
/**
* @param contents string to check for numeric characters
* @throws IllegalArgumentException if input contains characters other than digits 0-9.
*/
protected static void checkNumeric(String contents) {
if (!NUMERIC.matcher(contents).matches()) {
throw new IllegalArgumentException("Input should only contain digits 0-9");
}
}
/**
* @param target encode black/white pattern into this array
* @param pos position to start encoding at in {@code target}
* @param pattern lengths of black/white runs to encode
* @param startColor starting color - false for white, true for black
* @return the number of elements added to target.
*/
protected static int appendPattern(boolean[] target, int pos, int[] pattern, boolean startColor) {
boolean color = startColor;
int numAdded = 0;
for (int len : pattern) {
for (int j = 0; j < len; j++) {
target[pos++] = color;
}
numAdded += len;
color = !color; // flip color after each segment
}
return numAdded;
}
public int getDefaultMargin() {
// CodaBar spec requires a side margin to be more than ten times wider than narrow space.
// This seems like a decent idea for a default for all formats.
return 10;
}
}

View File

@@ -174,11 +174,11 @@ impl CodaBarReader {
// These values are critical for determining how permissive the decoding
// will be. All stripe sizes must be within the window these define, as
// compared to the average stripe size.
const MAX_ACCEPTABLE: f32 = 2.0;
const PADDING: f32 = 1.5;
pub const MAX_ACCEPTABLE: f32 = 2.0;
pub const PADDING: f32 = 1.5;
// const ALPHABET_STRING : &str= "0123456789-$:/.+ABCD";
const ALPHABET: [char; 20] = [
pub const ALPHABET: [char; 20] = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '$', ':', '/', '.', '+', 'A', 'B',
'C', 'D',
];
@@ -187,7 +187,7 @@ impl CodaBarReader {
* These represent the encodings of characters, as patterns of wide and narrow bars. The 7 least-significant bits of
* each int correspond to the pattern of wide and narrow, with 1s representing "wide" and 0s representing narrow.
*/
const CHARACTER_ENCODINGS: [u32; 20] = [
pub const CHARACTER_ENCODINGS: [u32; 20] = [
0x003, 0x006, 0x009, 0x060, 0x012, 0x042, 0x021, 0x024, 0x030, 0x048, // 0-9
0x00c, 0x018, 0x045, 0x051, 0x054, 0x015, 0x01A, 0x029, 0x00B, 0x00E, // -$:/.+ABCD
];
@@ -195,10 +195,10 @@ impl CodaBarReader {
// minimal number of characters that should be present (including start and stop characters)
// under normal circumstances this should be set to 3, but can be set higher
// as a last-ditch attempt to reduce false positives.
const MIN_CHARACTER_LENGTH: u32 = 3;
pub const MIN_CHARACTER_LENGTH: u32 = 3;
// official start and end patterns
const STARTEND_ENCODING: [char; 4] = ['A', 'B', 'C', 'D'];
pub const STARTEND_ENCODING: [char; 4] = ['A', 'B', 'C', 'D'];
// some Codabar generator allow the Codabar string to be closed by every
// character. This will cause lots of false positives!

230
src/oned/coda_bar_writer.rs Normal file
View File

@@ -0,0 +1,230 @@
/*
* Copyright 2011 ZXing authors
*
* 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.
*/
use one_d_reader_derive::OneDWriter;
use crate::BarcodeFormat;
use super::{CodaBarReader, OneDimensionalCodeWriter};
const START_END_CHARS: [char; 4] = ['A', 'B', 'C', 'D'];
const ALT_START_END_CHARS: [char; 4] = ['T', 'N', '*', 'E'];
const CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED: [char; 4] = ['/', ':', '+', '.'];
const DEFAULT_GUARD: char = START_END_CHARS[0];
/**
* This class renders CodaBar as {@code boolean[]}.
*
* @author dsbnatut@gmail.com (Kazuki Nishiura)
*/
#[derive(OneDWriter)]
pub struct CodaBarWriter;
impl OneDimensionalCodeWriter for CodaBarWriter {
fn encode_oned(&self, contents: &str) -> Result<Vec<bool>, crate::Exceptions> {
let contents = if contents.chars().count() < 2 {
// Can't have a start/end guard, so tentatively add default guards
format!("{}{}{}", DEFAULT_GUARD, contents, DEFAULT_GUARD)
} else {
// Verify input and calculate decoded length.
let firstChar = contents.chars().nth(0).unwrap().to_ascii_uppercase();
let lastChar = contents
.chars()
.nth(contents.chars().count() - 1)
.unwrap()
.to_ascii_uppercase();
let startsNormal = CodaBarReader::arrayContains(&START_END_CHARS, firstChar);
let endsNormal = CodaBarReader::arrayContains(&START_END_CHARS, lastChar);
let startsAlt = CodaBarReader::arrayContains(&ALT_START_END_CHARS, firstChar);
let endsAlt = CodaBarReader::arrayContains(&ALT_START_END_CHARS, lastChar);
if startsNormal {
if !endsNormal {
return Err(Exceptions::IllegalArgumentException(format!(
"Invalid start/end guards: {}",
contents
)));
}
// else already has valid start/end
contents.to_owned()
} else if startsAlt {
if !endsAlt {
return Err(Exceptions::IllegalArgumentException(format!(
"Invalid start/end guards: {}",
contents
)));
}
// else already has valid start/end
contents.to_owned()
} else {
// Doesn't start with a guard
if endsNormal || endsAlt {
return Err(Exceptions::IllegalArgumentException(format!(
"Invalid start/end guards: {}",
contents
)));
}
// else doesn't end with guard either, so add a default
format!("{}{}{}", DEFAULT_GUARD, contents, DEFAULT_GUARD)
}
};
// The start character and the end character are decoded to 10 length each.
let mut resultLength = 20;
//for i in 1..contents.chars().count() {
for ch in contents[1..contents.chars().count() - 1].chars() {
// for (int i = 1; i < contents.length() - 1; i++) {
if ch.is_digit(10) || ch == '-' || ch == '$' {
resultLength += 9;
} else if CodaBarReader::arrayContains(
&CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED,
ch,
) {
resultLength += 10;
} else {
return Err(Exceptions::IllegalArgumentException(format!(
"Cannot encode : '{}'",
ch
)));
}
}
// A blank is placed between each character.
resultLength += contents.chars().count() - 1;
let mut result = vec![false; resultLength];
let mut position = 0;
for index in 0..contents.chars().count() {
// for (int index = 0; index < contents.length(); index++) {
let mut c = contents.chars().nth(index).unwrap().to_ascii_uppercase();
if index == 0 || index == contents.chars().count() - 1 {
// The start/end chars are not in the CodaBarReader.ALPHABET.
c = match c {
'T' => 'A',
'N' => 'B',
'*' => 'C',
'E' => 'D',
_ => c,
}
}
let mut code = 0;
for i in 0..CodaBarReader::ALPHABET.len() {
// for (int i = 0; i < CodaBarReader::ALPHABET.length; i++) {
// Found any, because I checked above.
if c == CodaBarReader::ALPHABET[i] {
code = CodaBarReader::CHARACTER_ENCODINGS[i];
break;
}
}
let mut color = true;
let mut counter = 0;
let mut bit = 0;
while bit < 7 {
// A character consists of 7 digit.
result[position] = color;
position += 1;
if ((code >> (6 - bit)) & 1) == 0 || counter == 1 {
color = !color; // Flip the color.
bit += 1;
counter = 0;
} else {
counter += 1;
}
}
if index < contents.chars().count() - 1 {
result[position] = false;
position += 1;
}
}
Ok(result)
}
fn getSupportedWriteFormats(&self) -> Option<Vec<crate::BarcodeFormat>> {
Some(vec![BarcodeFormat::CODABAR])
}
}
impl Default for CodaBarWriter {
fn default() -> Self {
Self {}
}
}
/**
* @author dsbnatut@gmail.com (Kazuki Nishiura)
* @author Sean Owen
*/
#[cfg(test)]
mod CodaBarWriterTestCase {
use crate::{
common::{BitMatrix, BitMatrixTestCase},
oned::OneDimensionalCodeWriter,
BarcodeFormat, Writer,
};
use super::CodaBarWriter;
#[test]
fn testEncode() {
doTest(
"B515-3/B",
&format!(
"{}{}{}{}{}{}{}{}{}{}",
"00000",
"1001001011",
"0110101001",
"0101011001",
"0110101001",
"0101001101",
"0110010101",
"01101101011",
"01001001011",
"00000"
),
);
}
#[test]
fn testEncode2() {
doTest(
"T123T",
&format!(
"{}{}{}{}{}{}{}",
"00000",
"1011001001",
"0101011001",
"0101001011",
"0110010101",
"01011001001",
"00000"
),
);
}
#[test]
fn testAltStartEnd() {
assert_eq!(encode("T123456789-$T"), encode("A123456789-$A"));
}
fn doTest(input: &str, expected: &str) {
let result = encode(input);
assert_eq!(expected, BitMatrixTestCase::matrix_to_string(&result));
}
fn encode(input: &str) -> BitMatrix {
CodaBarWriter::default()
.encode(input, &BarcodeFormat::CODABAR, 0, 0)
.expect("must encode")
}
}

View File

@@ -46,3 +46,9 @@ pub use upc_a_reader::*;
mod upc_e_reader;
pub use upc_e_reader::*;
mod one_d_code_writer;
pub use one_d_code_writer::*;
mod coda_bar_writer;
pub use coda_bar_writer::*;

View File

@@ -0,0 +1,203 @@
/*
* Copyright 2011 ZXing authors
*
* 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.
*/
use std::collections::HashMap;
use crate::{
common::BitMatrix, BarcodeFormat, EncodeHintType, EncodeHintValue, Exceptions, Writer,
};
use lazy_static::lazy_static;
use regex::Regex;
lazy_static! {
pub static ref NUMERIC: Regex = Regex::new("[0-9]+").unwrap();
}
/**
* <p>Encapsulates functionality and implementation that is common to one-dimensional barcodes.</p>
*
* @author dsbnatut@gmail.com (Kazuki Nishiura)
*/
pub trait OneDimensionalCodeWriter: Writer {
// private static final Pattern NUMERIC = Pattern.compile("[0-9]+");
/**
* Encode the contents to boolean array expression of one-dimensional barcode.
* Start code and end code should be included in result, and side margins should not be included.
*
* @param contents barcode contents to encode
* @return a {@code boolean[]} of horizontal pixels (false = white, true = black)
*/
fn encode_oned(&self, contents: &str) -> Result<Vec<bool>, Exceptions>;
/**
* Can be overwritten if the encode requires to read the hints map. Otherwise it defaults to {@code encode}.
* @param contents barcode contents to encode
* @param hints encoding hints
* @return a {@code boolean[]} of horizontal pixels (false = white, true = black)
*/
fn encode_oned_with_hints(
&self,
contents: &str,
_hints: &crate::EncodingHintDictionary,
) -> Result<Vec<bool>, Exceptions> {
self.encode_oned(contents)
}
fn getSupportedWriteFormats(&self) -> Option<Vec<BarcodeFormat>> {
None
}
/**
* @return a byte array of horizontal pixels (0 = white, 1 = black)
*/
fn renderRXingResult(
code: &[bool],
width: i32,
height: i32,
sidesMargin: u32,
) -> Result<BitMatrix, Exceptions> {
let inputWidth = code.len();
// Add quiet zone on both sides.
let fullWidth = inputWidth + sidesMargin as usize;
let outputWidth = width.max(fullWidth as i32);
let outputHeight = 1.max(height);
let multiple = outputWidth as usize / fullWidth;
let leftPadding = (outputWidth as isize - (inputWidth as isize * multiple as isize)) / 2;
let mut output = BitMatrix::new(outputWidth as u32, outputHeight as u32)?;
let mut inputX = 0;
let mut outputX = leftPadding;
while inputX < inputWidth {
// for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
if code[inputX] {
output.setRegion(outputX as u32, 0, multiple as u32, outputHeight as u32)?;
}
inputX += 1;
outputX += multiple as isize;
}
Ok(output)
}
/**
* @param contents string to check for numeric characters
* @throws IllegalArgumentException if input contains characters other than digits 0-9.
*/
fn checkNumeric(contents: &str) -> Result<(), Exceptions> {
if !NUMERIC.is_match(contents) {
Err(Exceptions::IllegalArgumentException(
"Input should only contain digits 0-9".to_owned(),
))
} else {
Ok(())
}
}
/**
* @param target encode black/white pattern into this array
* @param pos position to start encoding at in {@code target}
* @param pattern lengths of black/white runs to encode
* @param startColor starting color - false for white, true for black
* @return the number of elements added to target.
*/
fn appendPattern(target: &mut [bool], pos: usize, pattern: &[usize], startColor: bool) -> u32 {
let mut color = startColor;
let mut numAdded = 0;
let mut pos = pos;
for len in pattern {
// for (int len : pattern) {
for _j in 0..*len {
// for (int j = 0; j < len; j++) {
target[pos] = color;
pos += 1;
}
numAdded += len;
color = !color; // flip color after each segment
}
numAdded as u32
}
fn getDefaultMargin(&self) -> u32 {
// CodaBar spec requires a side margin to be more than ten times wider than narrow space.
// This seems like a decent idea for a default for all formats.
10
}
}
struct L;
impl Writer for L {
fn encode(
&self,
contents: &str,
format: &crate::BarcodeFormat,
width: i32,
height: i32,
) -> Result<crate::common::BitMatrix, crate::Exceptions> {
self.encode_with_hints(contents, format, width, height, &HashMap::new())
}
fn encode_with_hints(
&self,
contents: &str,
format: &crate::BarcodeFormat,
width: i32,
height: i32,
hints: &crate::EncodingHintDictionary,
) -> Result<crate::common::BitMatrix, crate::Exceptions> {
if contents.is_empty() {
return Err(Exceptions::IllegalArgumentException(
"Found empty contents".to_owned(),
));
}
if width < 0 || height < 0 {
return Err(Exceptions::IllegalArgumentException(format!(
"Negative size is not allowed. Input: {}x{}",
width, height
)));
}
if let Some(supportedFormats) = self.getSupportedWriteFormats() {
if !supportedFormats.contains(format) {
return Err(Exceptions::IllegalArgumentException(format!(
"Can only encode {:?}, but got {:?}",
supportedFormats, format
)));
}
}
let mut sidesMargin = self.getDefaultMargin();
if let Some(EncodeHintValue::Margin(margin)) = hints.get(&EncodeHintType::MARGIN) {
sidesMargin = margin.parse::<u32>().unwrap();
}
// if hints.contains_key(&EncodeHintType::MARGIN) {
// sidesMargin = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString());
// }
let code = self.encode_oned_with_hints(contents, hints)?;
Self::renderRXingResult(&code, width, height, sidesMargin)
}
}
impl OneDimensionalCodeWriter for L {
fn encode_oned(&self, contents: &str) -> Result<Vec<bool>, Exceptions> {
todo!()
}
}