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 "fxbarcode/oned/BC_OnedCode128Writer.h" 24 25 #include <cctype> 26 #include <memory> 27 28 #include "fxbarcode/BC_Writer.h" 29 #include "fxbarcode/oned/BC_OneDimWriter.h" 30 31 namespace { 32 33 constexpr size_t kPatternSize = 7; 34 35 const int8_t CODE_PATTERNS[107][kPatternSize] = { 36 {2, 1, 2, 2, 2, 2, 0}, {2, 2, 2, 1, 2, 2, 0}, {2, 2, 2, 2, 2, 1, 0}, 37 {1, 2, 1, 2, 2, 3, 0}, {1, 2, 1, 3, 2, 2, 0}, {1, 3, 1, 2, 2, 2, 0}, 38 {1, 2, 2, 2, 1, 3, 0}, {1, 2, 2, 3, 1, 2, 0}, {1, 3, 2, 2, 1, 2, 0}, 39 {2, 2, 1, 2, 1, 3, 0}, {2, 2, 1, 3, 1, 2, 0}, {2, 3, 1, 2, 1, 2, 0}, 40 {1, 1, 2, 2, 3, 2, 0}, {1, 2, 2, 1, 3, 2, 0}, {1, 2, 2, 2, 3, 1, 0}, 41 {1, 1, 3, 2, 2, 2, 0}, {1, 2, 3, 1, 2, 2, 0}, {1, 2, 3, 2, 2, 1, 0}, 42 {2, 2, 3, 2, 1, 1, 0}, {2, 2, 1, 1, 3, 2, 0}, {2, 2, 1, 2, 3, 1, 0}, 43 {2, 1, 3, 2, 1, 2, 0}, {2, 2, 3, 1, 1, 2, 0}, {3, 1, 2, 1, 3, 1, 0}, 44 {3, 1, 1, 2, 2, 2, 0}, {3, 2, 1, 1, 2, 2, 0}, {3, 2, 1, 2, 2, 1, 0}, 45 {3, 1, 2, 2, 1, 2, 0}, {3, 2, 2, 1, 1, 2, 0}, {3, 2, 2, 2, 1, 1, 0}, 46 {2, 1, 2, 1, 2, 3, 0}, {2, 1, 2, 3, 2, 1, 0}, {2, 3, 2, 1, 2, 1, 0}, 47 {1, 1, 1, 3, 2, 3, 0}, {1, 3, 1, 1, 2, 3, 0}, {1, 3, 1, 3, 2, 1, 0}, 48 {1, 1, 2, 3, 1, 3, 0}, {1, 3, 2, 1, 1, 3, 0}, {1, 3, 2, 3, 1, 1, 0}, 49 {2, 1, 1, 3, 1, 3, 0}, {2, 3, 1, 1, 1, 3, 0}, {2, 3, 1, 3, 1, 1, 0}, 50 {1, 1, 2, 1, 3, 3, 0}, {1, 1, 2, 3, 3, 1, 0}, {1, 3, 2, 1, 3, 1, 0}, 51 {1, 1, 3, 1, 2, 3, 0}, {1, 1, 3, 3, 2, 1, 0}, {1, 3, 3, 1, 2, 1, 0}, 52 {3, 1, 3, 1, 2, 1, 0}, {2, 1, 1, 3, 3, 1, 0}, {2, 3, 1, 1, 3, 1, 0}, 53 {2, 1, 3, 1, 1, 3, 0}, {2, 1, 3, 3, 1, 1, 0}, {2, 1, 3, 1, 3, 1, 0}, 54 {3, 1, 1, 1, 2, 3, 0}, {3, 1, 1, 3, 2, 1, 0}, {3, 3, 1, 1, 2, 1, 0}, 55 {3, 1, 2, 1, 1, 3, 0}, {3, 1, 2, 3, 1, 1, 0}, {3, 3, 2, 1, 1, 1, 0}, 56 {3, 1, 4, 1, 1, 1, 0}, {2, 2, 1, 4, 1, 1, 0}, {4, 3, 1, 1, 1, 1, 0}, 57 {1, 1, 1, 2, 2, 4, 0}, {1, 1, 1, 4, 2, 2, 0}, {1, 2, 1, 1, 2, 4, 0}, 58 {1, 2, 1, 4, 2, 1, 0}, {1, 4, 1, 1, 2, 2, 0}, {1, 4, 1, 2, 2, 1, 0}, 59 {1, 1, 2, 2, 1, 4, 0}, {1, 1, 2, 4, 1, 2, 0}, {1, 2, 2, 1, 1, 4, 0}, 60 {1, 2, 2, 4, 1, 1, 0}, {1, 4, 2, 1, 1, 2, 0}, {1, 4, 2, 2, 1, 1, 0}, 61 {2, 4, 1, 2, 1, 1, 0}, {2, 2, 1, 1, 1, 4, 0}, {4, 1, 3, 1, 1, 1, 0}, 62 {2, 4, 1, 1, 1, 2, 0}, {1, 3, 4, 1, 1, 1, 0}, {1, 1, 1, 2, 4, 2, 0}, 63 {1, 2, 1, 1, 4, 2, 0}, {1, 2, 1, 2, 4, 1, 0}, {1, 1, 4, 2, 1, 2, 0}, 64 {1, 2, 4, 1, 1, 2, 0}, {1, 2, 4, 2, 1, 1, 0}, {4, 1, 1, 2, 1, 2, 0}, 65 {4, 2, 1, 1, 1, 2, 0}, {4, 2, 1, 2, 1, 1, 0}, {2, 1, 2, 1, 4, 1, 0}, 66 {2, 1, 4, 1, 2, 1, 0}, {4, 1, 2, 1, 2, 1, 0}, {1, 1, 1, 1, 4, 3, 0}, 67 {1, 1, 1, 3, 4, 1, 0}, {1, 3, 1, 1, 4, 1, 0}, {1, 1, 4, 1, 1, 3, 0}, 68 {1, 1, 4, 3, 1, 1, 0}, {4, 1, 1, 1, 1, 3, 0}, {4, 1, 1, 3, 1, 1, 0}, 69 {1, 1, 3, 1, 4, 1, 0}, {1, 1, 4, 1, 3, 1, 0}, {3, 1, 1, 1, 4, 1, 0}, 70 {4, 1, 1, 1, 3, 1, 0}, {2, 1, 1, 4, 1, 2, 0}, {2, 1, 1, 2, 1, 4, 0}, 71 {2, 1, 1, 2, 3, 2, 0}, {2, 3, 3, 1, 1, 1, 2}}; 72 73 const int32_t CODE_START_B = 104; 74 const int32_t CODE_START_C = 105; 75 const int32_t CODE_STOP = 106; 76 77 } // namespace 78 79 CBC_OnedCode128Writer::CBC_OnedCode128Writer(BC_TYPE type) 80 : m_codeFormat(type) { 81 assert(m_codeFormat == BC_CODE128_B || m_codeFormat == BC_CODE128_C); 82 } 83 84 CBC_OnedCode128Writer::~CBC_OnedCode128Writer() {} 85 86 bool CBC_OnedCode128Writer::CheckContentValidity( 87 const WideStringView& contents) { 88 for (const auto& ch : contents) { 89 int32_t patternIndex = static_cast<int32_t>(ch); 90 if (patternIndex < 32 || patternIndex > 126 || patternIndex == 34) 91 return false; 92 } 93 return true; 94 } 95 96 WideString CBC_OnedCode128Writer::FilterContents( 97 const WideStringView& contents) { 98 WideString filterChineseChar; 99 for (size_t i = 0; i < contents.GetLength(); i++) { 100 wchar_t ch = contents[i]; 101 if (ch > 175) { 102 i++; 103 continue; 104 } 105 filterChineseChar += ch; 106 } 107 const wchar_t limit = m_codeFormat == BC_CODE128_B ? 126 : 106; 108 WideString filtercontents; 109 for (const auto& ch : filterChineseChar) { 110 if (ch >= 32 && ch <= limit) 111 filtercontents += ch; 112 } 113 return filtercontents; 114 } 115 116 bool CBC_OnedCode128Writer::SetTextLocation(BC_TEXT_LOC location) { 117 if (location < BC_TEXT_LOC_NONE || location > BC_TEXT_LOC_BELOWEMBED) { 118 return false; 119 } 120 m_locTextLoc = location; 121 return true; 122 } 123 124 uint8_t* CBC_OnedCode128Writer::EncodeWithHint(const ByteString& contents, 125 BCFORMAT format, 126 int32_t& outWidth, 127 int32_t& outHeight, 128 int32_t hints) { 129 if (format != BCFORMAT_CODE_128) 130 return nullptr; 131 return CBC_OneDimWriter::EncodeWithHint(contents, format, outWidth, outHeight, 132 hints); 133 } 134 135 uint8_t* CBC_OnedCode128Writer::EncodeImpl(const ByteString& contents, 136 int32_t& outLength) { 137 if (contents.GetLength() < 1 || contents.GetLength() > 80) 138 return nullptr; 139 140 std::vector<int32_t> patterns; 141 int32_t checkSum = 0; 142 if (m_codeFormat == BC_CODE128_B) 143 checkSum = Encode128B(contents, &patterns); 144 else 145 checkSum = Encode128C(contents, &patterns); 146 147 checkSum %= 103; 148 patterns.push_back(checkSum); 149 patterns.push_back(CODE_STOP); 150 m_iContentLen = contents.GetLength() + 3; 151 int32_t codeWidth = 0; 152 for (const auto& patternIndex : patterns) { 153 const int8_t* pattern = CODE_PATTERNS[patternIndex]; 154 for (size_t i = 0; i < kPatternSize; ++i) 155 codeWidth += pattern[i]; 156 } 157 outLength = codeWidth; 158 std::unique_ptr<uint8_t, FxFreeDeleter> result(FX_Alloc(uint8_t, outLength)); 159 int32_t pos = 0; 160 for (size_t i = 0; i < patterns.size(); ++i) { 161 const int8_t* pattern = CODE_PATTERNS[patterns[i]]; 162 int32_t e = BCExceptionNO; 163 pos += AppendPattern(result.get(), pos, pattern, kPatternSize, 1, e); 164 if (e != BCExceptionNO) 165 return nullptr; 166 } 167 return result.release(); 168 } 169 170 // static 171 int32_t CBC_OnedCode128Writer::Encode128B(const ByteString& contents, 172 std::vector<int32_t>* patterns) { 173 int32_t checkWeight = 1; 174 patterns->push_back(CODE_START_B); 175 int32_t checkSum = CODE_START_B * checkWeight; 176 for (size_t position = 0; position < contents.GetLength(); position++) { 177 int32_t patternIndex = contents[position] - ' '; 178 patterns->push_back(patternIndex); 179 checkSum += patternIndex * checkWeight++; 180 } 181 return checkSum; 182 } 183 184 // static 185 int32_t CBC_OnedCode128Writer::Encode128C(const ByteString& contents, 186 std::vector<int32_t>* patterns) { 187 int32_t checkWeight = 1; 188 patterns->push_back(CODE_START_C); 189 int32_t checkSum = CODE_START_C * checkWeight; 190 size_t position = 0; 191 while (position < contents.GetLength()) { 192 int32_t patternIndex; 193 char ch = contents[position]; 194 if (std::isdigit(ch)) { 195 patternIndex = FXSYS_atoi( 196 contents.Mid(position, contents.IsValidIndex(position + 1) ? 2 : 1) 197 .c_str()); 198 ++position; 199 if (position < contents.GetLength() && std::isdigit(contents[position])) 200 ++position; 201 } else { 202 patternIndex = static_cast<int32_t>(ch); 203 ++position; 204 } 205 patterns->push_back(patternIndex); 206 checkSum += patternIndex * checkWeight++; 207 } 208 return checkSum; 209 } 210