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