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/src/fxbarcode/barcode.h"
24#include "xfa/src/fxbarcode/BC_Writer.h"
25#include "BC_OneDimWriter.h"
26#include "BC_OnedEAN13Writer.h"
27#include "BC_OnedUPCAWriter.h"
28CBC_OnedUPCAWriter::CBC_OnedUPCAWriter() {
29  m_subWriter = NULL;
30  m_bLeftPadding = TRUE;
31  m_bRightPadding = TRUE;
32}
33void CBC_OnedUPCAWriter::Init() {
34  m_subWriter = new CBC_OnedEAN13Writer;
35}
36CBC_OnedUPCAWriter::~CBC_OnedUPCAWriter() {
37  if (m_subWriter != NULL) {
38    delete m_subWriter;
39  }
40  m_subWriter = NULL;
41}
42FX_BOOL CBC_OnedUPCAWriter::CheckContentValidity(
43    const CFX_WideStringC& contents) {
44  int32_t i = 0;
45  for (i = 0; i < contents.GetLength(); i++) {
46    if (contents.GetAt(i) >= '0' && contents.GetAt(i) <= '9') {
47      continue;
48    } else {
49      return FALSE;
50    }
51  }
52  return TRUE;
53}
54CFX_WideString CBC_OnedUPCAWriter::FilterContents(
55    const CFX_WideStringC& contents) {
56  CFX_WideString filtercontents;
57  FX_WCHAR ch;
58  for (int32_t i = 0; i < contents.GetLength(); i++) {
59    ch = contents.GetAt(i);
60    if (ch > 175) {
61      i++;
62      continue;
63    }
64    if (ch >= '0' && ch <= '9') {
65      filtercontents += ch;
66    }
67  }
68  return filtercontents;
69}
70int32_t CBC_OnedUPCAWriter::CalcChecksum(const CFX_ByteString& contents) {
71  int32_t odd = 0;
72  int32_t even = 0;
73  int32_t j = 1;
74  for (int32_t i = contents.GetLength() - 1; i >= 0; i--) {
75    if (j % 2) {
76      odd += FXSYS_atoi(contents.Mid(i, 1));
77    } else {
78      even += FXSYS_atoi(contents.Mid(i, 1));
79    }
80    j++;
81  }
82  int32_t checksum = (odd * 3 + even) % 10;
83  checksum = (10 - checksum) % 10;
84  return (checksum);
85}
86uint8_t* CBC_OnedUPCAWriter::Encode(const CFX_ByteString& contents,
87                                    BCFORMAT format,
88                                    int32_t& outWidth,
89                                    int32_t& outHeight,
90                                    int32_t& e) {
91  uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e);
92  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
93  return ret;
94}
95uint8_t* CBC_OnedUPCAWriter::Encode(const CFX_ByteString& contents,
96                                    BCFORMAT format,
97                                    int32_t& outWidth,
98                                    int32_t& outHeight,
99                                    int32_t hints,
100                                    int32_t& e) {
101  if (format != BCFORMAT_UPC_A) {
102    e = BCExceptionOnlyEncodeUPC_A;
103    return NULL;
104  }
105  CFX_ByteString toEAN13String = '0' + contents;
106  m_iDataLenth = 13;
107  uint8_t* ret = m_subWriter->Encode(toEAN13String, BCFORMAT_EAN_13, outWidth,
108                                     outHeight, hints, e);
109  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
110  return ret;
111}
112void CBC_OnedUPCAWriter::ShowChars(const CFX_WideStringC& contents,
113                                   CFX_DIBitmap* pOutBitmap,
114                                   CFX_RenderDevice* device,
115                                   const CFX_Matrix* matrix,
116                                   int32_t barWidth,
117                                   int32_t multiple,
118                                   int32_t& e) {
119  if (device == NULL && pOutBitmap == NULL) {
120    e = BCExceptionIllegalArgument;
121    return;
122  }
123  int32_t leftPadding = 7 * multiple;
124  int32_t leftPosition = 10 * multiple + leftPadding;
125  CFX_ByteString str = FX_UTF8Encode(contents);
126  int32_t iLen = str.GetLength();
127  FXTEXT_CHARPOS* pCharPos = FX_Alloc(FXTEXT_CHARPOS, iLen);
128  FXSYS_memset(pCharPos, 0, sizeof(FXTEXT_CHARPOS) * iLen);
129  CFX_ByteString tempStr = str.Mid(1, 5);
130  FX_FLOAT strWidth = (FX_FLOAT)35 * multiple;
131  FX_FLOAT blank = 0.0;
132  CFX_FxgeDevice geBitmap;
133  if (pOutBitmap != NULL) {
134    geBitmap.Attach(pOutBitmap);
135  }
136  FX_FLOAT charsWidth = 0;
137  iLen = tempStr.GetLength();
138  int32_t iFontSize = (int32_t)fabs(m_fFontSize);
139  int32_t iTextHeight = iFontSize + 1;
140  if (pOutBitmap == NULL) {
141    CFX_Matrix matr(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0);
142    CFX_FloatRect rect(
143        (FX_FLOAT)leftPosition, (FX_FLOAT)(m_Height - iTextHeight),
144        (FX_FLOAT)(leftPosition + strWidth - 0.5), (FX_FLOAT)m_Height);
145    matr.Concat(*matrix);
146    matr.TransformRect(rect);
147    FX_RECT re = rect.GetOutterRect();
148    device->FillRect(&re, m_backgroundColor);
149    CFX_Matrix matr1(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0);
150    CFX_FloatRect rect1(
151        (FX_FLOAT)(leftPosition + 40 * multiple),
152        (FX_FLOAT)(m_Height - iTextHeight),
153        (FX_FLOAT)((leftPosition + 40 * multiple) + strWidth - 0.5),
154        (FX_FLOAT)m_Height);
155    matr1.Concat(*matrix);
156    matr1.TransformRect(rect1);
157    re = rect1.GetOutterRect();
158    device->FillRect(&re, m_backgroundColor);
159    FX_FLOAT strWidth1 = (FX_FLOAT)multiple * 7;
160    CFX_Matrix matr2(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0);
161    CFX_FloatRect rect2(0.0, (FX_FLOAT)(m_Height - iTextHeight),
162                        (FX_FLOAT)strWidth1 - 1, (FX_FLOAT)m_Height);
163    matr2.Concat(*matrix);
164    matr2.TransformRect(rect2);
165    re = rect2.GetOutterRect();
166    device->FillRect(&re, m_backgroundColor);
167    CFX_Matrix matr3(m_outputHScale, 0.0, 0.0, 1.0, 0.0, 0.0);
168    CFX_FloatRect rect3(
169        (FX_FLOAT)(leftPosition + 85 * multiple),
170        (FX_FLOAT)(m_Height - iTextHeight),
171        (FX_FLOAT)((leftPosition + 85 * multiple) + strWidth1 - 0.5),
172        (FX_FLOAT)m_Height);
173    matr3.Concat(*matrix);
174    matr3.TransformRect(rect3);
175    re = rect3.GetOutterRect();
176    device->FillRect(&re, m_backgroundColor);
177  }
178  if (pOutBitmap == NULL) {
179    strWidth = strWidth * m_outputHScale;
180  }
181  CalcTextInfo(tempStr, pCharPos + 1, m_pFont, strWidth, iFontSize, blank);
182  CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, 0.0, (FX_FLOAT)iFontSize);
183  CFX_FxgeDevice ge;
184  if (pOutBitmap != NULL) {
185    ge.Create((int)strWidth, iTextHeight, FXDIB_Argb);
186    ge.GetBitmap()->Clear(m_backgroundColor);
187    ge.DrawNormalText(iLen, pCharPos + 1, m_pFont,
188                      CFX_GEModule::Get()->GetFontCache(), (FX_FLOAT)iFontSize,
189                      (CFX_Matrix*)&affine_matrix, m_fontColor,
190                      FXTEXT_CLEARTYPE);
191    geBitmap.SetDIBits(ge.GetBitmap(), leftPosition, m_Height - iTextHeight);
192  } else {
193    CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0,
194                              (FX_FLOAT)leftPosition * m_outputHScale,
195                              (FX_FLOAT)(m_Height - iTextHeight + iFontSize));
196    if (matrix != NULL) {
197      affine_matrix1.Concat(*matrix);
198    }
199    device->DrawNormalText(iLen, pCharPos + 1, m_pFont,
200                           CFX_GEModule::Get()->GetFontCache(),
201                           (FX_FLOAT)iFontSize, (CFX_Matrix*)&affine_matrix1,
202                           m_fontColor, FXTEXT_CLEARTYPE);
203  }
204  tempStr = str.Mid(6, 5);
205  iLen = tempStr.GetLength();
206  charsWidth = 0.0f;
207  CalcTextInfo(tempStr, pCharPos + 6, m_pFont, strWidth, iFontSize, blank);
208  if (pOutBitmap != NULL) {
209    FX_RECT rect2(0, 0, (int)strWidth, iTextHeight);
210    ge.FillRect(&rect2, m_backgroundColor);
211    ge.DrawNormalText(iLen, pCharPos + 6, m_pFont,
212                      CFX_GEModule::Get()->GetFontCache(), (FX_FLOAT)iFontSize,
213                      (CFX_Matrix*)&affine_matrix, m_fontColor,
214                      FXTEXT_CLEARTYPE);
215    geBitmap.SetDIBits(ge.GetBitmap(), leftPosition + 40 * multiple,
216                       m_Height - iTextHeight);
217  } else {
218    CFX_Matrix affine_matrix1(
219        1.0, 0.0, 0.0, -1.0,
220        (FX_FLOAT)(leftPosition + 40 * multiple) * m_outputHScale,
221        (FX_FLOAT)(m_Height - iTextHeight + iFontSize));
222    if (matrix != NULL) {
223      affine_matrix1.Concat(*matrix);
224    }
225    device->DrawNormalText(iLen, pCharPos + 6, m_pFont,
226                           CFX_GEModule::Get()->GetFontCache(),
227                           (FX_FLOAT)iFontSize, (CFX_Matrix*)&affine_matrix1,
228                           m_fontColor, FXTEXT_CLEARTYPE);
229  }
230  tempStr = str.Mid(0, 1);
231  iLen = tempStr.GetLength();
232  strWidth = (FX_FLOAT)multiple * 7;
233  if (pOutBitmap == NULL) {
234    strWidth = strWidth * m_outputHScale;
235  }
236  CalcTextInfo(tempStr, pCharPos, m_pFont, strWidth, iFontSize, blank);
237  if (pOutBitmap != NULL) {
238    delete ge.GetBitmap();
239    ge.Create((int)strWidth, iTextHeight, FXDIB_Argb);
240    ge.GetBitmap()->Clear(m_backgroundColor);
241    ge.DrawNormalText(iLen, pCharPos, m_pFont,
242                      CFX_GEModule::Get()->GetFontCache(), (FX_FLOAT)iFontSize,
243                      (CFX_Matrix*)&affine_matrix, m_fontColor,
244                      FXTEXT_CLEARTYPE);
245    geBitmap.SetDIBits(ge.GetBitmap(), 0, m_Height - iTextHeight);
246  } else {
247    CFX_Matrix affine_matrix1(1.0, 0.0, 0.0, -1.0, 0,
248                              (FX_FLOAT)(m_Height - iTextHeight + iFontSize));
249    if (matrix != NULL) {
250      affine_matrix1.Concat(*matrix);
251    }
252    device->DrawNormalText(iLen, pCharPos, m_pFont,
253                           CFX_GEModule::Get()->GetFontCache(),
254                           (FX_FLOAT)iFontSize, (CFX_Matrix*)&affine_matrix1,
255                           m_fontColor, FXTEXT_CLEARTYPE);
256  }
257  tempStr = str.Mid(11, 1);
258  iLen = tempStr.GetLength();
259  CalcTextInfo(tempStr, pCharPos + 11, m_pFont, strWidth, iFontSize, blank);
260  if (pOutBitmap != NULL) {
261    delete ge.GetBitmap();
262    ge.Create((int)strWidth, iTextHeight, FXDIB_Argb);
263    ge.GetBitmap()->Clear(m_backgroundColor);
264    ge.DrawNormalText(iLen, pCharPos + 11, m_pFont,
265                      CFX_GEModule::Get()->GetFontCache(), (FX_FLOAT)iFontSize,
266                      (CFX_Matrix*)&affine_matrix, m_fontColor,
267                      FXTEXT_CLEARTYPE);
268    geBitmap.SetDIBits(ge.GetBitmap(), leftPosition + 85 * multiple,
269                       m_Height - iTextHeight);
270  } else {
271    CFX_Matrix affine_matrix1(
272        1.0, 0.0, 0.0, -1.0,
273        (FX_FLOAT)(leftPosition + 85 * multiple) * m_outputHScale,
274        (FX_FLOAT)(m_Height - iTextHeight + iFontSize));
275    if (matrix != NULL) {
276      affine_matrix1.Concat(*matrix);
277    }
278    device->DrawNormalText(iLen, pCharPos + 11, m_pFont,
279                           CFX_GEModule::Get()->GetFontCache(),
280                           (FX_FLOAT)iFontSize, (CFX_Matrix*)&affine_matrix1,
281                           m_fontColor, FXTEXT_CLEARTYPE);
282  }
283  FX_Free(pCharPos);
284}
285void CBC_OnedUPCAWriter::RenderResult(const CFX_WideStringC& contents,
286                                      uint8_t* code,
287                                      int32_t codeLength,
288                                      FX_BOOL isDevice,
289                                      int32_t& e) {
290  CBC_OneDimWriter::RenderResult(contents, code, codeLength, isDevice, e);
291}
292