xref: /aosp_15_r20/external/pdfium/fxbarcode/BC_TwoDimWriter.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include "fxbarcode/BC_TwoDimWriter.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <algorithm>
10*3ac0a46fSAndroid Build Coastguard Worker 
11*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_safe_types.h"
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_fillrenderoptions.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_graphstatedata.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_path.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_renderdevice.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "fxbarcode/BC_Writer.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "fxbarcode/common/BC_CommonBitMatrix.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/numerics/safe_math.h"
20*3ac0a46fSAndroid Build Coastguard Worker 
CBC_TwoDimWriter(bool bFixedSize)21*3ac0a46fSAndroid Build Coastguard Worker CBC_TwoDimWriter::CBC_TwoDimWriter(bool bFixedSize)
22*3ac0a46fSAndroid Build Coastguard Worker     : m_bFixedSize(bFixedSize) {}
23*3ac0a46fSAndroid Build Coastguard Worker 
24*3ac0a46fSAndroid Build Coastguard Worker CBC_TwoDimWriter::~CBC_TwoDimWriter() = default;
25*3ac0a46fSAndroid Build Coastguard Worker 
RenderResult(pdfium::span<const uint8_t> code,int32_t codeWidth,int32_t codeHeight)26*3ac0a46fSAndroid Build Coastguard Worker bool CBC_TwoDimWriter::RenderResult(pdfium::span<const uint8_t> code,
27*3ac0a46fSAndroid Build Coastguard Worker                                     int32_t codeWidth,
28*3ac0a46fSAndroid Build Coastguard Worker                                     int32_t codeHeight) {
29*3ac0a46fSAndroid Build Coastguard Worker   if (code.empty())
30*3ac0a46fSAndroid Build Coastguard Worker     return false;
31*3ac0a46fSAndroid Build Coastguard Worker 
32*3ac0a46fSAndroid Build Coastguard Worker   m_inputWidth = codeWidth;
33*3ac0a46fSAndroid Build Coastguard Worker   m_inputHeight = codeHeight;
34*3ac0a46fSAndroid Build Coastguard Worker   int32_t tempWidth = m_inputWidth + 2;
35*3ac0a46fSAndroid Build Coastguard Worker   int32_t tempHeight = m_inputHeight + 2;
36*3ac0a46fSAndroid Build Coastguard Worker   float moduleHSize = std::min(m_ModuleWidth, m_ModuleHeight);
37*3ac0a46fSAndroid Build Coastguard Worker   moduleHSize = std::min(moduleHSize, 8.0f);
38*3ac0a46fSAndroid Build Coastguard Worker   moduleHSize = std::max(moduleHSize, 1.0f);
39*3ac0a46fSAndroid Build Coastguard Worker   FX_SAFE_INT32 scaledWidth = tempWidth;
40*3ac0a46fSAndroid Build Coastguard Worker   FX_SAFE_INT32 scaledHeight = tempHeight;
41*3ac0a46fSAndroid Build Coastguard Worker   scaledWidth *= moduleHSize;
42*3ac0a46fSAndroid Build Coastguard Worker   scaledHeight *= moduleHSize;
43*3ac0a46fSAndroid Build Coastguard Worker   m_outputWidth = scaledWidth.ValueOrDie();
44*3ac0a46fSAndroid Build Coastguard Worker   m_outputHeight = scaledHeight.ValueOrDie();
45*3ac0a46fSAndroid Build Coastguard Worker 
46*3ac0a46fSAndroid Build Coastguard Worker   if (m_bFixedSize) {
47*3ac0a46fSAndroid Build Coastguard Worker     if (m_Width < m_outputWidth || m_Height < m_outputHeight) {
48*3ac0a46fSAndroid Build Coastguard Worker       return false;
49*3ac0a46fSAndroid Build Coastguard Worker     }
50*3ac0a46fSAndroid Build Coastguard Worker   } else {
51*3ac0a46fSAndroid Build Coastguard Worker     if (m_Width > m_outputWidth || m_Height > m_outputHeight) {
52*3ac0a46fSAndroid Build Coastguard Worker       int32_t width_factor = static_cast<int32_t>(
53*3ac0a46fSAndroid Build Coastguard Worker           floor(static_cast<float>(m_Width) / m_outputWidth));
54*3ac0a46fSAndroid Build Coastguard Worker       int32_t height_factor = static_cast<int32_t>(
55*3ac0a46fSAndroid Build Coastguard Worker           floor(static_cast<float>(m_Height) / m_outputHeight));
56*3ac0a46fSAndroid Build Coastguard Worker       width_factor = std::max(width_factor, 1);
57*3ac0a46fSAndroid Build Coastguard Worker       height_factor = std::max(height_factor, 1);
58*3ac0a46fSAndroid Build Coastguard Worker 
59*3ac0a46fSAndroid Build Coastguard Worker       m_outputWidth *= width_factor;
60*3ac0a46fSAndroid Build Coastguard Worker       m_outputHeight *= height_factor;
61*3ac0a46fSAndroid Build Coastguard Worker     }
62*3ac0a46fSAndroid Build Coastguard Worker   }
63*3ac0a46fSAndroid Build Coastguard Worker   m_multiX =
64*3ac0a46fSAndroid Build Coastguard Worker       static_cast<int32_t>(ceil(static_cast<float>(m_outputWidth) / tempWidth));
65*3ac0a46fSAndroid Build Coastguard Worker   m_multiY = static_cast<int32_t>(
66*3ac0a46fSAndroid Build Coastguard Worker       ceil(static_cast<float>(m_outputHeight) / tempHeight));
67*3ac0a46fSAndroid Build Coastguard Worker   if (m_bFixedSize) {
68*3ac0a46fSAndroid Build Coastguard Worker     m_multiX = std::min(m_multiX, m_multiY);
69*3ac0a46fSAndroid Build Coastguard Worker     m_multiY = m_multiX;
70*3ac0a46fSAndroid Build Coastguard Worker   }
71*3ac0a46fSAndroid Build Coastguard Worker 
72*3ac0a46fSAndroid Build Coastguard Worker   m_leftPadding = std::max((m_Width - m_outputWidth) / 2, 0);
73*3ac0a46fSAndroid Build Coastguard Worker   m_topPadding = std::max((m_Height - m_outputHeight) / 2, 0);
74*3ac0a46fSAndroid Build Coastguard Worker 
75*3ac0a46fSAndroid Build Coastguard Worker   m_output = std::make_unique<CBC_CommonBitMatrix>(m_inputWidth, m_inputHeight);
76*3ac0a46fSAndroid Build Coastguard Worker   for (int32_t y = 0; y < m_inputHeight; ++y) {
77*3ac0a46fSAndroid Build Coastguard Worker     for (int32_t x = 0; x < m_inputWidth; ++x) {
78*3ac0a46fSAndroid Build Coastguard Worker       if (code[x + y * m_inputWidth] == 1)
79*3ac0a46fSAndroid Build Coastguard Worker         m_output->Set(x, y);
80*3ac0a46fSAndroid Build Coastguard Worker     }
81*3ac0a46fSAndroid Build Coastguard Worker   }
82*3ac0a46fSAndroid Build Coastguard Worker   return true;
83*3ac0a46fSAndroid Build Coastguard Worker }
84*3ac0a46fSAndroid Build Coastguard Worker 
RenderDeviceResult(CFX_RenderDevice * device,const CFX_Matrix & matrix)85*3ac0a46fSAndroid Build Coastguard Worker void CBC_TwoDimWriter::RenderDeviceResult(CFX_RenderDevice* device,
86*3ac0a46fSAndroid Build Coastguard Worker                                           const CFX_Matrix& matrix) {
87*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(m_output);
88*3ac0a46fSAndroid Build Coastguard Worker 
89*3ac0a46fSAndroid Build Coastguard Worker   CFX_GraphStateData stateData;
90*3ac0a46fSAndroid Build Coastguard Worker   CFX_Path path;
91*3ac0a46fSAndroid Build Coastguard Worker   path.AppendRect(0, 0, m_Width, m_Height);
92*3ac0a46fSAndroid Build Coastguard Worker   device->DrawPath(path, &matrix, &stateData, kBackgroundColor,
93*3ac0a46fSAndroid Build Coastguard Worker                    kBackgroundColor, CFX_FillRenderOptions::EvenOddOptions());
94*3ac0a46fSAndroid Build Coastguard Worker   int32_t leftPos = m_leftPadding;
95*3ac0a46fSAndroid Build Coastguard Worker   int32_t topPos = m_topPadding;
96*3ac0a46fSAndroid Build Coastguard Worker 
97*3ac0a46fSAndroid Build Coastguard Worker   CFX_Matrix matri = matrix;
98*3ac0a46fSAndroid Build Coastguard Worker   if (m_Width < m_outputWidth && m_Height < m_outputHeight) {
99*3ac0a46fSAndroid Build Coastguard Worker     CFX_Matrix matriScale(static_cast<float>(m_Width) / m_outputWidth, 0.0, 0.0,
100*3ac0a46fSAndroid Build Coastguard Worker                           static_cast<float>(m_Height) / m_outputHeight, 0.0,
101*3ac0a46fSAndroid Build Coastguard Worker                           0.0);
102*3ac0a46fSAndroid Build Coastguard Worker     matriScale.Concat(matrix);
103*3ac0a46fSAndroid Build Coastguard Worker     matri = matriScale;
104*3ac0a46fSAndroid Build Coastguard Worker   }
105*3ac0a46fSAndroid Build Coastguard Worker 
106*3ac0a46fSAndroid Build Coastguard Worker   CFX_GraphStateData data;
107*3ac0a46fSAndroid Build Coastguard Worker   for (int32_t x = 0; x < m_inputWidth; x++) {
108*3ac0a46fSAndroid Build Coastguard Worker     for (int32_t y = 0; y < m_inputHeight; y++) {
109*3ac0a46fSAndroid Build Coastguard Worker       if (m_output->Get(x, y)) {
110*3ac0a46fSAndroid Build Coastguard Worker         // In the output, each module is shifted by 1 due to the one module
111*3ac0a46fSAndroid Build Coastguard Worker         // padding added to create quiet areas.
112*3ac0a46fSAndroid Build Coastguard Worker         int start_x_output = x + 1;
113*3ac0a46fSAndroid Build Coastguard Worker         int end_x_output = x + 2;
114*3ac0a46fSAndroid Build Coastguard Worker         int start_y_output = y + 1;
115*3ac0a46fSAndroid Build Coastguard Worker         int end_y_output = y + 2;
116*3ac0a46fSAndroid Build Coastguard Worker 
117*3ac0a46fSAndroid Build Coastguard Worker         CFX_Path rect;
118*3ac0a46fSAndroid Build Coastguard Worker         rect.AppendRect(leftPos + start_x_output * m_multiX,
119*3ac0a46fSAndroid Build Coastguard Worker                         topPos + start_y_output * m_multiY,
120*3ac0a46fSAndroid Build Coastguard Worker                         leftPos + end_x_output * m_multiX,
121*3ac0a46fSAndroid Build Coastguard Worker                         topPos + end_y_output * m_multiY);
122*3ac0a46fSAndroid Build Coastguard Worker         device->DrawPath(rect, &matri, &data, kBarColor, 0,
123*3ac0a46fSAndroid Build Coastguard Worker                          CFX_FillRenderOptions::WindingOptions());
124*3ac0a46fSAndroid Build Coastguard Worker       }
125*3ac0a46fSAndroid Build Coastguard Worker     }
126*3ac0a46fSAndroid Build Coastguard Worker   }
127*3ac0a46fSAndroid Build Coastguard Worker }
128