• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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