Use stdint.h types throughout PDFium.
[pdfium.git] / core / src / fxcodec / codec / fx_codec_flate.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 "../../../../third_party/base/nonstd_unique_ptr.h"
8 #include "../../../include/fxcodec/fx_codec.h"
9 #include "../../fx_zlib.h"
10 #include "codec_int.h"
11
12 extern "C"
13 {
14     static void* my_alloc_func (void* opaque, unsigned int items, unsigned int size)
15     {
16         return FX_Alloc2D(uint8_t, items, size);
17     }
18     static void   my_free_func  (void* opaque, void* address)
19     {
20         FX_Free(address);
21     }
22     void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int),
23                             void (*free_func)(void*, void*))
24     {
25         z_stream* p = (z_stream*)alloc_func(0, 1, sizeof(z_stream));
26         if (p == NULL) {
27             return NULL;
28         }
29         FXSYS_memset32(p, 0, sizeof(z_stream));
30         p->zalloc = alloc_func;
31         p->zfree = free_func;
32         inflateInit(p);
33         return p;
34     }
35     void FPDFAPI_FlateInput(void* context, const unsigned char* src_buf, unsigned int src_size)
36     {
37         ((z_stream*)context)->next_in = (unsigned char*)src_buf;
38         ((z_stream*)context)->avail_in = src_size;
39     }
40     int FPDFAPI_FlateGetTotalOut(void* context)
41     {
42         return ((z_stream*)context)->total_out;
43     }
44     int FPDFAPI_FlateOutput(void* context, unsigned char* dest_buf, unsigned int dest_size)
45     {
46         ((z_stream*)context)->next_out = dest_buf;
47         ((z_stream*)context)->avail_out = dest_size;
48         unsigned int pre_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context);
49         int ret = inflate((z_stream*)context, Z_SYNC_FLUSH);
50         unsigned int post_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context);
51         unsigned int written = post_pos - pre_pos;
52         if (written < dest_size) {
53             FXSYS_memset8(dest_buf + written, '\0', dest_size - written);
54         }
55         return ret;
56     }
57     int FPDFAPI_FlateGetTotalIn(void* context)
58     {
59         return ((z_stream*)context)->total_in;
60     }
61     int FPDFAPI_FlateGetAvailOut(void* context)
62     {
63         return ((z_stream*)context)->avail_out;
64     }
65     int FPDFAPI_FlateGetAvailIn(void* context)
66     {
67         return ((z_stream*)context)->avail_in;
68     }
69     void FPDFAPI_FlateEnd(void* context)
70     {
71         inflateEnd((z_stream*)context);
72         ((z_stream*)context)->zfree(0, context);
73     }
74     void FPDFAPI_FlateCompress(unsigned char* dest_buf, unsigned long* dest_size, const unsigned char* src_buf, unsigned long src_size)
75     {
76         compress(dest_buf, dest_size, src_buf, src_size);
77     }
78 }
79 class CLZWDecoder 
80 {
81 public:
82     FX_BOOL Decode(FX_LPBYTE output, FX_DWORD& outlen, const uint8_t* input, FX_DWORD& size, FX_BOOL bEarlyChange);
83 private:
84     FX_DWORD    m_InPos;
85     FX_DWORD    m_OutPos;
86     FX_LPBYTE   m_pOutput;
87     const uint8_t*      m_pInput;
88     FX_BOOL             m_Early;
89     void                AddCode(FX_DWORD prefix_code, uint8_t append_char);
90     FX_DWORD    m_CodeArray[5021];
91     FX_DWORD    m_nCodes;
92     uint8_t             m_DecodeStack[4000];
93     FX_DWORD    m_StackLen;
94     void                DecodeString(FX_DWORD code);
95     int                 m_CodeLen;
96 };
97 void CLZWDecoder::AddCode(FX_DWORD prefix_code, uint8_t append_char)
98 {
99     if (m_nCodes + m_Early == 4094) {
100         return;
101     }
102     m_CodeArray[m_nCodes ++] = (prefix_code << 16) | append_char;
103     if (m_nCodes + m_Early == 512 - 258) {
104         m_CodeLen = 10;
105     } else if (m_nCodes + m_Early == 1024 - 258) {
106         m_CodeLen = 11;
107     } else if (m_nCodes + m_Early == 2048 - 258) {
108         m_CodeLen = 12;
109     }
110 }
111 void CLZWDecoder::DecodeString(FX_DWORD code)
112 {
113     while (1) {
114         int index = code - 258;
115         if (index < 0 || index >= (int)m_nCodes) {
116             break;
117         }
118         FX_DWORD data = m_CodeArray[index];
119         if (m_StackLen >= sizeof(m_DecodeStack)) {
120             return;
121         }
122         m_DecodeStack[m_StackLen++] = (uint8_t)data;
123         code = data >> 16;
124     }
125     if (m_StackLen >= sizeof(m_DecodeStack)) {
126         return;
127     }
128     m_DecodeStack[m_StackLen++] = (uint8_t)code;
129 }
130 int CLZWDecoder::Decode(FX_LPBYTE dest_buf, FX_DWORD& dest_size, const uint8_t* src_buf, FX_DWORD& src_size, FX_BOOL bEarlyChange)
131 {
132     m_CodeLen = 9;
133     m_InPos = 0;
134     m_OutPos = 0;
135     m_pInput = src_buf;
136     m_pOutput = dest_buf;
137     m_Early = bEarlyChange ? 1 : 0;
138     m_nCodes = 0;
139     FX_DWORD old_code = (FX_DWORD) - 1;
140     uint8_t last_char;
141     while (1) {
142         if (m_InPos + m_CodeLen > src_size * 8) {
143             break;
144         }
145         int byte_pos = m_InPos / 8;
146         int bit_pos = m_InPos % 8, bit_left = m_CodeLen;
147         FX_DWORD code = 0;
148         if (bit_pos) {
149             bit_left -= 8 - bit_pos;
150             code = (m_pInput[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_left;
151         }
152         if (bit_left < 8) {
153             code |= m_pInput[byte_pos] >> (8 - bit_left);
154         } else {
155             bit_left -= 8;
156             code |= m_pInput[byte_pos++] << bit_left;
157             if (bit_left) {
158                 code |= m_pInput[byte_pos] >> (8 - bit_left);
159             }
160         }
161         m_InPos += m_CodeLen;
162         if (code < 256) {
163             if (m_OutPos == dest_size) {
164                 return -5;
165             }
166             if (m_pOutput) {
167                 m_pOutput[m_OutPos] = (uint8_t)code;
168             }
169             m_OutPos ++;
170             last_char = (uint8_t)code;
171             if (old_code != (FX_DWORD) - 1) {
172                 AddCode(old_code, last_char);
173             }
174             old_code = code;
175         } else if (code == 256) {
176             m_CodeLen = 9;
177             m_nCodes = 0;
178             old_code = (FX_DWORD) - 1;
179         } else if (code == 257) {
180             break;
181         } else {
182             if (old_code == (FX_DWORD) - 1) {
183                 return 2;
184             }
185             m_StackLen = 0;
186             if (code >= m_nCodes + 258) {
187                 if (m_StackLen < sizeof(m_DecodeStack)) {
188                     m_DecodeStack[m_StackLen++] = last_char;
189                 }
190                 DecodeString(old_code);
191             } else {
192                 DecodeString(code);
193             }
194             if (m_OutPos + m_StackLen > dest_size) {
195                 return -5;
196             }
197             if (m_pOutput) {
198                 for (FX_DWORD i = 0; i < m_StackLen; i ++) {
199                     m_pOutput[m_OutPos + i] = m_DecodeStack[m_StackLen - i - 1];
200                 }
201             }
202             m_OutPos += m_StackLen;
203             last_char = m_DecodeStack[m_StackLen - 1];
204             if (old_code < 256) {
205                 AddCode(old_code, last_char);
206             } else if (old_code - 258 >= m_nCodes) {
207                 dest_size = m_OutPos;
208                 src_size = (m_InPos + 7) / 8;
209                 return 0;
210             } else {
211                 AddCode(old_code, last_char);
212             }
213             old_code = code;
214         }
215     }
216     dest_size = m_OutPos;
217     src_size = (m_InPos + 7) / 8;
218     return 0;
219 }
220 static uint8_t PaethPredictor(int a, int b, int c)
221 {
222     int p = a + b - c;
223     int pa = FXSYS_abs(p - a);
224     int pb = FXSYS_abs(p - b);
225     int pc = FXSYS_abs(p - c);
226     if (pa <= pb && pa <= pc) {
227         return (uint8_t)a;
228     }
229     if (pb <= pc) {
230         return (uint8_t)b;
231     }
232     return (uint8_t)c;
233 }
234 static FX_BOOL PNG_PredictorEncode(FX_LPBYTE& data_buf, FX_DWORD& data_size,
235                                    int predictor, int Colors,
236                                    int BitsPerComponent, int Columns)
237 {
238     const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8;
239     const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
240     if (row_size <= 0)
241         return FALSE;
242     const int row_count = (data_size + row_size - 1) / row_size;
243     const int last_row_size = data_size % row_size;
244     FX_LPBYTE dest_buf = FX_Alloc2D(uint8_t, row_size + 1, row_count);
245     int byte_cnt = 0;
246     FX_LPBYTE pSrcData = data_buf;
247     FX_LPBYTE pDestData = dest_buf;
248     for (int row = 0; row < row_count; row++) {
249         if (predictor == 10) {
250             pDestData[0] = 0;
251             int move_size = row_size;
252             if (move_size * (row + 1) > (int)data_size) {
253                 move_size = data_size - (move_size * row);
254             }
255             FXSYS_memmove32(pDestData + 1, pSrcData, move_size);
256             pDestData += (move_size + 1);
257             pSrcData += move_size;
258             byte_cnt += move_size;
259             continue;
260         }
261         for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte++) {
262             switch (predictor) {
263                 case 11: {
264                         pDestData[0] = 1;
265                         uint8_t left = 0;
266                         if (byte >= BytesPerPixel) {
267                             left = pSrcData[byte - BytesPerPixel];
268                         }
269                         pDestData[byte + 1] = pSrcData[byte] - left;
270                     }
271                     break;
272                 case 12: {
273                         pDestData[0] = 2;
274                         uint8_t up = 0;
275                         if (row) {
276                             up = pSrcData[byte - row_size];
277                         }
278                         pDestData[byte + 1] = pSrcData[byte] - up;
279                     }
280                     break;
281                 case 13: {
282                         pDestData[0] = 3;
283                         uint8_t left = 0;
284                         if (byte >= BytesPerPixel) {
285                             left = pSrcData[byte - BytesPerPixel];
286                         }
287                         uint8_t up = 0;
288                         if (row) {
289                             up = pSrcData[byte - row_size];
290                         }
291                         pDestData[byte + 1] = pSrcData[byte] - (left + up) / 2;
292                     }
293                     break;
294                 case 14: {
295                         pDestData[0] = 4;
296                         uint8_t left = 0;
297                         if (byte >= BytesPerPixel) {
298                             left = pSrcData[byte - BytesPerPixel];
299                         }
300                         uint8_t up = 0;
301                         if (row) {
302                             up = pSrcData[byte - row_size];
303                         }
304                         uint8_t upper_left = 0;
305                         if (byte >= BytesPerPixel && row) {
306                             upper_left = pSrcData[byte - row_size - BytesPerPixel];
307                         }
308                         pDestData[byte + 1] = pSrcData[byte] - PaethPredictor(left, up, upper_left);
309                     }
310                     break;
311                 default: {
312                         pDestData[byte + 1] = pSrcData[byte];
313                     }
314                     break;
315             }
316             byte_cnt++;
317         }
318         pDestData += (row_size + 1);
319         pSrcData += row_size;
320     }
321     FX_Free(data_buf);
322     data_buf = dest_buf;
323     data_size = (row_size + 1) * row_count - (last_row_size > 0 ? (row_size - last_row_size) : 0);
324     return TRUE;
325 }
326 static void PNG_PredictLine(FX_LPBYTE pDestData, FX_LPCBYTE pSrcData, FX_LPCBYTE pLastLine,
327                             int bpc, int nColors, int nPixels)
328 {
329     int row_size = (nPixels * bpc * nColors + 7) / 8;
330     int BytesPerPixel = (bpc * nColors + 7) / 8;
331     uint8_t tag = pSrcData[0];
332     if (tag == 0) {
333         FXSYS_memmove32(pDestData, pSrcData + 1, row_size);
334         return;
335     }
336     for (int byte = 0; byte < row_size; byte ++) {
337         uint8_t raw_byte = pSrcData[byte + 1];
338         switch (tag) {
339             case 1:     {
340                     uint8_t left = 0;
341                     if (byte >= BytesPerPixel) {
342                         left = pDestData[byte - BytesPerPixel];
343                     }
344                     pDestData[byte] = raw_byte + left;
345                     break;
346                 }
347             case 2: {
348                     uint8_t up = 0;
349                     if (pLastLine) {
350                         up = pLastLine[byte];
351                     }
352                     pDestData[byte] = raw_byte + up;
353                     break;
354                 }
355             case 3: {
356                     uint8_t left = 0;
357                     if (byte >= BytesPerPixel) {
358                         left = pDestData[byte - BytesPerPixel];
359                     }
360                     uint8_t up = 0;
361                     if (pLastLine) {
362                         up = pLastLine[byte];
363                     }
364                     pDestData[byte] = raw_byte + (up + left) / 2;
365                     break;
366                 }
367             case 4: {
368                     uint8_t left = 0;
369                     if (byte >= BytesPerPixel) {
370                         left = pDestData[byte - BytesPerPixel];
371                     }
372                     uint8_t up = 0;
373                     if (pLastLine) {
374                         up = pLastLine[byte];
375                     }
376                     uint8_t upper_left = 0;
377                     if (byte >= BytesPerPixel && pLastLine) {
378                         upper_left = pLastLine[byte - BytesPerPixel];
379                     }
380                     pDestData[byte] = raw_byte + PaethPredictor(left, up, upper_left);
381                     break;
382                 }
383             default:
384                 pDestData[byte] = raw_byte;
385                 break;
386         }
387     }
388 }
389 static FX_BOOL PNG_Predictor(FX_LPBYTE& data_buf, FX_DWORD& data_size,
390                              int Colors, int BitsPerComponent, int Columns)
391 {
392     const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8;
393     const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
394     if (row_size <= 0)
395         return FALSE;
396     const int row_count = (data_size + row_size) / (row_size + 1);
397     const int last_row_size = data_size % (row_size + 1);
398     FX_LPBYTE dest_buf = FX_Alloc2D(uint8_t, row_size, row_count);
399     int byte_cnt = 0;
400     FX_LPBYTE pSrcData = data_buf;
401     FX_LPBYTE pDestData = dest_buf;
402     for (int row = 0; row < row_count; row ++) {
403         uint8_t tag = pSrcData[0];
404         byte_cnt++;
405         if (tag == 0) {
406             int move_size = row_size;
407             if ((row + 1) * (move_size + 1) > (int)data_size) {
408                 move_size = last_row_size - 1;
409             }
410             FXSYS_memmove32(pDestData, pSrcData + 1, move_size);
411             pSrcData += move_size + 1;
412             pDestData += move_size;
413             byte_cnt += move_size;
414             continue;
415         }
416         for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte ++) {
417             uint8_t raw_byte = pSrcData[byte + 1];
418             switch (tag) {
419                 case 1: {
420                         uint8_t left = 0;
421                         if (byte >= BytesPerPixel) {
422                             left = pDestData[byte - BytesPerPixel];
423                         }
424                         pDestData[byte] = raw_byte + left;
425                         break;
426                     }
427                 case 2: {
428                         uint8_t up = 0;
429                         if (row) {
430                             up = pDestData[byte - row_size];
431                         }
432                         pDestData[byte] = raw_byte + up;
433                         break;
434                     }
435                 case 3: {
436                         uint8_t left = 0;
437                         if (byte >= BytesPerPixel) {
438                             left = pDestData[byte - BytesPerPixel];
439                         }
440                         uint8_t up = 0;
441                         if (row) {
442                             up = pDestData[byte - row_size];
443                         }
444                         pDestData[byte] = raw_byte + (up + left) / 2;
445                         break;
446                     }
447                 case 4: {
448                         uint8_t left = 0;
449                         if (byte >= BytesPerPixel) {
450                             left = pDestData[byte - BytesPerPixel];
451                         }
452                         uint8_t up = 0;
453                         if (row) {
454                             up = pDestData[byte - row_size];
455                         }
456                         uint8_t upper_left = 0;
457                         if (byte >= BytesPerPixel && row) {
458                             upper_left = pDestData[byte - row_size - BytesPerPixel];
459                         }
460                         pDestData[byte] = raw_byte + PaethPredictor(left, up, upper_left);
461                         break;
462                     }
463                 default:
464                     pDestData[byte] = raw_byte;
465                     break;
466             }
467             byte_cnt++;
468         }
469         pSrcData += row_size + 1;
470         pDestData += row_size;
471     }
472     FX_Free(data_buf);
473     data_buf = dest_buf;
474     data_size = row_size * row_count - (last_row_size > 0 ? (row_size + 1 - last_row_size) : 0);
475     return TRUE;
476 }
477 static void TIFF_PredictorEncodeLine(FX_LPBYTE dest_buf, int row_size, int BitsPerComponent, int Colors, int Columns)
478 {
479     int BytesPerPixel = BitsPerComponent * Colors / 8;
480     if (BitsPerComponent < 8) {
481         uint8_t mask = 0x01;
482         if (BitsPerComponent == 2) {
483             mask = 0x03;
484         } else if (BitsPerComponent == 4) {
485             mask = 0x0F;
486         }
487         int row_bits = Colors * BitsPerComponent * Columns;
488         for (int i = row_bits - BitsPerComponent; i >= BitsPerComponent; i -= BitsPerComponent) {
489             int col = i % 8;
490             int index = i / 8;
491             int col_pre = (col == 0) ? (8 - BitsPerComponent) : (col - BitsPerComponent);
492             int index_pre = (col == 0) ? (index - 1) : index;
493             uint8_t cur = (dest_buf[index] >> (8 - col - BitsPerComponent)) & mask;
494             uint8_t left = (dest_buf[index_pre] >> (8 - col_pre - BitsPerComponent)) & mask;
495             cur -= left;
496             cur &= mask;
497             cur <<= (8 - col - BitsPerComponent);
498             dest_buf[index] &= ~(mask << ((8 - col - BitsPerComponent)));
499             dest_buf[index] |= cur;
500         }
501     } else if (BitsPerComponent == 8) {
502         for (int i = row_size - 1; i >= BytesPerPixel; i--) {
503             dest_buf[i] -= dest_buf[i - BytesPerPixel];
504         }
505     } else {
506         for (int i = row_size - BytesPerPixel; i >= BytesPerPixel; i -= BytesPerPixel) {
507             FX_WORD pixel = (dest_buf[i] << 8) | dest_buf[i + 1];
508             pixel -= (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1];
509             dest_buf[i] = pixel >> 8;
510             dest_buf[i + 1] = (uint8_t)pixel;
511         }
512     }
513 }
514 static FX_BOOL TIFF_PredictorEncode(FX_LPBYTE& data_buf, FX_DWORD& data_size,
515                                     int Colors, int BitsPerComponent, int Columns)
516 {
517     int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
518     if (row_size == 0)
519         return FALSE;
520     const int row_count = (data_size + row_size - 1) / row_size;
521     const int last_row_size = data_size % row_size;
522     for (int row = 0; row < row_count; row++) {
523         FX_LPBYTE scan_line = data_buf + row * row_size;
524         if ((row + 1) * row_size > (int)data_size) {
525             row_size = last_row_size;
526         }
527         TIFF_PredictorEncodeLine(scan_line, row_size, BitsPerComponent, Colors, Columns);
528     }
529     return TRUE;
530 }
531 static void TIFF_PredictLine(FX_LPBYTE dest_buf, int row_size, int BitsPerComponent, int Colors, int Columns)
532 {
533     if (BitsPerComponent == 1) {
534         int row_bits = FX_MIN(BitsPerComponent * Colors * Columns, row_size * 8);
535         int index_pre = 0;
536         int col_pre = 0;
537         for(int i = 1; i < row_bits; i ++) {
538             int col = i % 8;
539             int index = i / 8;
540             if( ((dest_buf[index] >> (7 - col)) & 1) ^ ((dest_buf[index_pre] >> (7 - col_pre)) & 1) ) {
541                 dest_buf[index] |= 1 << (7 - col);
542             } else {
543                 dest_buf[index] &= ~(1 << (7 - col));
544             }
545             index_pre = index;
546             col_pre = col;
547         }
548         return;
549     }
550     int BytesPerPixel = BitsPerComponent * Colors / 8;
551     if (BitsPerComponent == 16) {
552         for (int i = BytesPerPixel; i < row_size; i += 2) {
553             FX_WORD pixel = (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1];
554             pixel += (dest_buf[i] << 8) | dest_buf[i + 1];
555             dest_buf[i] = pixel >> 8;
556             dest_buf[i + 1] = (uint8_t)pixel;
557         }
558     } else {
559         for (int i = BytesPerPixel; i < row_size; i ++) {
560             dest_buf[i] += dest_buf[i - BytesPerPixel];
561         }
562     }
563 }
564 static FX_BOOL TIFF_Predictor(FX_LPBYTE& data_buf, FX_DWORD& data_size,
565                               int Colors, int BitsPerComponent, int Columns)
566 {
567     int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
568     if (row_size == 0)
569         return FALSE;
570     const int row_count = (data_size + row_size - 1) / row_size;
571     const int last_row_size = data_size % row_size;
572     for (int row = 0; row < row_count; row ++) {
573         FX_LPBYTE scan_line = data_buf + row * row_size;
574         if ((row + 1) * row_size > (int)data_size) {
575             row_size = last_row_size;
576         }
577         TIFF_PredictLine(scan_line, row_size, BitsPerComponent, Colors, Columns);
578     }
579     return TRUE;
580 }
581 class CCodec_FlateScanlineDecoder : public CCodec_ScanlineDecoder
582 {
583 public:
584     CCodec_FlateScanlineDecoder();
585     ~CCodec_FlateScanlineDecoder();
586     void Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc,
587                 int predictor, int Colors, int BitsPerComponent, int Columns);
588     virtual void                Destroy()
589     {
590         delete this;
591     }
592     virtual void                v_DownScale(int dest_width, int dest_height) {}
593     virtual FX_BOOL             v_Rewind();
594     virtual FX_LPBYTE   v_GetNextLine();
595     virtual FX_DWORD    GetSrcOffset();
596     void*                               m_pFlate;
597     FX_LPCBYTE                  m_SrcBuf;
598     FX_DWORD                    m_SrcSize;
599     FX_LPBYTE                   m_pScanline;
600     FX_LPBYTE                   m_pLastLine;
601     FX_LPBYTE                   m_pPredictBuffer;
602     FX_LPBYTE                   m_pPredictRaw;
603     int                                 m_Predictor;
604     int                                 m_Colors, m_BitsPerComponent, m_Columns, m_PredictPitch, m_LeftOver;
605 };
606 CCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder()
607 {
608     m_pFlate = NULL;
609     m_pScanline = NULL;
610     m_pLastLine = NULL;
611     m_pPredictBuffer = NULL;
612     m_pPredictRaw = NULL;
613     m_LeftOver = 0;
614 }
615 CCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder()
616 {
617     if (m_pScanline) {
618         FX_Free(m_pScanline);
619     }
620     if (m_pLastLine) {
621         FX_Free(m_pLastLine);
622     }
623     if (m_pPredictBuffer) {
624         FX_Free(m_pPredictBuffer);
625     }
626     if (m_pPredictRaw) {
627         FX_Free(m_pPredictRaw);
628     }
629     if (m_pFlate) {
630         FPDFAPI_FlateEnd(m_pFlate);
631     }
632 }
633 void CCodec_FlateScanlineDecoder::Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
634         int nComps, int bpc, int predictor, int Colors, int BitsPerComponent, int Columns)
635 {
636     m_SrcBuf = src_buf;
637     m_SrcSize = src_size;
638     m_OutputWidth = m_OrigWidth = width;
639     m_OutputHeight = m_OrigHeight = height;
640     m_nComps = nComps;
641     m_bpc = bpc;
642     m_bColorTransformed = FALSE;
643     m_Pitch = (width * nComps * bpc + 7) / 8;
644     m_pScanline = FX_Alloc(uint8_t, m_Pitch);
645     m_Predictor = 0;
646     if (predictor) {
647         if (predictor >= 10) {
648             m_Predictor = 2;
649         } else if (predictor == 2) {
650             m_Predictor = 1;
651         }
652         if (m_Predictor) {
653             if (BitsPerComponent * Colors * Columns == 0) {
654                 BitsPerComponent = m_bpc;
655                 Colors = m_nComps;
656                 Columns = m_OrigWidth;
657             }
658             m_Colors = Colors;
659             m_BitsPerComponent = BitsPerComponent;
660             m_Columns = Columns;
661             m_PredictPitch = (m_BitsPerComponent * m_Colors * m_Columns + 7) / 8;
662             m_pLastLine = FX_Alloc(uint8_t, m_PredictPitch);
663             m_pPredictRaw = FX_Alloc(uint8_t, m_PredictPitch + 1);
664             m_pPredictBuffer = FX_Alloc(uint8_t, m_PredictPitch);
665         }
666     }
667 }
668 FX_BOOL CCodec_FlateScanlineDecoder::v_Rewind()
669 {
670     if (m_pFlate) {
671         FPDFAPI_FlateEnd(m_pFlate);
672     }
673     m_pFlate = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
674     if (m_pFlate == NULL) {
675         return FALSE;
676     }
677     FPDFAPI_FlateInput(m_pFlate, m_SrcBuf, m_SrcSize);
678     m_LeftOver = 0;
679     return TRUE;
680 }
681 FX_LPBYTE CCodec_FlateScanlineDecoder::v_GetNextLine()
682 {
683     if (m_Predictor) {
684         if (m_Pitch == m_PredictPitch) {
685             if (m_Predictor == 2) {
686                 FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
687                 PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, m_Colors, m_Columns);
688                 FXSYS_memcpy32(m_pLastLine, m_pScanline, m_PredictPitch);
689             } else {
690                 FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch);
691                 TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps, m_OutputWidth);
692             }
693         } else {
694             int bytes_to_go = m_Pitch;
695             int read_leftover = m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftOver;
696             if (read_leftover) {
697                 FXSYS_memcpy32(m_pScanline, m_pPredictBuffer + m_PredictPitch - m_LeftOver, read_leftover);
698                 m_LeftOver -= read_leftover;
699                 bytes_to_go -= read_leftover;
700             }
701             while (bytes_to_go) {
702                 if (m_Predictor == 2) {
703                     FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
704                     PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, m_Colors, m_Columns);
705                     FXSYS_memcpy32(m_pLastLine, m_pPredictBuffer, m_PredictPitch);
706                 } else {
707                     FPDFAPI_FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch);
708                     TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPerComponent, m_Colors, m_Columns);
709                 }
710                 int read_bytes = m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch;
711                 FXSYS_memcpy32(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer, read_bytes);
712                 m_LeftOver += m_PredictPitch - read_bytes;
713                 bytes_to_go -= read_bytes;
714             }
715         }
716     } else {
717         FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch);
718     }
719     return m_pScanline;
720 }
721 FX_DWORD CCodec_FlateScanlineDecoder::GetSrcOffset()
722 {
723     return FPDFAPI_FlateGetTotalIn(m_pFlate);
724 }
725 static void FlateUncompress(FX_LPCBYTE src_buf, FX_DWORD src_size, FX_DWORD orig_size,
726                             FX_LPBYTE& dest_buf, FX_DWORD& dest_size, FX_DWORD& offset)
727 {
728     const FX_BOOL useOldImpl = src_size < 10240;
729     FX_DWORD guess_size = orig_size ? orig_size : src_size * 2;
730     FX_DWORD alloc_step = orig_size ? 10240 : (src_size < 10240 ? 10240 : src_size);
731     static const FX_DWORD kMaxInitialAllocSize = 10000000;
732     if (guess_size > kMaxInitialAllocSize) {
733         guess_size = kMaxInitialAllocSize;
734         alloc_step = kMaxInitialAllocSize;
735     }
736     FX_DWORD buf_size = guess_size;
737     FX_DWORD last_buf_size = buf_size;
738     void* context = nullptr;
739
740     FX_LPBYTE guess_buf = FX_Alloc(uint8_t, guess_size + 1);
741     FX_LPBYTE cur_buf = guess_buf;
742     guess_buf[guess_size] = '\0';
743     context = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
744     if (!context)
745         goto fail;
746     FPDFAPI_FlateInput(context, src_buf, src_size);
747     if (useOldImpl) {
748         while (1) {
749             int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size);
750             if (ret != Z_OK)
751                 break;
752             int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context);
753             if (avail_buf_size != 0)
754                 break;
755
756             // |avail_buf_size| == 0 case.
757             FX_DWORD old_size = guess_size;
758             guess_size += alloc_step;
759             if (guess_size < old_size || guess_size + 1 < guess_size)
760                 goto fail;
761             guess_buf = FX_Realloc(uint8_t, guess_buf, guess_size + 1);
762             if (!guess_buf)
763                 goto fail;
764             guess_buf[guess_size] = '\0';
765             cur_buf = guess_buf + old_size;
766             buf_size = guess_size - old_size;
767         }
768         dest_size = FPDFAPI_FlateGetTotalOut(context);
769         offset = FPDFAPI_FlateGetTotalIn(context);
770         if (guess_size / 2 > dest_size) {
771             guess_buf = FX_Realloc(uint8_t, guess_buf, dest_size + 1);
772             if (!guess_buf)
773                 goto fail;
774             guess_size = dest_size;
775             guess_buf[guess_size] = '\0';
776         }
777         dest_buf = guess_buf;
778     } else {
779         CFX_ArrayTemplate<FX_LPBYTE> result_tmp_bufs;
780         while (1) {
781             int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size);
782             int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context);
783             if (ret != Z_OK) {
784                 last_buf_size = buf_size - avail_buf_size;
785                 result_tmp_bufs.Add(cur_buf);
786                 break;
787             }
788             if (avail_buf_size != 0) {
789                 last_buf_size = buf_size - avail_buf_size;
790                 result_tmp_bufs.Add(cur_buf);
791                 break;
792             }
793
794             // |avail_buf_size| == 0 case.
795             result_tmp_bufs.Add(cur_buf);
796             cur_buf = FX_Alloc(uint8_t, buf_size + 1);
797             cur_buf[buf_size] = '\0';
798         }
799         dest_size = FPDFAPI_FlateGetTotalOut(context);
800         offset = FPDFAPI_FlateGetTotalIn(context);
801         if (result_tmp_bufs.GetSize() == 1) {
802             dest_buf = result_tmp_bufs[0];
803         } else {
804             FX_LPBYTE result_buf = FX_Alloc(uint8_t, dest_size);
805             FX_DWORD result_pos = 0;
806             for (int32_t i = 0; i < result_tmp_bufs.GetSize(); i++) {
807                 FX_LPBYTE tmp_buf = result_tmp_bufs[i];
808                 FX_DWORD tmp_buf_size = buf_size;
809                 if (i == result_tmp_bufs.GetSize() - 1) {
810                     tmp_buf_size = last_buf_size;
811                 }
812                 FXSYS_memcpy32(result_buf + result_pos, tmp_buf, tmp_buf_size);
813                 result_pos += tmp_buf_size;
814                 FX_Free(result_tmp_bufs[i]);
815             }
816             dest_buf = result_buf;
817         }
818     }
819     FPDFAPI_FlateEnd(context);
820     return;
821
822 fail:
823     FX_Free(guess_buf);
824     dest_buf = nullptr;
825     dest_size = 0;
826     return;
827 }
828 ICodec_ScanlineDecoder* CCodec_FlateModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
829         int nComps, int bpc, int predictor, int Colors, int BitsPerComponent, int Columns)
830 {
831     CCodec_FlateScanlineDecoder* pDecoder = new CCodec_FlateScanlineDecoder;
832     pDecoder->Create(src_buf, src_size, width, height, nComps, bpc, predictor, Colors, BitsPerComponent, Columns);
833     return pDecoder;
834 }
835 FX_DWORD CCodec_FlateModule::FlateOrLZWDecode(FX_BOOL bLZW, const uint8_t* src_buf, FX_DWORD src_size, FX_BOOL bEarlyChange,
836         int predictor, int Colors, int BitsPerComponent, int Columns,
837         FX_DWORD estimated_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
838 {
839     dest_buf = NULL;
840     FX_DWORD offset = 0;
841     int predictor_type = 0;
842     if (predictor) {
843         if (predictor >= 10) {
844             predictor_type = 2;
845         } else if (predictor == 2) {
846             predictor_type = 1;
847         }
848     }
849     if (bLZW) {
850         {
851             nonstd::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder);
852             dest_size = (FX_DWORD) - 1;
853             offset = src_size;
854             int err = decoder->Decode(NULL, dest_size, src_buf, offset,
855                                       bEarlyChange);
856             if (err || dest_size == 0 || dest_size + 1 < dest_size) {
857                 return -1;
858             }
859         }
860         {
861             nonstd::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder);
862             dest_buf = FX_Alloc( uint8_t, dest_size + 1);
863             dest_buf[dest_size] = '\0';
864             decoder->Decode(dest_buf, dest_size, src_buf, offset, bEarlyChange);
865         }
866     } else {
867         FlateUncompress(src_buf, src_size, estimated_size, dest_buf, dest_size, offset);
868     }
869     if (predictor_type == 0) {
870         return offset;
871     }
872     FX_BOOL ret = TRUE;
873     if (predictor_type == 2) {
874         ret = PNG_Predictor(dest_buf, dest_size, Colors, BitsPerComponent,
875                             Columns);
876     } else if (predictor_type == 1) {
877         ret = TIFF_Predictor(dest_buf, dest_size, Colors, BitsPerComponent,
878                              Columns);
879     }
880     return ret ? offset : -1;
881 }
882 FX_BOOL CCodec_FlateModule::Encode(const uint8_t* src_buf, FX_DWORD src_size,
883                                    int predictor, int Colors, int BitsPerComponent, int Columns,
884                                    FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
885 {
886     if (predictor != 2 && predictor < 10) {
887         return Encode(src_buf, src_size, dest_buf, dest_size);
888     }
889     FX_LPBYTE pSrcBuf = NULL;
890     pSrcBuf = FX_Alloc(uint8_t, src_size);
891     FXSYS_memcpy32(pSrcBuf, src_buf, src_size);
892     FX_BOOL ret = TRUE;
893     if (predictor == 2) {
894         ret = TIFF_PredictorEncode(pSrcBuf, src_size, Colors, BitsPerComponent,
895                                    Columns);
896     } else if (predictor >= 10) {
897         ret = PNG_PredictorEncode(pSrcBuf, src_size, predictor, Colors,
898                                   BitsPerComponent, Columns);
899     }
900     if (ret)
901         ret = Encode(pSrcBuf, src_size, dest_buf, dest_size);
902     FX_Free(pSrcBuf);
903     return ret;
904 }
905 FX_BOOL CCodec_FlateModule::Encode(FX_LPCBYTE src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
906 {
907     dest_size = src_size + src_size / 1000 + 12;
908     dest_buf = FX_Alloc( uint8_t, dest_size);
909     unsigned long temp_size = dest_size;
910     FPDFAPI_FlateCompress(dest_buf, &temp_size, src_buf, src_size);
911     dest_size = (FX_DWORD)temp_size;
912     return TRUE;
913 }