1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 // Original code is licensed as follows:
7 /*
8 * Copyright 2010 ZXing authors
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 */
22
23 #include "xfa/fxbarcode/BC_Writer.h"
24 #include "xfa/fxbarcode/oned/BC_OneDimWriter.h"
25 #include "xfa/fxbarcode/oned/BC_OnedCode128Writer.h"
26
27 namespace {
28
29 const int32_t CODE_PATTERNS[107][7] = {
30 {2, 1, 2, 2, 2, 2, 0}, {2, 2, 2, 1, 2, 2, 0}, {2, 2, 2, 2, 2, 1, 0},
31 {1, 2, 1, 2, 2, 3, 0}, {1, 2, 1, 3, 2, 2, 0}, {1, 3, 1, 2, 2, 2, 0},
32 {1, 2, 2, 2, 1, 3, 0}, {1, 2, 2, 3, 1, 2, 0}, {1, 3, 2, 2, 1, 2, 0},
33 {2, 2, 1, 2, 1, 3, 0}, {2, 2, 1, 3, 1, 2, 0}, {2, 3, 1, 2, 1, 2, 0},
34 {1, 1, 2, 2, 3, 2, 0}, {1, 2, 2, 1, 3, 2, 0}, {1, 2, 2, 2, 3, 1, 0},
35 {1, 1, 3, 2, 2, 2, 0}, {1, 2, 3, 1, 2, 2, 0}, {1, 2, 3, 2, 2, 1, 0},
36 {2, 2, 3, 2, 1, 1, 0}, {2, 2, 1, 1, 3, 2, 0}, {2, 2, 1, 2, 3, 1, 0},
37 {2, 1, 3, 2, 1, 2, 0}, {2, 2, 3, 1, 1, 2, 0}, {3, 1, 2, 1, 3, 1, 0},
38 {3, 1, 1, 2, 2, 2, 0}, {3, 2, 1, 1, 2, 2, 0}, {3, 2, 1, 2, 2, 1, 0},
39 {3, 1, 2, 2, 1, 2, 0}, {3, 2, 2, 1, 1, 2, 0}, {3, 2, 2, 2, 1, 1, 0},
40 {2, 1, 2, 1, 2, 3, 0}, {2, 1, 2, 3, 2, 1, 0}, {2, 3, 2, 1, 2, 1, 0},
41 {1, 1, 1, 3, 2, 3, 0}, {1, 3, 1, 1, 2, 3, 0}, {1, 3, 1, 3, 2, 1, 0},
42 {1, 1, 2, 3, 1, 3, 0}, {1, 3, 2, 1, 1, 3, 0}, {1, 3, 2, 3, 1, 1, 0},
43 {2, 1, 1, 3, 1, 3, 0}, {2, 3, 1, 1, 1, 3, 0}, {2, 3, 1, 3, 1, 1, 0},
44 {1, 1, 2, 1, 3, 3, 0}, {1, 1, 2, 3, 3, 1, 0}, {1, 3, 2, 1, 3, 1, 0},
45 {1, 1, 3, 1, 2, 3, 0}, {1, 1, 3, 3, 2, 1, 0}, {1, 3, 3, 1, 2, 1, 0},
46 {3, 1, 3, 1, 2, 1, 0}, {2, 1, 1, 3, 3, 1, 0}, {2, 3, 1, 1, 3, 1, 0},
47 {2, 1, 3, 1, 1, 3, 0}, {2, 1, 3, 3, 1, 1, 0}, {2, 1, 3, 1, 3, 1, 0},
48 {3, 1, 1, 1, 2, 3, 0}, {3, 1, 1, 3, 2, 1, 0}, {3, 3, 1, 1, 2, 1, 0},
49 {3, 1, 2, 1, 1, 3, 0}, {3, 1, 2, 3, 1, 1, 0}, {3, 3, 2, 1, 1, 1, 0},
50 {3, 1, 4, 1, 1, 1, 0}, {2, 2, 1, 4, 1, 1, 0}, {4, 3, 1, 1, 1, 1, 0},
51 {1, 1, 1, 2, 2, 4, 0}, {1, 1, 1, 4, 2, 2, 0}, {1, 2, 1, 1, 2, 4, 0},
52 {1, 2, 1, 4, 2, 1, 0}, {1, 4, 1, 1, 2, 2, 0}, {1, 4, 1, 2, 2, 1, 0},
53 {1, 1, 2, 2, 1, 4, 0}, {1, 1, 2, 4, 1, 2, 0}, {1, 2, 2, 1, 1, 4, 0},
54 {1, 2, 2, 4, 1, 1, 0}, {1, 4, 2, 1, 1, 2, 0}, {1, 4, 2, 2, 1, 1, 0},
55 {2, 4, 1, 2, 1, 1, 0}, {2, 2, 1, 1, 1, 4, 0}, {4, 1, 3, 1, 1, 1, 0},
56 {2, 4, 1, 1, 1, 2, 0}, {1, 3, 4, 1, 1, 1, 0}, {1, 1, 1, 2, 4, 2, 0},
57 {1, 2, 1, 1, 4, 2, 0}, {1, 2, 1, 2, 4, 1, 0}, {1, 1, 4, 2, 1, 2, 0},
58 {1, 2, 4, 1, 1, 2, 0}, {1, 2, 4, 2, 1, 1, 0}, {4, 1, 1, 2, 1, 2, 0},
59 {4, 2, 1, 1, 1, 2, 0}, {4, 2, 1, 2, 1, 1, 0}, {2, 1, 2, 1, 4, 1, 0},
60 {2, 1, 4, 1, 2, 1, 0}, {4, 1, 2, 1, 2, 1, 0}, {1, 1, 1, 1, 4, 3, 0},
61 {1, 1, 1, 3, 4, 1, 0}, {1, 3, 1, 1, 4, 1, 0}, {1, 1, 4, 1, 1, 3, 0},
62 {1, 1, 4, 3, 1, 1, 0}, {4, 1, 1, 1, 1, 3, 0}, {4, 1, 1, 3, 1, 1, 0},
63 {1, 1, 3, 1, 4, 1, 0}, {1, 1, 4, 1, 3, 1, 0}, {3, 1, 1, 1, 4, 1, 0},
64 {4, 1, 1, 1, 3, 1, 0}, {2, 1, 1, 4, 1, 2, 0}, {2, 1, 1, 2, 1, 4, 0},
65 {2, 1, 1, 2, 3, 2, 0}, {2, 3, 3, 1, 1, 1, 2}};
66
67 const int32_t CODE_START_B = 104;
68 const int32_t CODE_START_C = 105;
69 const int32_t CODE_STOP = 106;
70
71 } // namespace
72
CBC_OnedCode128Writer()73 CBC_OnedCode128Writer::CBC_OnedCode128Writer() {
74 m_codeFormat = BC_CODE128_B;
75 }
CBC_OnedCode128Writer(BC_TYPE type)76 CBC_OnedCode128Writer::CBC_OnedCode128Writer(BC_TYPE type) {
77 m_codeFormat = type;
78 }
~CBC_OnedCode128Writer()79 CBC_OnedCode128Writer::~CBC_OnedCode128Writer() {}
GetType()80 BC_TYPE CBC_OnedCode128Writer::GetType() {
81 return m_codeFormat;
82 }
CheckContentValidity(const CFX_WideStringC & contents)83 bool CBC_OnedCode128Writer::CheckContentValidity(
84 const CFX_WideStringC& contents) {
85 bool ret = true;
86 int32_t position = 0;
87 int32_t patternIndex = -1;
88 if (m_codeFormat == BC_CODE128_B || m_codeFormat == BC_CODE128_C) {
89 while (position < contents.GetLength()) {
90 patternIndex = (int32_t)contents.GetAt(position);
91 if (patternIndex < 32 || patternIndex > 126 || patternIndex == 34) {
92 ret = false;
93 break;
94 }
95 position++;
96 }
97 } else {
98 ret = false;
99 }
100 return ret;
101 }
FilterContents(const CFX_WideStringC & contents)102 CFX_WideString CBC_OnedCode128Writer::FilterContents(
103 const CFX_WideStringC& contents) {
104 CFX_WideString filterChineseChar;
105 FX_WCHAR ch;
106 for (int32_t i = 0; i < contents.GetLength(); i++) {
107 ch = contents.GetAt(i);
108 if (ch > 175) {
109 i++;
110 continue;
111 }
112 filterChineseChar += ch;
113 }
114 CFX_WideString filtercontents;
115 if (m_codeFormat == BC_CODE128_B) {
116 for (int32_t i = 0; i < filterChineseChar.GetLength(); i++) {
117 ch = filterChineseChar.GetAt(i);
118 if (ch >= 32 && ch <= 126) {
119 filtercontents += ch;
120 } else {
121 continue;
122 }
123 }
124 } else if (m_codeFormat == BC_CODE128_C) {
125 for (int32_t i = 0; i < filterChineseChar.GetLength(); i++) {
126 ch = filterChineseChar.GetAt(i);
127 if (ch >= 32 && ch <= 106) {
128 filtercontents += ch;
129 } else {
130 continue;
131 }
132 }
133 } else {
134 filtercontents = contents;
135 }
136 return filtercontents;
137 }
SetTextLocation(BC_TEXT_LOC location)138 bool CBC_OnedCode128Writer::SetTextLocation(BC_TEXT_LOC location) {
139 if (location < BC_TEXT_LOC_NONE || location > BC_TEXT_LOC_BELOWEMBED) {
140 return false;
141 }
142 m_locTextLoc = location;
143 return true;
144 }
Encode(const CFX_ByteString & contents,BCFORMAT format,int32_t & outWidth,int32_t & outHeight,int32_t hints,int32_t & e)145 uint8_t* CBC_OnedCode128Writer::Encode(const CFX_ByteString& contents,
146 BCFORMAT format,
147 int32_t& outWidth,
148 int32_t& outHeight,
149 int32_t hints,
150 int32_t& e) {
151 if (format != BCFORMAT_CODE_128) {
152 e = BCExceptionOnlyEncodeCODE_128;
153 return nullptr;
154 }
155 uint8_t* ret =
156 CBC_OneDimWriter::Encode(contents, format, outWidth, outHeight, hints, e);
157 if (e != BCExceptionNO)
158 return nullptr;
159 return ret;
160 }
Encode(const CFX_ByteString & contents,BCFORMAT format,int32_t & outWidth,int32_t & outHeight,int32_t & e)161 uint8_t* CBC_OnedCode128Writer::Encode(const CFX_ByteString& contents,
162 BCFORMAT format,
163 int32_t& outWidth,
164 int32_t& outHeight,
165 int32_t& e) {
166 uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e);
167 if (e != BCExceptionNO)
168 return nullptr;
169 return ret;
170 }
IsDigits(const CFX_ByteString & contents,int32_t start,int32_t length)171 bool CBC_OnedCode128Writer::IsDigits(const CFX_ByteString& contents,
172 int32_t start,
173 int32_t length) {
174 int32_t end = start + length;
175 for (int32_t i = start; i < end; i++) {
176 if (contents[i] < '0' || contents[i] > '9') {
177 return false;
178 }
179 }
180 return true;
181 }
182
Encode(const CFX_ByteString & contents,int32_t & outLength,int32_t & e)183 uint8_t* CBC_OnedCode128Writer::Encode(const CFX_ByteString& contents,
184 int32_t& outLength,
185 int32_t& e) {
186 if (contents.GetLength() < 1 || contents.GetLength() > 80) {
187 e = BCExceptionContentsLengthShouldBetween1and80;
188 return nullptr;
189 }
190 CFX_ArrayTemplate<const int32_t*> patterns;
191 int32_t checkSum = 0;
192 if (m_codeFormat == BC_CODE128_B) {
193 checkSum = Encode128B(contents, &patterns);
194 } else if (m_codeFormat == BC_CODE128_C) {
195 checkSum = Encode128C(contents, &patterns);
196 } else {
197 e = BCExceptionFormatException;
198 return nullptr;
199 }
200 checkSum %= 103;
201 patterns.Add(CODE_PATTERNS[checkSum]);
202 patterns.Add(CODE_PATTERNS[CODE_STOP]);
203 m_iContentLen = contents.GetLength() + 3;
204 int32_t codeWidth = 0;
205 for (int32_t k = 0; k < patterns.GetSize(); k++) {
206 const int32_t* pattern = patterns[k];
207 for (int32_t j = 0; j < 7; j++) {
208 codeWidth += pattern[j];
209 }
210 }
211 outLength = codeWidth;
212 uint8_t* result = FX_Alloc(uint8_t, outLength);
213 int32_t pos = 0;
214 for (int32_t j = 0; j < patterns.GetSize(); j++) {
215 const int32_t* pattern = patterns[j];
216 pos += AppendPattern(result, pos, pattern, 7, 1, e);
217 if (e != BCExceptionNO) {
218 FX_Free(result);
219 return nullptr;
220 }
221 }
222 return result;
223 }
224
Encode128B(const CFX_ByteString & contents,CFX_ArrayTemplate<const int32_t * > * patterns)225 int32_t CBC_OnedCode128Writer::Encode128B(
226 const CFX_ByteString& contents,
227 CFX_ArrayTemplate<const int32_t*>* patterns) {
228 int32_t checkSum = 0;
229 int32_t checkWeight = 1;
230 int32_t position = 0;
231 patterns->Add(CODE_PATTERNS[CODE_START_B]);
232 checkSum += CODE_START_B * checkWeight;
233 while (position < contents.GetLength()) {
234 int32_t patternIndex = 0;
235 patternIndex = contents[position] - ' ';
236 position += 1;
237 patterns->Add(CODE_PATTERNS[patternIndex]);
238 checkSum += patternIndex * checkWeight;
239 if (position != 0) {
240 checkWeight++;
241 }
242 }
243 return checkSum;
244 }
245
Encode128C(const CFX_ByteString & contents,CFX_ArrayTemplate<const int32_t * > * patterns)246 int32_t CBC_OnedCode128Writer::Encode128C(
247 const CFX_ByteString& contents,
248 CFX_ArrayTemplate<const int32_t*>* patterns) {
249 int32_t checkSum = 0;
250 int32_t checkWeight = 1;
251 int32_t position = 0;
252 patterns->Add(CODE_PATTERNS[CODE_START_C]);
253 checkSum += CODE_START_C * checkWeight;
254 while (position < contents.GetLength()) {
255 int32_t patternIndex = 0;
256 FX_CHAR ch = contents.GetAt(position);
257 if (ch < '0' || ch > '9') {
258 patternIndex = (int32_t)ch;
259 position++;
260 } else {
261 patternIndex = FXSYS_atoi(contents.Mid(position, 2).c_str());
262 if (contents.GetAt(position + 1) < '0' ||
263 contents.GetAt(position + 1) > '9') {
264 position += 1;
265 } else {
266 position += 2;
267 }
268 }
269 patterns->Add(CODE_PATTERNS[patternIndex]);
270 checkSum += patternIndex * checkWeight;
271 if (position != 0) {
272 checkWeight++;
273 }
274 }
275 return checkSum;
276 }
277