Home | History | Annotate | Download | only in oned
      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 
     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 
     52 CBC_OneDimWriter::~CBC_OneDimWriter() {}
     53 
     54 void CBC_OneDimWriter::SetPrintChecksum(bool checksum) {
     55   m_bPrintChecksum = checksum;
     56 }
     57 
     58 void CBC_OneDimWriter::SetDataLength(int32_t length) {
     59   m_iDataLenth = length;
     60 }
     61 
     62 void CBC_OneDimWriter::SetCalcChecksum(bool state) {
     63   m_bCalcChecksum = state;
     64 }
     65 
     66 bool CBC_OneDimWriter::SetFont(CFX_Font* cFont) {
     67   if (!cFont)
     68     return false;
     69 
     70   m_pFont = cFont;
     71   return true;
     72 }
     73 
     74 void CBC_OneDimWriter::SetFontSize(FX_FLOAT size) {
     75   m_fFontSize = size;
     76 }
     77 
     78 void CBC_OneDimWriter::SetFontStyle(int32_t style) {
     79   m_iFontStyle = style;
     80 }
     81 
     82 void CBC_OneDimWriter::SetFontColor(FX_ARGB color) {
     83   m_fontColor = color;
     84 }
     85 
     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 
     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 
    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 
    122 uint8_t* CBC_OneDimWriter::Encode(const CFX_ByteString& contents,
    123                                   int32_t& outLength,
    124                                   int32_t& e) {
    125   return nullptr;
    126 }
    127 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    473 bool CBC_OneDimWriter::CheckContentValidity(const CFX_WideStringC& contents) {
    474   return true;
    475 }
    476 
    477 CFX_WideString CBC_OneDimWriter::FilterContents(
    478     const CFX_WideStringC& contents) {
    479   return CFX_WideString();
    480 }
    481 
    482 CFX_WideString CBC_OneDimWriter::RenderTextContents(
    483     const CFX_WideStringC& contents) {
    484   return CFX_WideString();
    485 }
    486