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