• 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 2011 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/oned/BC_OneDimWriter.h"
24 
25 #include <algorithm>
26 #include <memory>
27 
28 #include "core/fxge/cfx_fxgedevice.h"
29 #include "core/fxge/cfx_gemodule.h"
30 #include "core/fxge/cfx_graphstatedata.h"
31 #include "core/fxge/cfx_pathdata.h"
32 #include "core/fxge/cfx_renderdevice.h"
33 #include "core/fxge/cfx_unicodeencodingex.h"
34 #include "third_party/base/ptr_util.h"
35 #include "xfa/fxbarcode/BC_Writer.h"
36 #include "xfa/fxbarcode/common/BC_CommonBitMatrix.h"
37 
CBC_OneDimWriter()38 CBC_OneDimWriter::CBC_OneDimWriter() {
39   m_locTextLoc = BC_TEXT_LOC_BELOWEMBED;
40   m_bPrintChecksum = true;
41   m_iDataLenth = 0;
42   m_bCalcChecksum = false;
43   m_pFont = nullptr;
44   m_fFontSize = 10;
45   m_iFontStyle = 0;
46   m_fontColor = 0xff000000;
47   m_iContentLen = 0;
48   m_bLeftPadding = false;
49   m_bRightPadding = false;
50 }
51 
~CBC_OneDimWriter()52 CBC_OneDimWriter::~CBC_OneDimWriter() {}
53 
SetPrintChecksum(bool checksum)54 void CBC_OneDimWriter::SetPrintChecksum(bool checksum) {
55   m_bPrintChecksum = checksum;
56 }
57 
SetDataLength(int32_t length)58 void CBC_OneDimWriter::SetDataLength(int32_t length) {
59   m_iDataLenth = length;
60 }
61 
SetCalcChecksum(bool state)62 void CBC_OneDimWriter::SetCalcChecksum(bool state) {
63   m_bCalcChecksum = state;
64 }
65 
SetFont(CFX_Font * cFont)66 bool CBC_OneDimWriter::SetFont(CFX_Font* cFont) {
67   if (!cFont)
68     return false;
69 
70   m_pFont = cFont;
71   return true;
72 }
73 
SetFontSize(FX_FLOAT size)74 void CBC_OneDimWriter::SetFontSize(FX_FLOAT size) {
75   m_fFontSize = size;
76 }
77 
SetFontStyle(int32_t style)78 void CBC_OneDimWriter::SetFontStyle(int32_t style) {
79   m_iFontStyle = style;
80 }
81 
SetFontColor(FX_ARGB color)82 void CBC_OneDimWriter::SetFontColor(FX_ARGB color) {
83   m_fontColor = color;
84 }
85 
Upper(FX_WCHAR ch)86 FX_WCHAR CBC_OneDimWriter::Upper(FX_WCHAR ch) {
87   if (ch >= 'a' && ch <= 'z') {
88     ch = ch - ('a' - 'A');
89   }
90   return ch;
91 }
92 
Encode(const CFX_ByteString & contents,BCFORMAT format,int32_t & outWidth,int32_t & outHeight,int32_t hints,int32_t & e)93 uint8_t* CBC_OneDimWriter::Encode(const CFX_ByteString& contents,
94                                   BCFORMAT format,
95                                   int32_t& outWidth,
96                                   int32_t& outHeight,
97                                   int32_t hints,
98                                   int32_t& e) {
99   uint8_t* ret = nullptr;
100   outHeight = 1;
101   if (m_Width >= 20) {
102     ret = Encode(contents, outWidth, e);
103   } else {
104     ret = Encode(contents, outWidth, e);
105   }
106   if (e != BCExceptionNO)
107     return nullptr;
108   return ret;
109 }
110 
Encode(const CFX_ByteString & contents,BCFORMAT format,int32_t & outWidth,int32_t & outHeight,int32_t & e)111 uint8_t* CBC_OneDimWriter::Encode(const CFX_ByteString& contents,
112                                   BCFORMAT format,
113                                   int32_t& outWidth,
114                                   int32_t& outHeight,
115                                   int32_t& e) {
116   uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e);
117   if (e != BCExceptionNO)
118     return nullptr;
119   return ret;
120 }
121 
Encode(const CFX_ByteString & contents,int32_t & outLength,int32_t & e)122 uint8_t* CBC_OneDimWriter::Encode(const CFX_ByteString& contents,
123                                   int32_t& outLength,
124                                   int32_t& e) {
125   return nullptr;
126 }
127 
AppendPattern(uint8_t * target,int32_t pos,const int32_t * pattern,int32_t patternLength,int32_t startColor,int32_t & e)128 int32_t CBC_OneDimWriter::AppendPattern(uint8_t* target,
129                                         int32_t pos,
130                                         const int32_t* pattern,
131                                         int32_t patternLength,
132                                         int32_t startColor,
133                                         int32_t& e) {
134   if (startColor != 0 && startColor != 1) {
135     e = BCExceptionValueMustBeEither0or1;
136     return 0;
137   }
138   uint8_t color = (uint8_t)startColor;
139   int32_t numAdded = 0;
140   for (int32_t i = 0; i < patternLength; i++) {
141     for (int32_t j = 0; j < pattern[i]; j++) {
142       target[pos] = color;
143       pos += 1;
144       numAdded += 1;
145     }
146     color ^= 1;
147   }
148   return numAdded;
149 }
150 
CalcTextInfo(const CFX_ByteString & text,FXTEXT_CHARPOS * charPos,CFX_Font * cFont,FX_FLOAT geWidth,int32_t fontSize,FX_FLOAT & charsLen)151 void CBC_OneDimWriter::CalcTextInfo(const CFX_ByteString& text,
152                                     FXTEXT_CHARPOS* charPos,
153                                     CFX_Font* cFont,
154                                     FX_FLOAT geWidth,
155                                     int32_t fontSize,
156                                     FX_FLOAT& charsLen) {
157   std::unique_ptr<CFX_UnicodeEncodingEx> encoding(
158       FX_CreateFontEncodingEx(cFont));
159 
160   int32_t length = text.GetLength();
161   uint32_t* pCharCode = FX_Alloc(uint32_t, text.GetLength());
162   FX_FLOAT charWidth = 0;
163   for (int32_t j = 0; j < text.GetLength(); j++) {
164     pCharCode[j] = encoding->CharCodeFromUnicode(text[j]);
165     int32_t glyp_code = encoding->GlyphFromCharCode(pCharCode[j]);
166     int32_t glyp_value = cFont->GetGlyphWidth(glyp_code);
167     FX_FLOAT temp = (FX_FLOAT)((glyp_value)*fontSize / 1000.0);
168     charWidth += temp;
169   }
170   charsLen = charWidth;
171   FX_FLOAT leftPositon = (FX_FLOAT)(geWidth - charsLen) / 2.0f;
172   if (leftPositon < 0 && geWidth == 0) {
173     leftPositon = 0;
174   }
175   FX_FLOAT penX = 0.0;
176   FX_FLOAT penY =
177       (FX_FLOAT)FXSYS_abs(cFont->GetDescent()) * (FX_FLOAT)fontSize / 1000.0f;
178   FX_FLOAT left = leftPositon;
179   FX_FLOAT top = 0.0;
180   charPos[0].m_Origin = CFX_PointF(penX + left, penY + top);
181   charPos[0].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[0]);
182   charPos[0].m_FontCharWidth = cFont->GetGlyphWidth(charPos[0].m_GlyphIndex);
183 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
184   charPos[0].m_ExtGID = charPos[0].m_GlyphIndex;
185 #endif
186   penX += (FX_FLOAT)(charPos[0].m_FontCharWidth) * (FX_FLOAT)fontSize / 1000.0f;
187   for (int32_t i = 1; i < length; i++) {
188     charPos[i].m_Origin = CFX_PointF(penX + left, penY + top);
189     charPos[i].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[i]);
190     charPos[i].m_FontCharWidth = cFont->GetGlyphWidth(charPos[i].m_GlyphIndex);
191 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
192     charPos[i].m_ExtGID = charPos[i].m_GlyphIndex;
193 #endif
194     penX +=
195         (FX_FLOAT)(charPos[i].m_FontCharWidth) * (FX_FLOAT)fontSize / 1000.0f;
196   }
197   FX_Free(pCharCode);
198 }
199 
ShowDeviceChars(CFX_RenderDevice * device,const CFX_Matrix * matrix,const CFX_ByteString str,FX_FLOAT geWidth,FXTEXT_CHARPOS * pCharPos,FX_FLOAT locX,FX_FLOAT locY,int32_t barWidth)200 void CBC_OneDimWriter::ShowDeviceChars(CFX_RenderDevice* device,
201                                        const CFX_Matrix* matrix,
202                                        const CFX_ByteString str,
203                                        FX_FLOAT geWidth,
204                                        FXTEXT_CHARPOS* pCharPos,
205                                        FX_FLOAT locX,
206                                        FX_FLOAT locY,
207                                        int32_t barWidth) {
208   int32_t iFontSize = (int32_t)fabs(m_fFontSize);
209   int32_t iTextHeight = iFontSize + 1;
210   CFX_FloatRect rect((FX_FLOAT)locX, (FX_FLOAT)locY, (FX_FLOAT)(locX + geWidth),
211                      (FX_FLOAT)(locY + iTextHeight));
212   if (geWidth != m_Width) {
213     rect.right -= 1;
214   }
215   matrix->TransformRect(rect);
216   FX_RECT re = rect.GetOuterRect();
217   device->FillRect(&re, m_backgroundColor);
218   CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, (FX_FLOAT)locX,
219                            (FX_FLOAT)(locY + iFontSize));
220   if (matrix) {
221     affine_matrix.Concat(*matrix);
222   }
223   device->DrawNormalText(str.GetLength(), pCharPos, m_pFont,
224                          static_cast<FX_FLOAT>(iFontSize), &affine_matrix,
225                          m_fontColor, FXTEXT_CLEARTYPE);
226 }
227 
ShowBitmapChars(CFX_DIBitmap * pOutBitmap,const CFX_ByteString str,FX_FLOAT geWidth,FXTEXT_CHARPOS * pCharPos,FX_FLOAT locX,FX_FLOAT locY,int32_t barWidth)228 void CBC_OneDimWriter::ShowBitmapChars(CFX_DIBitmap* pOutBitmap,
229                                        const CFX_ByteString str,
230                                        FX_FLOAT geWidth,
231                                        FXTEXT_CHARPOS* pCharPos,
232                                        FX_FLOAT locX,
233                                        FX_FLOAT locY,
234                                        int32_t barWidth) {
235   int32_t iFontSize = (int32_t)fabs(m_fFontSize);
236   int32_t iTextHeight = iFontSize + 1;
237   CFX_FxgeDevice ge;
238   ge.Create((int)geWidth, iTextHeight, m_colorSpace, nullptr);
239   FX_RECT geRect(0, 0, (int)geWidth, iTextHeight);
240   ge.FillRect(&geRect, m_backgroundColor);
241   CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, 0.0,
242                            static_cast<FX_FLOAT>(iFontSize));
243   ge.DrawNormalText(str.GetLength(), pCharPos, m_pFont,
244                     static_cast<FX_FLOAT>(iFontSize), &affine_matrix,
245                     m_fontColor, FXTEXT_CLEARTYPE);
246   CFX_FxgeDevice geBitmap;
247   geBitmap.Attach(pOutBitmap, false, nullptr, false);
248   geBitmap.SetDIBits(ge.GetBitmap(), (int)locX, (int)locY);
249 }
250 
ShowChars(const CFX_WideStringC & contents,CFX_DIBitmap * pOutBitmap,CFX_RenderDevice * device,const CFX_Matrix * matrix,int32_t barWidth,int32_t multiple,int32_t & e)251 void CBC_OneDimWriter::ShowChars(const CFX_WideStringC& contents,
252                                  CFX_DIBitmap* pOutBitmap,
253                                  CFX_RenderDevice* device,
254                                  const CFX_Matrix* matrix,
255                                  int32_t barWidth,
256                                  int32_t multiple,
257                                  int32_t& e) {
258   if (!device && !pOutBitmap) {
259     e = BCExceptionIllegalArgument;
260     return;
261   }
262   if (!m_pFont) {
263     e = BCExceptionNullPointer;
264     return;
265   }
266   CFX_ByteString str = FX_UTF8Encode(contents);
267   int32_t iLen = str.GetLength();
268   FXTEXT_CHARPOS* pCharPos = FX_Alloc(FXTEXT_CHARPOS, iLen);
269   FXSYS_memset(pCharPos, 0, sizeof(FXTEXT_CHARPOS) * iLen);
270   FX_FLOAT charsLen = 0;
271   FX_FLOAT geWidth = 0;
272   if (m_locTextLoc == BC_TEXT_LOC_ABOVEEMBED ||
273       m_locTextLoc == BC_TEXT_LOC_BELOWEMBED) {
274     geWidth = 0;
275   } else if (m_locTextLoc == BC_TEXT_LOC_ABOVE ||
276              m_locTextLoc == BC_TEXT_LOC_BELOW) {
277     geWidth = (FX_FLOAT)barWidth;
278   }
279   int32_t iFontSize = (int32_t)fabs(m_fFontSize);
280   int32_t iTextHeight = iFontSize + 1;
281   CalcTextInfo(str, pCharPos, m_pFont, geWidth, iFontSize, charsLen);
282   if (charsLen < 1) {
283     return;
284   }
285   int32_t locX = 0;
286   int32_t locY = 0;
287   switch (m_locTextLoc) {
288     case BC_TEXT_LOC_ABOVEEMBED:
289       locX = (int32_t)(barWidth - charsLen) / 2;
290       locY = 0;
291       geWidth = charsLen;
292       break;
293     case BC_TEXT_LOC_ABOVE:
294       locX = 0;
295       locY = 0;
296       geWidth = (FX_FLOAT)barWidth;
297       break;
298     case BC_TEXT_LOC_BELOWEMBED:
299       locX = (int32_t)(barWidth - charsLen) / 2;
300       locY = m_Height - iTextHeight;
301       geWidth = charsLen;
302       break;
303     case BC_TEXT_LOC_BELOW:
304     default:
305       locX = 0;
306       locY = m_Height - iTextHeight;
307       geWidth = (FX_FLOAT)barWidth;
308       break;
309   }
310   if (device) {
311     ShowDeviceChars(device, matrix, str, geWidth, pCharPos, (FX_FLOAT)locX,
312                     (FX_FLOAT)locY, barWidth);
313   } else {
314     ShowBitmapChars(pOutBitmap, str, geWidth, pCharPos, (FX_FLOAT)locX,
315                     (FX_FLOAT)locY, barWidth);
316   }
317   FX_Free(pCharPos);
318 }
319 
RenderBitmapResult(CFX_DIBitmap * & pOutBitmap,const CFX_WideStringC & contents,int32_t & e)320 void CBC_OneDimWriter::RenderBitmapResult(CFX_DIBitmap*& pOutBitmap,
321                                           const CFX_WideStringC& contents,
322                                           int32_t& e) {
323   if (!m_output)
324     if (e != BCExceptionNO)
325       return;
326 
327   pOutBitmap = CreateDIBitmap(m_output->GetWidth(), m_output->GetHeight());
328   pOutBitmap->Clear(m_backgroundColor);
329   if (!pOutBitmap) {
330     e = BCExceptionFailToCreateBitmap;
331     return;
332   }
333   for (int32_t x = 0; x < m_output->GetWidth(); x++) {
334     for (int32_t y = 0; y < m_output->GetHeight(); y++) {
335       if (m_output->Get(x, y)) {
336         pOutBitmap->SetPixel(x, y, m_barColor);
337       }
338     }
339   }
340   int32_t i = 0;
341   for (; i < contents.GetLength(); i++)
342     if (contents.GetAt(i) != ' ') {
343       break;
344     }
345   if (m_locTextLoc != BC_TEXT_LOC_NONE && i < contents.GetLength()) {
346     ShowChars(contents, pOutBitmap, nullptr, nullptr, m_barWidth, m_multiple,
347               e);
348     if (e != BCExceptionNO)
349       return;
350   }
351   std::unique_ptr<CFX_DIBitmap> pStretchBitmap =
352       pOutBitmap->StretchTo(m_Width, m_Height);
353   delete pOutBitmap;
354   pOutBitmap = pStretchBitmap.release();
355 }
356 
RenderDeviceResult(CFX_RenderDevice * device,const CFX_Matrix * matrix,const CFX_WideStringC & contents,int32_t & e)357 void CBC_OneDimWriter::RenderDeviceResult(CFX_RenderDevice* device,
358                                           const CFX_Matrix* matrix,
359                                           const CFX_WideStringC& contents,
360                                           int32_t& e) {
361   if (!m_output)
362     if (e != BCExceptionNO)
363       return;
364 
365   CFX_GraphStateData stateData;
366   CFX_PathData path;
367   path.AppendRect(0, 0, (FX_FLOAT)m_Width, (FX_FLOAT)m_Height);
368   device->DrawPath(&path, matrix, &stateData, m_backgroundColor,
369                    m_backgroundColor, FXFILL_ALTERNATE);
370   CFX_Matrix matri(m_outputHScale, 0.0, 0.0, (FX_FLOAT)m_Height, 0.0, 0.0);
371   matri.Concat(*matrix);
372   for (int32_t x = 0; x < m_output->GetWidth(); x++) {
373     for (int32_t y = 0; y < m_output->GetHeight(); y++) {
374       CFX_PathData rect;
375       rect.AppendRect((FX_FLOAT)x, (FX_FLOAT)y, (FX_FLOAT)(x + 1),
376                       (FX_FLOAT)(y + 1));
377       if (m_output->Get(x, y)) {
378         CFX_GraphStateData data;
379         device->DrawPath(&rect, &matri, &data, m_barColor, 0, FXFILL_WINDING);
380       }
381     }
382   }
383   int32_t i = 0;
384   for (; i < contents.GetLength(); i++)
385     if (contents.GetAt(i) != ' ') {
386       break;
387     }
388   if (m_locTextLoc != BC_TEXT_LOC_NONE && i < contents.GetLength()) {
389     ShowChars(contents, nullptr, device, matrix, m_barWidth, m_multiple, e);
390     if (e != BCExceptionNO)
391       return;
392   }
393 }
394 
RenderResult(const CFX_WideStringC & contents,uint8_t * code,int32_t codeLength,bool isDevice,int32_t & e)395 void CBC_OneDimWriter::RenderResult(const CFX_WideStringC& contents,
396                                     uint8_t* code,
397                                     int32_t codeLength,
398                                     bool isDevice,
399                                     int32_t& e) {
400   if (codeLength < 1) {
401     if (e != BCExceptionNO)
402       return;
403   }
404   if (m_ModuleHeight < 20.0) {
405     m_ModuleHeight = 20;
406   }
407   int32_t codeOldLength = codeLength;
408   int32_t leftPadding = 0;
409   int32_t rightPadding = 0;
410   if (m_bLeftPadding) {
411     leftPadding = 7;
412   }
413   if (m_bRightPadding) {
414     rightPadding = 7;
415   }
416   codeLength += leftPadding;
417   codeLength += rightPadding;
418   m_outputHScale = 1.0;
419   if (m_Width > 0) {
420     m_outputHScale = (FX_FLOAT)m_Width / (FX_FLOAT)codeLength;
421   }
422   if (!isDevice) {
423     m_outputHScale =
424         std::max(m_outputHScale, static_cast<FX_FLOAT>(m_ModuleWidth));
425   }
426   FX_FLOAT dataLengthScale = 1.0;
427   if (m_iDataLenth > 0 && contents.GetLength() != 0) {
428     dataLengthScale = FX_FLOAT(contents.GetLength()) / FX_FLOAT(m_iDataLenth);
429   }
430   if (m_iDataLenth > 0 && contents.GetLength() == 0) {
431     dataLengthScale = FX_FLOAT(1) / FX_FLOAT(m_iDataLenth);
432   }
433   m_multiple = 1;
434   if (!isDevice) {
435     m_multiple = (int32_t)ceil(m_outputHScale * dataLengthScale);
436   }
437   int32_t outputHeight = 1;
438   if (!isDevice) {
439     if (m_Height == 0) {
440       outputHeight = std::max(20, m_ModuleHeight);
441     } else {
442       outputHeight = m_Height;
443     }
444   }
445   int32_t outputWidth = codeLength;
446   if (!isDevice) {
447     outputWidth = (int32_t)(codeLength * m_multiple / dataLengthScale);
448   }
449   m_barWidth = m_Width;
450   if (!isDevice) {
451     m_barWidth = codeLength * m_multiple;
452   }
453   m_output = pdfium::MakeUnique<CBC_CommonBitMatrix>();
454   m_output->Init(outputWidth, outputHeight);
455   int32_t outputX = leftPadding * m_multiple;
456   for (int32_t inputX = 0; inputX < codeOldLength; inputX++) {
457     if (code[inputX] == 1) {
458       if (outputX >= outputWidth) {
459         break;
460       }
461       if (outputX + m_multiple > outputWidth && outputWidth - outputX > 0) {
462         m_output->SetRegion(outputX, 0, outputWidth - outputX, outputHeight, e);
463         break;
464       }
465       m_output->SetRegion(outputX, 0, m_multiple, outputHeight, e);
466       if (e != BCExceptionNO)
467         return;
468     }
469     outputX += m_multiple;
470   }
471 }
472 
CheckContentValidity(const CFX_WideStringC & contents)473 bool CBC_OneDimWriter::CheckContentValidity(const CFX_WideStringC& contents) {
474   return true;
475 }
476 
FilterContents(const CFX_WideStringC & contents)477 CFX_WideString CBC_OneDimWriter::FilterContents(
478     const CFX_WideStringC& contents) {
479   return CFX_WideString();
480 }
481 
RenderTextContents(const CFX_WideStringC & contents)482 CFX_WideString CBC_OneDimWriter::RenderTextContents(
483     const CFX_WideStringC& contents) {
484   return CFX_WideString();
485 }
486