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