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 2009 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_OnedEAN13Writer.h"
24
25 #include <algorithm>
26 #include <cwctype>
27 #include <memory>
28 #include <vector>
29
30 #include "core/fxcrt/fx_extension.h"
31 #include "core/fxcrt/fx_memory_wrappers.h"
32 #include "core/fxge/cfx_defaultrenderdevice.h"
33 #include "core/fxge/text_char_pos.h"
34 #include "fxbarcode/BC_Writer.h"
35 #include "fxbarcode/oned/BC_OneDimWriter.h"
36 #include "fxbarcode/oned/BC_OnedEANChecksum.h"
37
38 namespace {
39
40 const int8_t kFirstDigitEncodings[10] = {0x00, 0x0B, 0x0D, 0xE, 0x13,
41 0x19, 0x1C, 0x15, 0x16, 0x1A};
42 const int8_t kOnedEAN13StartPattern[3] = {1, 1, 1};
43 const int8_t kOnedEAN13MiddlePattern[5] = {1, 1, 1, 1, 1};
44 const int8_t kOnedEAN13LPattern[10][4] = {
45 {3, 2, 1, 1}, {2, 2, 2, 1}, {2, 1, 2, 2}, {1, 4, 1, 1}, {1, 1, 3, 2},
46 {1, 2, 3, 1}, {1, 1, 1, 4}, {1, 3, 1, 2}, {1, 2, 1, 3}, {3, 1, 1, 2}};
47 const int8_t L_AND_G_PATTERNS[20][4] = {
48 {3, 2, 1, 1}, {2, 2, 2, 1}, {2, 1, 2, 2}, {1, 4, 1, 1}, {1, 1, 3, 2},
49 {1, 2, 3, 1}, {1, 1, 1, 4}, {1, 3, 1, 2}, {1, 2, 1, 3}, {3, 1, 1, 2},
50 {1, 1, 2, 3}, {1, 2, 2, 2}, {2, 2, 1, 2}, {1, 1, 4, 1}, {2, 3, 1, 1},
51 {1, 3, 2, 1}, {4, 1, 1, 1}, {2, 1, 3, 1}, {3, 1, 2, 1}, {2, 1, 1, 3}};
52
53 } // namespace
54
CBC_OnedEAN13Writer()55 CBC_OnedEAN13Writer::CBC_OnedEAN13Writer() {
56 m_bLeftPadding = true;
57 m_codeWidth = 3 + (7 * 6) + 5 + (7 * 6) + 3;
58 }
~CBC_OnedEAN13Writer()59 CBC_OnedEAN13Writer::~CBC_OnedEAN13Writer() {}
60
CheckContentValidity(WideStringView contents)61 bool CBC_OnedEAN13Writer::CheckContentValidity(WideStringView contents) {
62 return std::all_of(contents.begin(), contents.end(),
63 [](wchar_t c) { return FXSYS_IsDecimalDigit(c); });
64 }
65
FilterContents(WideStringView contents)66 WideString CBC_OnedEAN13Writer::FilterContents(WideStringView contents) {
67 WideString filtercontents;
68 filtercontents.Reserve(contents.GetLength());
69 wchar_t ch;
70 for (size_t i = 0; i < contents.GetLength(); i++) {
71 ch = contents[i];
72 if (ch > 175) {
73 i++;
74 continue;
75 }
76 if (FXSYS_IsDecimalDigit(ch))
77 filtercontents += ch;
78 }
79 return filtercontents;
80 }
81
CalcChecksum(const ByteString & contents)82 int32_t CBC_OnedEAN13Writer::CalcChecksum(const ByteString& contents) {
83 return EANCalcChecksum(contents);
84 }
85
EncodeWithHint(const ByteString & contents,BCFORMAT format,int32_t & outWidth,int32_t & outHeight,int32_t hints)86 uint8_t* CBC_OnedEAN13Writer::EncodeWithHint(const ByteString& contents,
87 BCFORMAT format,
88 int32_t& outWidth,
89 int32_t& outHeight,
90 int32_t hints) {
91 if (format != BCFORMAT_EAN_13)
92 return nullptr;
93 return CBC_OneDimWriter::EncodeWithHint(contents, format, outWidth, outHeight,
94 hints);
95 }
96
EncodeImpl(const ByteString & contents,int32_t & outLength)97 uint8_t* CBC_OnedEAN13Writer::EncodeImpl(const ByteString& contents,
98 int32_t& outLength) {
99 if (contents.GetLength() != 13)
100 return nullptr;
101
102 m_iDataLenth = 13;
103 int32_t firstDigit = FXSYS_DecimalCharToInt(contents.Front());
104 int32_t parities = kFirstDigitEncodings[firstDigit];
105 outLength = m_codeWidth;
106 std::unique_ptr<uint8_t, FxFreeDeleter> result(
107 FX_Alloc(uint8_t, m_codeWidth));
108 int32_t pos = 0;
109 pos += AppendPattern(result.get(), pos, kOnedEAN13StartPattern, 3, true);
110
111 int32_t i = 0;
112 for (i = 1; i <= 6; i++) {
113 int32_t digit = FXSYS_DecimalCharToInt(contents[i]);
114 if ((parities >> (6 - i) & 1) == 1) {
115 digit += 10;
116 }
117 pos += AppendPattern(result.get(), pos, L_AND_G_PATTERNS[digit], 4, false);
118 }
119 pos += AppendPattern(result.get(), pos, kOnedEAN13MiddlePattern, 5, false);
120
121 for (i = 7; i <= 12; i++) {
122 int32_t digit = FXSYS_DecimalCharToInt(contents[i]);
123 pos += AppendPattern(result.get(), pos, kOnedEAN13LPattern[digit], 4, true);
124 }
125 pos += AppendPattern(result.get(), pos, kOnedEAN13StartPattern, 3, true);
126 return result.release();
127 }
128
ShowChars(WideStringView contents,CFX_RenderDevice * device,const CFX_Matrix * matrix,int32_t barWidth,int32_t multiple)129 bool CBC_OnedEAN13Writer::ShowChars(WideStringView contents,
130 CFX_RenderDevice* device,
131 const CFX_Matrix* matrix,
132 int32_t barWidth,
133 int32_t multiple) {
134 if (!device)
135 return false;
136
137 int32_t leftPadding = 7 * multiple;
138 int32_t leftPosition = 3 * multiple + leftPadding;
139 ByteString str = FX_UTF8Encode(contents);
140 size_t length = str.GetLength();
141 std::vector<TextCharPos> charpos(length);
142 int32_t iFontSize = (int32_t)fabs(m_fFontSize);
143 int32_t iTextHeight = iFontSize + 1;
144 ByteString tempStr = str.Substr(1, 6);
145 int32_t strWidth = multiple * 42;
146
147 CFX_Matrix matr(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0);
148 CFX_FloatRect rect((float)leftPosition, (float)(m_Height - iTextHeight),
149 (float)(leftPosition + strWidth - 0.5), (float)m_Height);
150 matr.Concat(*matrix);
151 FX_RECT re = matr.TransformRect(rect).GetOuterRect();
152 device->FillRect(re, kBackgroundColor);
153 CFX_FloatRect rect1(
154 (float)(leftPosition + 47 * multiple), (float)(m_Height - iTextHeight),
155 (float)(leftPosition + 47 * multiple + strWidth - 0.5), (float)m_Height);
156 CFX_Matrix matr1(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0);
157 matr1.Concat(*matrix);
158 re = matr1.TransformRect(rect1).GetOuterRect();
159 device->FillRect(re, kBackgroundColor);
160 int32_t strWidth1 = multiple * 7;
161 CFX_Matrix matr2(m_outputHScale, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
162 CFX_FloatRect rect2(0.0f, (float)(m_Height - iTextHeight),
163 (float)strWidth1 - 0.5f, (float)m_Height);
164 matr2.Concat(*matrix);
165 re = matr2.TransformRect(rect2).GetOuterRect();
166 device->FillRect(re, kBackgroundColor);
167
168 float blank = 0.0;
169 length = tempStr.GetLength();
170 strWidth = (int32_t)(strWidth * m_outputHScale);
171
172 CalcTextInfo(tempStr, &charpos[1], m_pFont.Get(), (float)strWidth, iFontSize,
173 blank);
174 {
175 CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0,
176 (float)leftPosition * m_outputHScale,
177 (float)(m_Height - iTextHeight) + iFontSize);
178 if (matrix)
179 affine_matrix1.Concat(*matrix);
180 device->DrawNormalText(length, &charpos[1], m_pFont.Get(),
181 static_cast<float>(iFontSize), affine_matrix1,
182 m_fontColor, FXTEXT_CLEARTYPE);
183 }
184 tempStr = str.Substr(7, 6);
185 length = tempStr.GetLength();
186 CalcTextInfo(tempStr, &charpos[7], m_pFont.Get(), (float)strWidth, iFontSize,
187 blank);
188 {
189 CFX_Matrix affine_matrix1(
190 1.0, 0.0, 0.0, -1.0,
191 (float)(leftPosition + 47 * multiple) * m_outputHScale,
192 (float)(m_Height - iTextHeight + iFontSize));
193 if (matrix)
194 affine_matrix1.Concat(*matrix);
195 device->DrawNormalText(length, &charpos[7], m_pFont.Get(),
196 static_cast<float>(iFontSize), affine_matrix1,
197 m_fontColor, FXTEXT_CLEARTYPE);
198 }
199 tempStr = str.First(1);
200 length = tempStr.GetLength();
201 strWidth = multiple * 7;
202 strWidth = (int32_t)(strWidth * m_outputHScale);
203
204 CalcTextInfo(tempStr, charpos.data(), m_pFont.Get(), (float)strWidth,
205 iFontSize, blank);
206 {
207 CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, 0.0,
208 (float)(m_Height - iTextHeight + iFontSize));
209 if (matrix)
210 affine_matrix1.Concat(*matrix);
211 device->DrawNormalText(length, charpos.data(), m_pFont.Get(),
212 static_cast<float>(iFontSize), affine_matrix1,
213 m_fontColor, FXTEXT_CLEARTYPE);
214 }
215 return true;
216 }
217