blob: bff37dfb89a31f4689f7a9d4cacd6e21a6335a37 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// 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
7#include <algorithm>
8
dsinclair74a34fc2016-09-29 16:41:42 -07009#include "core/fxge/cfx_graphstatedata.h"
10#include "core/fxge/cfx_pathdata.h"
11#include "core/fxge/cfx_renderdevice.h"
Dan Sinclaire7786682017-03-29 15:18:41 -040012#include "fxbarcode/BC_TwoDimWriter.h"
13#include "fxbarcode/BC_Writer.h"
14#include "fxbarcode/common/BC_CommonBitMatrix.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040015#include "third_party/base/numerics/safe_math.h"
tsepeza9caab92016-12-14 05:57:10 -080016#include "third_party/base/ptr_util.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040017
tsepezd19e9122016-11-02 15:43:18 -070018CBC_TwoDimWriter::CBC_TwoDimWriter() : m_iCorrectLevel(1), m_bFixedSize(true) {}
weilie76203d2016-08-09 13:45:03 -070019
20CBC_TwoDimWriter::~CBC_TwoDimWriter() {}
21
weilie76203d2016-08-09 13:45:03 -070022int32_t CBC_TwoDimWriter::GetErrorCorrectionLevel() const {
weili29b8ad02016-06-14 18:20:04 -070023 return m_iCorrectLevel;
24}
25
Lei Zhang1badb852017-04-20 15:58:56 -070026bool CBC_TwoDimWriter::RenderResult(uint8_t* code,
Dan Sinclair1770c022016-03-14 14:14:16 -040027 int32_t codeWidth,
Lei Zhang1badb852017-04-20 15:58:56 -070028 int32_t codeHeight) {
Henrique Nakashimadc2bb9a2018-08-21 19:50:17 +000029 m_inputWidth = codeWidth;
30 m_inputHeight = codeHeight;
31 int32_t tempWidth = m_inputWidth + 2;
32 int32_t tempHeight = m_inputHeight + 2;
Dan Sinclair05df0752017-03-14 14:43:42 -040033 float moduleHSize = std::min(m_ModuleWidth, m_ModuleHeight);
Dan Sinclair1770c022016-03-14 14:14:16 -040034 moduleHSize = std::min(moduleHSize, 8.0f);
35 moduleHSize = std::max(moduleHSize, 1.0f);
36 pdfium::base::CheckedNumeric<int32_t> scaledWidth = tempWidth;
37 pdfium::base::CheckedNumeric<int32_t> scaledHeight = tempHeight;
38 scaledWidth *= moduleHSize;
39 scaledHeight *= moduleHSize;
Henrique Nakashimadc2bb9a2018-08-21 19:50:17 +000040 m_outputWidth = scaledWidth.ValueOrDie();
41 m_outputHeight = scaledHeight.ValueOrDie();
Dan Sinclair1770c022016-03-14 14:14:16 -040042
Dan Sinclair1770c022016-03-14 14:14:16 -040043 if (m_bFixedSize) {
Henrique Nakashimadc2bb9a2018-08-21 19:50:17 +000044 if (m_Width < m_outputWidth || m_Height < m_outputHeight) {
Lei Zhang1badb852017-04-20 15:58:56 -070045 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040046 }
47 } else {
Henrique Nakashimadc2bb9a2018-08-21 19:50:17 +000048 if (m_Width > m_outputWidth || m_Height > m_outputHeight) {
49 int32_t width_factor = static_cast<int32_t>(
50 floor(static_cast<float>(m_Width) / m_outputWidth));
51 int32_t height_factor = static_cast<int32_t>(
52 floor(static_cast<float>(m_Height) / m_outputHeight));
53 width_factor = std::max(width_factor, 1);
54 height_factor = std::max(height_factor, 1);
55
56 m_outputWidth *= width_factor;
57 m_outputHeight *= height_factor;
Dan Sinclair1770c022016-03-14 14:14:16 -040058 }
59 }
Henrique Nakashimadc2bb9a2018-08-21 19:50:17 +000060 m_multiX =
61 static_cast<int32_t>(ceil(static_cast<float>(m_outputWidth) / tempWidth));
62 m_multiY = static_cast<int32_t>(
63 ceil(static_cast<float>(m_outputHeight) / tempHeight));
Dan Sinclair1770c022016-03-14 14:14:16 -040064 if (m_bFixedSize) {
Henrique Nakashimadc2bb9a2018-08-21 19:50:17 +000065 m_multiX = std::min(m_multiX, m_multiY);
66 m_multiY = m_multiX;
Dan Sinclair1770c022016-03-14 14:14:16 -040067 }
Henrique Nakashimadc2bb9a2018-08-21 19:50:17 +000068
69 m_leftPadding = std::max((m_Width - m_outputWidth) / 2, 0);
70 m_topPadding = std::max((m_Height - m_outputHeight) / 2, 0);
71
tsepeza9caab92016-12-14 05:57:10 -080072 m_output = pdfium::MakeUnique<CBC_CommonBitMatrix>();
Henrique Nakashimadc2bb9a2018-08-21 19:50:17 +000073 m_output->Init(m_inputWidth, m_inputHeight);
74
75 for (int32_t y = 0; y < m_inputHeight; ++y) {
76 for (int32_t x = 0; x < m_inputWidth; ++x) {
77 if (code[x + y * m_inputWidth] == 1)
78 m_output->Set(x, y);
Dan Sinclair1770c022016-03-14 14:14:16 -040079 }
80 }
Lei Zhang1badb852017-04-20 15:58:56 -070081 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -040082}
Henrique Nakashimace6a1cc2018-08-23 19:02:30 +000083
84void CBC_TwoDimWriter::RenderDeviceResult(CFX_RenderDevice* device,
85 const CFX_Matrix* matrix) {
86 ASSERT(m_output);
87
88 CFX_GraphStateData stateData;
89 CFX_PathData path;
90 path.AppendRect(0, 0, (float)m_Width, (float)m_Height);
91 device->DrawPath(&path, matrix, &stateData, m_backgroundColor,
92 m_backgroundColor, FXFILL_ALTERNATE);
93 int32_t leftPos = m_leftPadding;
94 int32_t topPos = m_topPadding;
95
96 CFX_Matrix matri = *matrix;
97 if (m_Width < m_outputWidth && m_Height < m_outputHeight) {
98 CFX_Matrix matriScale(static_cast<float>(m_Width) / m_outputWidth, 0.0, 0.0,
99 static_cast<float>(m_Height) / m_outputHeight, 0.0,
100 0.0);
101 matriScale.Concat(*matrix);
102 matri = matriScale;
103 }
104
105 CFX_GraphStateData data;
106 for (int32_t x = 0; x < m_inputWidth; x++) {
107 for (int32_t y = 0; y < m_inputHeight; y++) {
108 if (m_output->Get(x, y)) {
109 // In the output, each module is shifted by 1 due to the one module
110 // padding added to create quiet areas.
111 int start_x_output = x + 1;
112 int end_x_output = x + 2;
113 int start_y_output = y + 1;
114 int end_y_output = y + 2;
115
116 CFX_PathData rect;
117 rect.AppendRect(leftPos + start_x_output * m_multiX,
118 topPos + start_y_output * m_multiY,
119 leftPos + end_x_output * m_multiX,
120 topPos + end_y_output * m_multiY);
121 device->DrawPath(&rect, &matri, &data, m_barColor, 0, FXFILL_WINDING);
122 }
123 }
124 }
125}