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 "fxbarcode/oned/BC_OneDimWriter.h"
     24 
     25 #include <algorithm>
     26 #include <memory>
     27 #include <vector>
     28 
     29 #include "core/fxge/cfx_defaultrenderdevice.h"
     30 #include "core/fxge/cfx_font.h"
     31 #include "core/fxge/cfx_graphstatedata.h"
     32 #include "core/fxge/cfx_pathdata.h"
     33 #include "core/fxge/cfx_renderdevice.h"
     34 #include "core/fxge/cfx_unicodeencodingex.h"
     35 #include "fxbarcode/BC_Writer.h"
     36 #include "third_party/base/ptr_util.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(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 wchar_t CBC_OneDimWriter::Upper(wchar_t ch) {
     87   if (ch >= 'a' && ch <= 'z') {
     88     ch = ch - ('a' - 'A');
     89   }
     90   return ch;
     91 }
     92 
     93 uint8_t* CBC_OneDimWriter::EncodeWithHint(const ByteString& contents,
     94                                           BCFORMAT format,
     95                                           int32_t& outWidth,
     96                                           int32_t& outHeight,
     97                                           int32_t hints) {
     98   outHeight = 1;
     99   return EncodeImpl(contents, outWidth);
    100 }
    101 
    102 uint8_t* CBC_OneDimWriter::Encode(const ByteString& contents,
    103                                   BCFORMAT format,
    104                                   int32_t& outWidth,
    105                                   int32_t& outHeight) {
    106   return EncodeWithHint(contents, format, outWidth, outHeight, 0);
    107 }
    108 
    109 int32_t CBC_OneDimWriter::AppendPattern(uint8_t* target,
    110                                         int32_t pos,
    111                                         const int8_t* pattern,
    112                                         int32_t patternLength,
    113                                         int32_t startColor,
    114                                         int32_t& e) {
    115   if (startColor != 0 && startColor != 1) {
    116     e = BCExceptionValueMustBeEither0or1;
    117     return 0;
    118   }
    119   uint8_t color = (uint8_t)startColor;
    120   int32_t numAdded = 0;
    121   for (int32_t i = 0; i < patternLength; i++) {
    122     for (int32_t j = 0; j < pattern[i]; j++) {
    123       target[pos++] = color;
    124       numAdded += 1;
    125     }
    126     color ^= 1;
    127   }
    128   return numAdded;
    129 }
    130 
    131 void CBC_OneDimWriter::CalcTextInfo(const ByteString& text,
    132                                     FXTEXT_CHARPOS* charPos,
    133                                     CFX_Font* cFont,
    134                                     float geWidth,
    135                                     int32_t fontSize,
    136                                     float& charsLen) {
    137   std::unique_ptr<CFX_UnicodeEncodingEx> encoding =
    138       FX_CreateFontEncodingEx(cFont, FXFM_ENCODING_NONE);
    139 
    140   size_t length = text.GetLength();
    141   uint32_t* pCharCode = FX_Alloc(uint32_t, text.GetLength());
    142   float charWidth = 0;
    143   for (size_t j = 0; j < length; j++) {
    144     pCharCode[j] = encoding->CharCodeFromUnicode(text[j]);
    145     int32_t glyp_code = encoding->GlyphFromCharCode(pCharCode[j]);
    146     int32_t glyp_value = cFont->GetGlyphWidth(glyp_code);
    147     float temp = (float)((glyp_value)*fontSize / 1000.0);
    148     charWidth += temp;
    149   }
    150   charsLen = charWidth;
    151   float leftPositon = (float)(geWidth - charsLen) / 2.0f;
    152   if (leftPositon < 0 && geWidth == 0) {
    153     leftPositon = 0;
    154   }
    155   float penX = 0.0;
    156   float penY = (float)abs(cFont->GetDescent()) * (float)fontSize / 1000.0f;
    157   float left = leftPositon;
    158   float top = 0.0;
    159   charPos[0].m_Origin = CFX_PointF(penX + left, penY + top);
    160   charPos[0].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[0]);
    161   charPos[0].m_FontCharWidth = cFont->GetGlyphWidth(charPos[0].m_GlyphIndex);
    162 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
    163   charPos[0].m_ExtGID = charPos[0].m_GlyphIndex;
    164 #endif
    165   penX += (float)(charPos[0].m_FontCharWidth) * (float)fontSize / 1000.0f;
    166   for (size_t i = 1; i < length; i++) {
    167     charPos[i].m_Origin = CFX_PointF(penX + left, penY + top);
    168     charPos[i].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[i]);
    169     charPos[i].m_FontCharWidth = cFont->GetGlyphWidth(charPos[i].m_GlyphIndex);
    170 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
    171     charPos[i].m_ExtGID = charPos[i].m_GlyphIndex;
    172 #endif
    173     penX += (float)(charPos[i].m_FontCharWidth) * (float)fontSize / 1000.0f;
    174   }
    175   FX_Free(pCharCode);
    176 }
    177 
    178 void CBC_OneDimWriter::ShowDeviceChars(CFX_RenderDevice* device,
    179                                        const CFX_Matrix* matrix,
    180                                        const ByteString str,
    181                                        float geWidth,
    182                                        FXTEXT_CHARPOS* pCharPos,
    183                                        float locX,
    184                                        float locY,
    185                                        int32_t barWidth) {
    186   int32_t iFontSize = (int32_t)fabs(m_fFontSize);
    187   int32_t iTextHeight = iFontSize + 1;
    188   CFX_FloatRect rect((float)locX, (float)locY, (float)(locX + geWidth),
    189                      (float)(locY + iTextHeight));
    190   if (geWidth != m_Width) {
    191     rect.right -= 1;
    192   }
    193   FX_RECT re = matrix->TransformRect(rect).GetOuterRect();
    194   device->FillRect(&re, m_backgroundColor);
    195   CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, (float)locX,
    196                            (float)(locY + iFontSize));
    197   if (matrix) {
    198     affine_matrix.Concat(*matrix);
    199   }
    200   device->DrawNormalText(str.GetLength(), pCharPos, m_pFont.Get(),
    201                          static_cast<float>(iFontSize), &affine_matrix,
    202                          m_fontColor, FXTEXT_CLEARTYPE);
    203 }
    204 
    205 bool CBC_OneDimWriter::ShowChars(const WideStringView& contents,
    206                                  CFX_RenderDevice* device,
    207                                  const CFX_Matrix* matrix,
    208                                  int32_t barWidth,
    209                                  int32_t multiple) {
    210   if (!device || !m_pFont)
    211     return false;
    212 
    213   ByteString str = FX_UTF8Encode(contents);
    214   int32_t iLen = str.GetLength();
    215   std::vector<FXTEXT_CHARPOS> charpos(iLen);
    216   float charsLen = 0;
    217   float geWidth = 0;
    218   if (m_locTextLoc == BC_TEXT_LOC_ABOVEEMBED ||
    219       m_locTextLoc == BC_TEXT_LOC_BELOWEMBED) {
    220     geWidth = 0;
    221   } else if (m_locTextLoc == BC_TEXT_LOC_ABOVE ||
    222              m_locTextLoc == BC_TEXT_LOC_BELOW) {
    223     geWidth = (float)barWidth;
    224   }
    225   int32_t iFontSize = (int32_t)fabs(m_fFontSize);
    226   int32_t iTextHeight = iFontSize + 1;
    227   CalcTextInfo(str, charpos.data(), m_pFont.Get(), geWidth, iFontSize,
    228                charsLen);
    229   if (charsLen < 1)
    230     return true;
    231 
    232   int32_t locX = 0;
    233   int32_t locY = 0;
    234   switch (m_locTextLoc) {
    235     case BC_TEXT_LOC_ABOVEEMBED:
    236       locX = (int32_t)(barWidth - charsLen) / 2;
    237       locY = 0;
    238       geWidth = charsLen;
    239       break;
    240     case BC_TEXT_LOC_ABOVE:
    241       locX = 0;
    242       locY = 0;
    243       geWidth = (float)barWidth;
    244       break;
    245     case BC_TEXT_LOC_BELOWEMBED:
    246       locX = (int32_t)(barWidth - charsLen) / 2;
    247       locY = m_Height - iTextHeight;
    248       geWidth = charsLen;
    249       break;
    250     case BC_TEXT_LOC_BELOW:
    251     default:
    252       locX = 0;
    253       locY = m_Height - iTextHeight;
    254       geWidth = (float)barWidth;
    255       break;
    256   }
    257   ShowDeviceChars(device, matrix, str, geWidth, charpos.data(), (float)locX,
    258                   (float)locY, barWidth);
    259   return true;
    260 }
    261 
    262 bool CBC_OneDimWriter::RenderDeviceResult(CFX_RenderDevice* device,
    263                                           const CFX_Matrix* matrix,
    264                                           const WideStringView& contents) {
    265   if (m_output.empty())
    266     return false;
    267 
    268   CFX_GraphStateData stateData;
    269   CFX_PathData path;
    270   path.AppendRect(0, 0, static_cast<float>(m_Width),
    271                   static_cast<float>(m_Height));
    272   device->DrawPath(&path, matrix, &stateData, m_backgroundColor,
    273                    m_backgroundColor, FXFILL_ALTERNATE);
    274   CFX_Matrix scaledMatrix(m_outputHScale, 0.0, 0.0,
    275                           static_cast<float>(m_Height), 0.0, 0.0);
    276   scaledMatrix.Concat(*matrix);
    277   for (auto& rect : m_output) {
    278     CFX_GraphStateData data;
    279     device->DrawPath(&rect, &scaledMatrix, &data, m_barColor, 0,
    280                      FXFILL_WINDING);
    281   }
    282 
    283   return m_locTextLoc == BC_TEXT_LOC_NONE || !contents.Contains(' ') ||
    284          ShowChars(contents, device, matrix, m_barWidth, m_multiple);
    285 }
    286 
    287 bool CBC_OneDimWriter::RenderResult(const WideStringView& contents,
    288                                     uint8_t* code,
    289                                     int32_t codeLength) {
    290   if (codeLength < 1)
    291     return false;
    292 
    293   m_ModuleHeight = std::max(m_ModuleHeight, 20);
    294   const int32_t codeOldLength = codeLength;
    295   const int32_t leftPadding = m_bLeftPadding ? 7 : 0;
    296   const int32_t rightPadding = m_bRightPadding ? 7 : 0;
    297   codeLength += leftPadding;
    298   codeLength += rightPadding;
    299   m_outputHScale =
    300       m_Width > 0 ? static_cast<float>(m_Width) / static_cast<float>(codeLength)
    301                   : 1.0;
    302   m_multiple = 1;
    303   const int32_t outputHeight = 1;
    304   const int32_t outputWidth = codeLength;
    305   m_barWidth = m_Width;
    306 
    307   m_output.clear();
    308   for (int32_t inputX = 0, outputX = leftPadding * m_multiple;
    309        inputX < codeOldLength; ++inputX, outputX += m_multiple) {
    310     if (code[inputX] != 1)
    311       continue;
    312 
    313     if (outputX >= outputWidth)
    314       return true;
    315 
    316     if (outputX + m_multiple > outputWidth && outputWidth - outputX > 0) {
    317       RenderVerticalBars(outputX, outputWidth - outputX, outputHeight);
    318       return true;
    319     }
    320 
    321     RenderVerticalBars(outputX, m_multiple, outputHeight);
    322   }
    323   return true;
    324 }
    325 
    326 void CBC_OneDimWriter::RenderVerticalBars(int32_t outputX,
    327                                           int32_t width,
    328                                           int32_t height) {
    329   for (int i = 0; i < width; ++i) {
    330     float x = outputX + i;
    331     CFX_PathData rect;
    332     rect.AppendRect(x, 0.0f, x + 1, static_cast<float>(height));
    333     m_output.push_back(rect);
    334   }
    335 }
    336 
    337 WideString CBC_OneDimWriter::RenderTextContents(
    338     const WideStringView& contents) {
    339   return WideString();
    340 }
    341