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
7 #include "core/fxcodec/include/fx_codec.h"
8
9 #include <cmath>
10 #include <memory>
11 #include <utility>
12
13 #include "core/fxcodec/codec/codec_int.h"
14 #include "core/fxcrt/include/fx_ext.h"
15 #include "core/fxcrt/include/fx_safe_types.h"
16 #include "third_party/base/logging.h"
17
CCodec_ModuleMgr()18 CCodec_ModuleMgr::CCodec_ModuleMgr()
19 : m_pBasicModule(new CCodec_BasicModule),
20 m_pFaxModule(new CCodec_FaxModule),
21 m_pJpegModule(new CCodec_JpegModule),
22 m_pJpxModule(new CCodec_JpxModule),
23 m_pJbig2Module(new CCodec_Jbig2Module),
24 m_pIccModule(new CCodec_IccModule),
25 #ifdef PDF_ENABLE_XFA
26 m_pPngModule(new CCodec_PngModule),
27 m_pGifModule(new CCodec_GifModule),
28 m_pBmpModule(new CCodec_BmpModule),
29 m_pTiffModule(new CCodec_TiffModule),
30 #endif // PDF_ENABLE_XFA
31 m_pFlateModule(new CCodec_FlateModule) {
32 }
33
~CCodec_ModuleMgr()34 CCodec_ModuleMgr::~CCodec_ModuleMgr() {}
35
CCodec_ScanlineDecoder()36 CCodec_ScanlineDecoder::CCodec_ScanlineDecoder()
37 : m_NextLine(-1), m_pLastScanline(nullptr) {}
38
~CCodec_ScanlineDecoder()39 CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder() {}
40
GetScanline(int line)41 const uint8_t* CCodec_ScanlineDecoder::GetScanline(int line) {
42 if (m_NextLine == line + 1)
43 return m_pLastScanline;
44
45 if (m_NextLine < 0 || m_NextLine > line) {
46 if (!v_Rewind())
47 return nullptr;
48 m_NextLine = 0;
49 }
50 while (m_NextLine < line) {
51 ReadNextLine();
52 m_NextLine++;
53 }
54 m_pLastScanline = ReadNextLine();
55 m_NextLine++;
56 return m_pLastScanline;
57 }
58
SkipToScanline(int line,IFX_Pause * pPause)59 FX_BOOL CCodec_ScanlineDecoder::SkipToScanline(int line, IFX_Pause* pPause) {
60 if (m_NextLine == line || m_NextLine == line + 1)
61 return FALSE;
62
63 if (m_NextLine < 0 || m_NextLine > line) {
64 v_Rewind();
65 m_NextLine = 0;
66 }
67 m_pLastScanline = nullptr;
68 while (m_NextLine < line) {
69 m_pLastScanline = ReadNextLine();
70 m_NextLine++;
71 if (pPause && pPause->NeedToPauseNow()) {
72 return TRUE;
73 }
74 }
75 return FALSE;
76 }
77
ReadNextLine()78 uint8_t* CCodec_ScanlineDecoder::ReadNextLine() {
79 return v_GetNextLine();
80 }
81
82 #ifdef PDF_ENABLE_XFA
CFX_DIBAttribute()83 CFX_DIBAttribute::CFX_DIBAttribute()
84 : m_nXDPI(-1),
85 m_nYDPI(-1),
86 m_fAspectRatio(-1.0f),
87 m_wDPIUnit(0),
88 m_nGifLeft(0),
89 m_nGifTop(0),
90 m_pGifLocalPalette(nullptr),
91 m_nGifLocalPalNum(0),
92 m_nBmpCompressType(0) {
93 FXSYS_memset(m_strTime, 0, sizeof(m_strTime));
94 }
~CFX_DIBAttribute()95 CFX_DIBAttribute::~CFX_DIBAttribute() {
96 for (const auto& pair : m_Exif)
97 FX_Free(pair.second);
98 }
99 #endif // PDF_ENABLE_XFA
100
101 class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder {
102 public:
103 CCodec_RLScanlineDecoder();
104 ~CCodec_RLScanlineDecoder() override;
105
106 FX_BOOL Create(const uint8_t* src_buf,
107 uint32_t src_size,
108 int width,
109 int height,
110 int nComps,
111 int bpc);
112
113 // CCodec_ScanlineDecoder
114 FX_BOOL v_Rewind() override;
115 uint8_t* v_GetNextLine() override;
GetSrcOffset()116 uint32_t GetSrcOffset() override { return m_SrcOffset; }
117
118 protected:
119 FX_BOOL CheckDestSize();
120 void GetNextOperator();
121 void UpdateOperator(uint8_t used_bytes);
122
123 uint8_t* m_pScanline;
124 const uint8_t* m_pSrcBuf;
125 uint32_t m_SrcSize;
126 uint32_t m_dwLineBytes;
127 uint32_t m_SrcOffset;
128 FX_BOOL m_bEOD;
129 uint8_t m_Operator;
130 };
CCodec_RLScanlineDecoder()131 CCodec_RLScanlineDecoder::CCodec_RLScanlineDecoder()
132 : m_pScanline(nullptr),
133 m_pSrcBuf(nullptr),
134 m_SrcSize(0),
135 m_dwLineBytes(0),
136 m_SrcOffset(0),
137 m_bEOD(FALSE),
138 m_Operator(0) {}
~CCodec_RLScanlineDecoder()139 CCodec_RLScanlineDecoder::~CCodec_RLScanlineDecoder() {
140 FX_Free(m_pScanline);
141 }
CheckDestSize()142 FX_BOOL CCodec_RLScanlineDecoder::CheckDestSize() {
143 uint32_t i = 0;
144 uint32_t old_size = 0;
145 uint32_t dest_size = 0;
146 while (i < m_SrcSize) {
147 if (m_pSrcBuf[i] < 128) {
148 old_size = dest_size;
149 dest_size += m_pSrcBuf[i] + 1;
150 if (dest_size < old_size) {
151 return FALSE;
152 }
153 i += m_pSrcBuf[i] + 2;
154 } else if (m_pSrcBuf[i] > 128) {
155 old_size = dest_size;
156 dest_size += 257 - m_pSrcBuf[i];
157 if (dest_size < old_size) {
158 return FALSE;
159 }
160 i += 2;
161 } else {
162 break;
163 }
164 }
165 if (((uint32_t)m_OrigWidth * m_nComps * m_bpc * m_OrigHeight + 7) / 8 >
166 dest_size) {
167 return FALSE;
168 }
169 return TRUE;
170 }
Create(const uint8_t * src_buf,uint32_t src_size,int width,int height,int nComps,int bpc)171 FX_BOOL CCodec_RLScanlineDecoder::Create(const uint8_t* src_buf,
172 uint32_t src_size,
173 int width,
174 int height,
175 int nComps,
176 int bpc) {
177 m_pSrcBuf = src_buf;
178 m_SrcSize = src_size;
179 m_OutputWidth = m_OrigWidth = width;
180 m_OutputHeight = m_OrigHeight = height;
181 m_nComps = nComps;
182 m_bpc = bpc;
183 // Aligning the pitch to 4 bytes requires an integer overflow check.
184 FX_SAFE_UINT32 pitch = width;
185 pitch *= nComps;
186 pitch *= bpc;
187 pitch += 31;
188 pitch /= 32;
189 pitch *= 4;
190 if (!pitch.IsValid()) {
191 return FALSE;
192 }
193 m_Pitch = pitch.ValueOrDie();
194 // Overflow should already have been checked before this is called.
195 m_dwLineBytes = (static_cast<uint32_t>(width) * nComps * bpc + 7) / 8;
196 m_pScanline = FX_Alloc(uint8_t, m_Pitch);
197 return CheckDestSize();
198 }
v_Rewind()199 FX_BOOL CCodec_RLScanlineDecoder::v_Rewind() {
200 FXSYS_memset(m_pScanline, 0, m_Pitch);
201 m_SrcOffset = 0;
202 m_bEOD = FALSE;
203 m_Operator = 0;
204 return TRUE;
205 }
v_GetNextLine()206 uint8_t* CCodec_RLScanlineDecoder::v_GetNextLine() {
207 if (m_SrcOffset == 0) {
208 GetNextOperator();
209 } else {
210 if (m_bEOD) {
211 return nullptr;
212 }
213 }
214 FXSYS_memset(m_pScanline, 0, m_Pitch);
215 uint32_t col_pos = 0;
216 FX_BOOL eol = FALSE;
217 while (m_SrcOffset < m_SrcSize && !eol) {
218 if (m_Operator < 128) {
219 uint32_t copy_len = m_Operator + 1;
220 if (col_pos + copy_len >= m_dwLineBytes) {
221 copy_len = m_dwLineBytes - col_pos;
222 eol = TRUE;
223 }
224 if (copy_len >= m_SrcSize - m_SrcOffset) {
225 copy_len = m_SrcSize - m_SrcOffset;
226 m_bEOD = TRUE;
227 }
228 FXSYS_memcpy(m_pScanline + col_pos, m_pSrcBuf + m_SrcOffset, copy_len);
229 col_pos += copy_len;
230 UpdateOperator((uint8_t)copy_len);
231 } else if (m_Operator > 128) {
232 int fill = 0;
233 if (m_SrcOffset - 1 < m_SrcSize - 1) {
234 fill = m_pSrcBuf[m_SrcOffset];
235 }
236 uint32_t duplicate_len = 257 - m_Operator;
237 if (col_pos + duplicate_len >= m_dwLineBytes) {
238 duplicate_len = m_dwLineBytes - col_pos;
239 eol = TRUE;
240 }
241 FXSYS_memset(m_pScanline + col_pos, fill, duplicate_len);
242 col_pos += duplicate_len;
243 UpdateOperator((uint8_t)duplicate_len);
244 } else {
245 m_bEOD = TRUE;
246 break;
247 }
248 }
249 return m_pScanline;
250 }
GetNextOperator()251 void CCodec_RLScanlineDecoder::GetNextOperator() {
252 if (m_SrcOffset >= m_SrcSize) {
253 m_Operator = 128;
254 return;
255 }
256 m_Operator = m_pSrcBuf[m_SrcOffset];
257 m_SrcOffset++;
258 }
UpdateOperator(uint8_t used_bytes)259 void CCodec_RLScanlineDecoder::UpdateOperator(uint8_t used_bytes) {
260 if (used_bytes == 0) {
261 return;
262 }
263 if (m_Operator < 128) {
264 ASSERT((uint32_t)m_Operator + 1 >= used_bytes);
265 if (used_bytes == m_Operator + 1) {
266 m_SrcOffset += used_bytes;
267 GetNextOperator();
268 return;
269 }
270 m_Operator -= used_bytes;
271 m_SrcOffset += used_bytes;
272 if (m_SrcOffset >= m_SrcSize) {
273 m_Operator = 128;
274 }
275 return;
276 }
277 uint8_t count = 257 - m_Operator;
278 ASSERT((uint32_t)count >= used_bytes);
279 if (used_bytes == count) {
280 m_SrcOffset++;
281 GetNextOperator();
282 return;
283 }
284 count -= used_bytes;
285 m_Operator = 257 - count;
286 }
287
CreateRunLengthDecoder(const uint8_t * src_buf,uint32_t src_size,int width,int height,int nComps,int bpc)288 CCodec_ScanlineDecoder* CCodec_BasicModule::CreateRunLengthDecoder(
289 const uint8_t* src_buf,
290 uint32_t src_size,
291 int width,
292 int height,
293 int nComps,
294 int bpc) {
295 std::unique_ptr<CCodec_RLScanlineDecoder> pRLScanlineDecoder(
296 new CCodec_RLScanlineDecoder);
297 if (!pRLScanlineDecoder->Create(src_buf, src_size, width, height, nComps,
298 bpc)) {
299 return nullptr;
300 }
301
302 return pRLScanlineDecoder.release();
303 }
304