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