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 "../../../include/fxcodec/fx_codec.h"
8 #include "codec_int.h"
CCodec_ModuleMgr()9 CCodec_ModuleMgr::CCodec_ModuleMgr()
10 {
11 m_pBasicModule = FX_NEW CCodec_BasicModule;
12 m_pFaxModule = FX_NEW CCodec_FaxModule;
13 m_pJpegModule = FX_NEW CCodec_JpegModule;
14 m_pJpxModule = FX_NEW CCodec_JpxModule;
15 m_pJbig2Module = FX_NEW CCodec_Jbig2Module;
16 m_pIccModule = FX_NEW CCodec_IccModule;
17 m_pFlateModule = FX_NEW CCodec_FlateModule;
18 }
~CCodec_ModuleMgr()19 CCodec_ModuleMgr::~CCodec_ModuleMgr()
20 {
21 delete m_pBasicModule;
22 delete m_pFaxModule;
23 delete m_pJpegModule;
24 delete m_pFlateModule;
25 delete m_pJpxModule;
26 delete m_pJbig2Module;
27 delete m_pIccModule;
28 }
InitJbig2Decoder()29 void CCodec_ModuleMgr::InitJbig2Decoder()
30 {
31 }
InitJpxDecoder()32 void CCodec_ModuleMgr::InitJpxDecoder()
33 {
34 }
InitIccDecoder()35 void CCodec_ModuleMgr::InitIccDecoder()
36 {
37 }
CCodec_ScanlineDecoder()38 CCodec_ScanlineDecoder::CCodec_ScanlineDecoder()
39 {
40 m_NextLine = -1;
41 m_pDataCache = NULL;
42 m_pLastScanline = NULL;
43 }
~CCodec_ScanlineDecoder()44 CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder()
45 {
46 if (m_pDataCache) {
47 FX_Free(m_pDataCache);
48 }
49 }
GetScanline(int line)50 FX_LPBYTE CCodec_ScanlineDecoder::GetScanline(int line)
51 {
52 if (m_pDataCache && line < m_pDataCache->m_nCachedLines) {
53 return &m_pDataCache->m_Data + line * m_Pitch;
54 }
55 if (m_NextLine == line + 1) {
56 return m_pLastScanline;
57 }
58 if (m_NextLine < 0 || m_NextLine > line) {
59 if (!v_Rewind()) {
60 return NULL;
61 }
62 m_NextLine = 0;
63 }
64 while (m_NextLine < line) {
65 ReadNextLine();
66 m_NextLine ++;
67 }
68 m_pLastScanline = ReadNextLine();
69 m_NextLine ++;
70 return m_pLastScanline;
71 }
SkipToScanline(int line,IFX_Pause * pPause)72 FX_BOOL CCodec_ScanlineDecoder::SkipToScanline(int line, IFX_Pause* pPause)
73 {
74 if (m_pDataCache && line < m_pDataCache->m_nCachedLines) {
75 return FALSE;
76 }
77 if (m_NextLine == line || m_NextLine == line + 1) {
78 return FALSE;
79 }
80 if (m_NextLine < 0 || m_NextLine > line) {
81 v_Rewind();
82 m_NextLine = 0;
83 }
84 m_pLastScanline = NULL;
85 while (m_NextLine < line) {
86 m_pLastScanline = ReadNextLine();
87 m_NextLine ++;
88 if (pPause && pPause->NeedToPauseNow()) {
89 return TRUE;
90 }
91 }
92 return FALSE;
93 }
ReadNextLine()94 FX_LPBYTE CCodec_ScanlineDecoder::ReadNextLine()
95 {
96 FX_LPBYTE pLine = v_GetNextLine();
97 if (pLine == NULL) {
98 return NULL;
99 }
100 if (m_pDataCache && m_NextLine == m_pDataCache->m_nCachedLines) {
101 FXSYS_memcpy32(&m_pDataCache->m_Data + m_NextLine * m_Pitch, pLine, m_Pitch);
102 m_pDataCache->m_nCachedLines ++;
103 }
104 return pLine;
105 }
DownScale(int dest_width,int dest_height)106 void CCodec_ScanlineDecoder::DownScale(int dest_width, int dest_height)
107 {
108 if (dest_width < 0) {
109 dest_width = -dest_width;
110 }
111 if (dest_height < 0) {
112 dest_height = -dest_height;
113 }
114 v_DownScale(dest_width, dest_height);
115 if (m_pDataCache) {
116 if (m_pDataCache->m_Height == m_OutputHeight && m_pDataCache->m_Width == m_OutputWidth) {
117 return;
118 }
119 FX_Free(m_pDataCache);
120 m_pDataCache = NULL;
121 }
122 m_pDataCache = (CCodec_ImageDataCache*)FXMEM_DefaultAlloc(
123 sizeof(CCodec_ImageDataCache) + m_Pitch * m_OutputHeight, FXMEM_NONLEAVE);
124 if (m_pDataCache == NULL) {
125 return;
126 }
127 m_pDataCache->m_Height = m_OutputHeight;
128 m_pDataCache->m_Width = m_OutputWidth;
129 m_pDataCache->m_nCachedLines = 0;
130 }
RunLengthEncode(const FX_BYTE * src_buf,FX_DWORD src_size,FX_LPBYTE & dest_buf,FX_DWORD & dest_size)131 FX_BOOL CCodec_BasicModule::RunLengthEncode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf,
132 FX_DWORD& dest_size)
133 {
134 return FALSE;
135 }
FXstrtod(const char * nptr,char ** endptr)136 extern "C" double FXstrtod(const char* nptr, char** endptr)
137 {
138 double ret = 0.0;
139 const char* ptr = nptr;
140 const char* exp_ptr = NULL;
141 int e_number = 0,
142 e_signal = 0,
143 e_point = 0,
144 is_negative = 0;
145 int exp_ret = 0, exp_sig = 1,
146 fra_ret = 0, fra_count = 0, fra_base = 1;
147 if(nptr == NULL) {
148 return 0.0;
149 }
150 for (;; ptr++) {
151 if(!e_number && !e_point && (*ptr == '\t' || *ptr == ' ')) {
152 continue;
153 }
154 if(*ptr >= '0' && *ptr <= '9') {
155 if(!e_number) {
156 e_number = 1;
157 }
158 if(!e_point) {
159 ret *= 10;
160 ret += (*ptr - '0');
161 } else {
162 fra_count++;
163 fra_ret *= 10;
164 fra_ret += (*ptr - '0');
165 }
166 continue;
167 }
168 if(!e_point && *ptr == '.') {
169 e_point = 1;
170 continue;
171 }
172 if(!e_number && !e_point && !e_signal) {
173 switch(*ptr) {
174 case '-':
175 is_negative = 1;
176 case '+':
177 e_signal = 1;
178 continue;
179 }
180 }
181 if(e_number && (*ptr == 'e' || *ptr == 'E')) {
182 #define EXPONENT_DETECT(ptr) \
183 for(;;ptr++){ \
184 if(*ptr < '0' || *ptr > '9'){ \
185 if(endptr) *endptr = (char*)ptr; \
186 break; \
187 }else{ \
188 exp_ret *= 10; \
189 exp_ret += (*ptr - '0'); \
190 continue; \
191 } \
192 }
193 exp_ptr = ptr++;
194 if(*ptr == '+' || *ptr == '-') {
195 exp_sig = (*ptr++ == '+') ? 1 : -1;
196 if(*ptr < '0' || *ptr > '9') {
197 if(endptr) {
198 *endptr = (char*)exp_ptr;
199 }
200 break;
201 }
202 EXPONENT_DETECT(ptr);
203 } else if(*ptr >= '0' && *ptr <= '9') {
204 EXPONENT_DETECT(ptr);
205 } else {
206 if(endptr) {
207 *endptr = (char*)exp_ptr;
208 }
209 break;
210 }
211 #undef EXPONENT_DETECT
212 break;
213 }
214 if(ptr != nptr && !e_number) {
215 if(endptr) {
216 *endptr = (char*)nptr;
217 }
218 break;
219 }
220 if(endptr) {
221 *endptr = (char*)ptr;
222 }
223 break;
224 }
225 while(fra_count--) {
226 fra_base *= 10;
227 }
228 ret += (double)fra_ret / (double)fra_base;
229 if(exp_sig == 1) {
230 while(exp_ret--) {
231 ret *= 10.0;
232 }
233 } else {
234 while(exp_ret--) {
235 ret /= 10.0;
236 }
237 }
238 return is_negative ? -ret : ret;
239 }
A85Encode(const FX_BYTE * src_buf,FX_DWORD src_size,FX_LPBYTE & dest_buf,FX_DWORD & dest_size)240 FX_BOOL CCodec_BasicModule::A85Encode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf,
241 FX_DWORD& dest_size)
242 {
243 return FALSE;
244 }
Create()245 CCodec_ModuleMgr* CCodec_ModuleMgr::Create()
246 {
247 return FX_NEW CCodec_ModuleMgr;
248 }
Destroy()249 void CCodec_ModuleMgr::Destroy()
250 {
251 delete this;
252 }
253 class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder
254 {
255 public:
256 CCodec_RLScanlineDecoder();
257 virtual ~CCodec_RLScanlineDecoder();
258 FX_BOOL Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc);
v_DownScale(int dest_width,int dest_height)259 virtual void v_DownScale(int dest_width, int dest_height) {}
260 virtual FX_BOOL v_Rewind();
261 virtual FX_LPBYTE v_GetNextLine();
GetSrcOffset()262 virtual FX_DWORD GetSrcOffset()
263 {
264 return m_SrcOffset;
265 }
266 protected:
267 FX_BOOL CheckDestSize();
268 void GetNextOperator();
269 void UpdateOperator(FX_BYTE used_bytes);
270
271 FX_LPBYTE m_pScanline;
272 FX_LPCBYTE m_pSrcBuf;
273 FX_DWORD m_SrcSize;
274 FX_DWORD m_dwLineBytes;
275 FX_DWORD m_SrcOffset;
276 FX_BOOL m_bEOD;
277 FX_BYTE m_Operator;
278 };
CCodec_RLScanlineDecoder()279 CCodec_RLScanlineDecoder::CCodec_RLScanlineDecoder()
280 : m_pScanline(NULL)
281 , m_pSrcBuf(NULL)
282 , m_SrcSize(0)
283 , m_dwLineBytes(0)
284 , m_SrcOffset(0)
285 , m_bEOD(FALSE)
286 , m_Operator(0)
287 {
288 }
~CCodec_RLScanlineDecoder()289 CCodec_RLScanlineDecoder::~CCodec_RLScanlineDecoder()
290 {
291 if (m_pScanline) {
292 FX_Free(m_pScanline);
293 }
294 }
CheckDestSize()295 FX_BOOL CCodec_RLScanlineDecoder::CheckDestSize()
296 {
297 FX_DWORD i = 0;
298 FX_DWORD old_size = 0;
299 FX_DWORD dest_size = 0;
300 while (i < m_SrcSize) {
301 if (m_pSrcBuf[i] < 128) {
302 old_size = dest_size;
303 dest_size += m_pSrcBuf[i] + 1;
304 if (dest_size < old_size) {
305 return FALSE;
306 }
307 i += m_pSrcBuf[i] + 2;
308 } else if (m_pSrcBuf[i] > 128) {
309 old_size = dest_size;
310 dest_size += 257 - m_pSrcBuf[i];
311 if (dest_size < old_size) {
312 return FALSE;
313 }
314 i += 2;
315 } else {
316 break;
317 }
318 }
319 if (((FX_DWORD)m_OrigWidth * m_nComps * m_bpc * m_OrigHeight + 7) / 8 > dest_size) {
320 return FALSE;
321 }
322 return TRUE;
323 }
Create(FX_LPCBYTE src_buf,FX_DWORD src_size,int width,int height,int nComps,int bpc)324 FX_BOOL CCodec_RLScanlineDecoder::Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc)
325 {
326 m_pSrcBuf = src_buf;
327 m_SrcSize = src_size;
328 m_OutputWidth = m_OrigWidth = width;
329 m_OutputHeight = m_OrigHeight = height;
330 m_nComps = nComps;
331 m_bpc = bpc;
332 m_bColorTransformed = FALSE;
333 m_DownScale = 1;
334 m_Pitch = (width * nComps * bpc + 31) / 32 * 4;
335 m_dwLineBytes = (width * nComps * bpc + 7) / 8;
336 m_pScanline = FX_Alloc(FX_BYTE, m_Pitch);
337 if (m_pScanline == NULL) {
338 return FALSE;
339 }
340 FXSYS_memset32(m_pScanline, 0, m_Pitch);
341 return CheckDestSize();
342 }
v_Rewind()343 FX_BOOL CCodec_RLScanlineDecoder::v_Rewind()
344 {
345 FXSYS_memset32(m_pScanline, 0, m_Pitch);
346 m_SrcOffset = 0;
347 m_bEOD = FALSE;
348 m_Operator = 0;
349 return TRUE;
350 }
v_GetNextLine()351 FX_LPBYTE CCodec_RLScanlineDecoder::v_GetNextLine()
352 {
353 if (m_SrcOffset == 0) {
354 GetNextOperator();
355 } else {
356 if (m_bEOD) {
357 return NULL;
358 }
359 }
360 FXSYS_memset32(m_pScanline, 0, m_Pitch);
361 FX_DWORD col_pos = 0;
362 FX_BOOL eol = FALSE;
363 while (m_SrcOffset < m_SrcSize && !eol) {
364 if (m_Operator < 128) {
365 FX_DWORD copy_len = m_Operator + 1;
366 if (col_pos + copy_len >= m_dwLineBytes) {
367 copy_len = m_dwLineBytes - col_pos;
368 eol = TRUE;
369 }
370 if (copy_len >= m_SrcSize - m_SrcOffset) {
371 copy_len = m_SrcSize - m_SrcOffset;
372 m_bEOD = TRUE;
373 }
374 FXSYS_memcpy32(m_pScanline + col_pos, m_pSrcBuf + m_SrcOffset, copy_len);
375 col_pos += copy_len;
376 UpdateOperator((FX_BYTE)copy_len);
377 } else if (m_Operator > 128) {
378 int fill = 0;
379 if (m_SrcOffset - 1 < m_SrcSize - 1) {
380 fill = m_pSrcBuf[m_SrcOffset];
381 }
382 FX_DWORD duplicate_len = 257 - m_Operator;
383 if (col_pos + duplicate_len >= m_dwLineBytes) {
384 duplicate_len = m_dwLineBytes - col_pos;
385 eol = TRUE;
386 }
387 FXSYS_memset8(m_pScanline + col_pos, fill, duplicate_len);
388 col_pos += duplicate_len;
389 UpdateOperator((FX_BYTE)duplicate_len);
390 } else {
391 m_bEOD = TRUE;
392 break;
393 }
394 }
395 return m_pScanline;
396 }
GetNextOperator()397 void CCodec_RLScanlineDecoder::GetNextOperator()
398 {
399 if (m_SrcOffset >= m_SrcSize) {
400 m_Operator = 128;
401 return;
402 }
403 m_Operator = m_pSrcBuf[m_SrcOffset];
404 m_SrcOffset ++;
405 }
UpdateOperator(FX_BYTE used_bytes)406 void CCodec_RLScanlineDecoder::UpdateOperator(FX_BYTE used_bytes)
407 {
408 if (used_bytes == 0) {
409 return;
410 }
411 if (m_Operator < 128) {
412 FXSYS_assert((FX_DWORD)m_Operator + 1 >= used_bytes);
413 if (used_bytes == m_Operator + 1) {
414 m_SrcOffset += used_bytes;
415 GetNextOperator();
416 return;
417 }
418 m_Operator -= used_bytes;
419 m_SrcOffset += used_bytes;
420 if (m_SrcOffset >= m_SrcSize) {
421 m_Operator = 128;
422 }
423 return;
424 }
425 FX_BYTE count = 257 - m_Operator;
426 FXSYS_assert((FX_DWORD)count >= used_bytes);
427 if (used_bytes == count) {
428 m_SrcOffset ++;
429 GetNextOperator();
430 return;
431 }
432 count -= used_bytes;
433 m_Operator = 257 - count;
434 }
CreateRunLengthDecoder(FX_LPCBYTE src_buf,FX_DWORD src_size,int width,int height,int nComps,int bpc)435 ICodec_ScanlineDecoder* CCodec_BasicModule::CreateRunLengthDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
436 int nComps, int bpc)
437 {
438 CCodec_RLScanlineDecoder* pRLScanlineDecoder = FX_NEW CCodec_RLScanlineDecoder;
439 if (pRLScanlineDecoder == NULL) {
440 return NULL;
441 }
442 if (!pRLScanlineDecoder->Create(src_buf, src_size, width, height, nComps, bpc)) {
443 delete pRLScanlineDecoder;
444 return NULL;
445 }
446 return pRLScanlineDecoder;
447 }
448