fx_codec.cpp revision ee451cb395940862dad63c85adfe8f2fd55e864c
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"
9CCodec_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}
19CCodec_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}
29void CCodec_ModuleMgr::InitJbig2Decoder()
30{
31}
32void CCodec_ModuleMgr::InitJpxDecoder()
33{
34}
35void CCodec_ModuleMgr::InitIccDecoder()
36{
37}
38CCodec_ScanlineDecoder::CCodec_ScanlineDecoder()
39{
40    m_NextLine = -1;
41    m_pDataCache = NULL;
42    m_pLastScanline = NULL;
43}
44CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder()
45{
46    if (m_pDataCache) {
47        FX_Free(m_pDataCache);
48    }
49}
50FX_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}
72FX_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}
94FX_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}
106void 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}
131FX_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}
136extern "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}
240FX_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}
245CCodec_ModuleMgr* CCodec_ModuleMgr::Create()
246{
247    return FX_NEW CCodec_ModuleMgr;
248}
249void CCodec_ModuleMgr::Destroy()
250{
251    delete this;
252}
253class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder
254{
255public:
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);
259    virtual void		v_DownScale(int dest_width, int dest_height) {}
260    virtual FX_BOOL		v_Rewind();
261    virtual FX_LPBYTE	v_GetNextLine();
262    virtual FX_DWORD	GetSrcOffset()
263    {
264        return m_SrcOffset;
265    }
266protected:
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};
279CCodec_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}
289CCodec_RLScanlineDecoder::~CCodec_RLScanlineDecoder()
290{
291    if (m_pScanline) {
292        FX_Free(m_pScanline);
293    }
294}
295FX_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}
324FX_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}
343FX_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}
351FX_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}
397void 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}
406void 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}
435ICodec_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