Revert "Remove FX_Alloc() null checks now that it can't return NULL."
[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(FX_BYTE, 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 FX_BYTE* 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 FX_BYTE*      m_pInput;
88     FX_BOOL             m_Early;
89     void                AddCode(FX_DWORD prefix_code, FX_BYTE append_char);
90     FX_DWORD    m_CodeArray[5021];
91     FX_DWORD    m_nCodes;
92     FX_BYTE             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, FX_BYTE 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++] = (FX_BYTE)data;
123         code = data >> 16;
124     }
125     if (m_StackLen >= sizeof(m_DecodeStack)) {
126         return;
127     }
128     m_DecodeStack[m_StackLen++] = (FX_BYTE)code;
129 }
130 int CLZWDecoder::Decode(FX_LPBYTE dest_buf, FX_DWORD& dest_size, const FX_BYTE* 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     FX_BYTE 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] = (FX_BYTE)code;
168             }
169             m_OutPos ++;
170             last_char = (FX_BYTE)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 FX_BYTE 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 (FX_BYTE)a;
228     }
229     if (pb <= pc) {
230         return (FX_BYTE)b;
231     }
232     return (FX_BYTE)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(FX_BYTE, 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                         FX_BYTE 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                         FX_BYTE 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                         FX_BYTE left = 0;
284                         if (byte >= BytesPerPixel) {
285                             left = pSrcData[byte - BytesPerPixel];
286                         }
287                         FX_BYTE 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                         FX_BYTE left = 0;
297                         if (byte >= BytesPerPixel) {
298                             left = pSrcData[byte - BytesPerPixel];
299                         }
300                         FX_BYTE up = 0;
301                         if (row) {
302                             up = pSrcData[byte - row_size];
303                         }
304                         FX_BYTE 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     FX_BYTE 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         FX_BYTE raw_byte = pSrcData[byte + 1];
338         switch (tag) {
339             case 1:     {
340                     FX_BYTE 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                     FX_BYTE up = 0;
349                     if (pLastLine) {
350                         up = pLastLine[byte];
351                     }
352                     pDestData[byte] = raw_byte + up;
353                     break;
354                 }
355             case 3: {
356                     FX_BYTE left = 0;
357                     if (byte >= BytesPerPixel) {
358                         left = pDestData[byte - BytesPerPixel];
359                     }
360                     FX_BYTE 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                     FX_BYTE left = 0;
369                     if (byte >= BytesPerPixel) {
370                         left = pDestData[byte - BytesPerPixel];
371                     }
372                     FX_BYTE up = 0;
373                     if (pLastLine) {
374                         up = pLastLine[byte];
375                     }
376                     FX_BYTE 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(FX_BYTE, 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         FX_BYTE 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             FX_BYTE raw_byte = pSrcData[byte + 1];
418             switch (tag) {
419                 case 1: {
420                         FX_BYTE 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                         FX_BYTE 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                         FX_BYTE left = 0;
437                         if (byte >= BytesPerPixel) {
438                             left = pDestData[byte - BytesPerPixel];
439                         }
440                         FX_BYTE 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                         FX_BYTE left = 0;
449                         if (byte >= BytesPerPixel) {
450                             left = pDestData[byte - BytesPerPixel];
451                         }
452                         FX_BYTE up = 0;
453                         if (row) {
454                             up = pDestData[byte - row_size];
455                         }
456                         FX_BYTE 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         FX_BYTE 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             FX_BYTE cur = (dest_buf[index] >> (8 - col - BitsPerComponent)) & mask;
494             FX_BYTE 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] = (FX_BYTE)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] = (FX_BYTE)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     FX_BOOL             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 FX_BOOL 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(FX_BYTE, m_Pitch);
645     if (m_pScanline == NULL) {
646         return FALSE;
647     }
648     m_Predictor = 0;
649     if (predictor) {
650         if (predictor >= 10) {
651             m_Predictor = 2;
652         } else if (predictor == 2) {
653             m_Predictor = 1;
654         }
655         if (m_Predictor) {
656             if (BitsPerComponent * Colors * Columns == 0) {
657                 BitsPerComponent = m_bpc;
658                 Colors = m_nComps;
659                 Columns = m_OrigWidth;
660             }
661             m_Colors = Colors;
662             m_BitsPerComponent = BitsPerComponent;
663             m_Columns = Columns;
664             m_PredictPitch = (m_BitsPerComponent * m_Colors * m_Columns + 7) / 8;
665             m_pLastLine = FX_Alloc(FX_BYTE, m_PredictPitch);
666             if (m_pLastLine == NULL) {
667                 return FALSE;
668             }
669             m_pPredictRaw = FX_Alloc(FX_BYTE, m_PredictPitch + 1);
670             if (m_pPredictRaw == NULL) {
671                 return FALSE;
672             }
673             m_pPredictBuffer = FX_Alloc(FX_BYTE, m_PredictPitch);
674             if (m_pPredictBuffer == NULL) {
675                 return FALSE;
676             }
677         }
678     }
679     return TRUE;
680 }
681 FX_BOOL CCodec_FlateScanlineDecoder::v_Rewind()
682 {
683     if (m_pFlate) {
684         FPDFAPI_FlateEnd(m_pFlate);
685     }
686     m_pFlate = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
687     if (m_pFlate == NULL) {
688         return FALSE;
689     }
690     FPDFAPI_FlateInput(m_pFlate, m_SrcBuf, m_SrcSize);
691     m_LeftOver = 0;
692     return TRUE;
693 }
694 FX_LPBYTE CCodec_FlateScanlineDecoder::v_GetNextLine()
695 {
696     if (m_Predictor) {
697         if (m_Pitch == m_PredictPitch) {
698             if (m_Predictor == 2) {
699                 FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
700                 PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, m_Colors, m_Columns);
701                 FXSYS_memcpy32(m_pLastLine, m_pScanline, m_PredictPitch);
702             } else {
703                 FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch);
704                 TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps, m_OutputWidth);
705             }
706         } else {
707             int bytes_to_go = m_Pitch;
708             int read_leftover = m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftOver;
709             if (read_leftover) {
710                 FXSYS_memcpy32(m_pScanline, m_pPredictBuffer + m_PredictPitch - m_LeftOver, read_leftover);
711                 m_LeftOver -= read_leftover;
712                 bytes_to_go -= read_leftover;
713             }
714             while (bytes_to_go) {
715                 if (m_Predictor == 2) {
716                     FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
717                     PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, m_Colors, m_Columns);
718                     FXSYS_memcpy32(m_pLastLine, m_pPredictBuffer, m_PredictPitch);
719                 } else {
720                     FPDFAPI_FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch);
721                     TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPerComponent, m_Colors, m_Columns);
722                 }
723                 int read_bytes = m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch;
724                 FXSYS_memcpy32(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer, read_bytes);
725                 m_LeftOver += m_PredictPitch - read_bytes;
726                 bytes_to_go -= read_bytes;
727             }
728         }
729     } else {
730         FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch);
731     }
732     return m_pScanline;
733 }
734 FX_DWORD CCodec_FlateScanlineDecoder::GetSrcOffset()
735 {
736     return FPDFAPI_FlateGetTotalIn(m_pFlate);
737 }
738 static void FlateUncompress(FX_LPCBYTE src_buf, FX_DWORD src_size, FX_DWORD orig_size,
739                             FX_LPBYTE& dest_buf, FX_DWORD& dest_size, FX_DWORD& offset)
740 {
741     const FX_BOOL useOldImpl = src_size < 10240;
742     FX_DWORD guess_size = orig_size ? orig_size : src_size * 2;
743     FX_DWORD alloc_step = orig_size ? 10240 : (src_size < 10240 ? 10240 : src_size);
744     static const FX_DWORD kMaxInitialAllocSize = 10000000;
745     if (guess_size > kMaxInitialAllocSize) {
746         guess_size = kMaxInitialAllocSize;
747         alloc_step = kMaxInitialAllocSize;
748     }
749     FX_DWORD buf_size = guess_size;
750     FX_DWORD last_buf_size = buf_size;
751     void* context = nullptr;
752
753     FX_LPBYTE guess_buf = FX_Alloc(FX_BYTE, guess_size + 1);
754     FX_LPBYTE cur_buf = guess_buf;
755     if (!guess_buf)
756         goto fail;
757     guess_buf[guess_size] = '\0';
758     context = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
759     if (!context)
760         goto fail;
761     FPDFAPI_FlateInput(context, src_buf, src_size);
762     if (useOldImpl) {
763         while (1) {
764             FX_INT32 ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size);
765             if (ret != Z_OK)
766                 break;
767             FX_INT32 avail_buf_size = FPDFAPI_FlateGetAvailOut(context);
768             if (avail_buf_size != 0)
769                 break;
770
771             // |avail_buf_size| == 0 case.
772             FX_DWORD old_size = guess_size;
773             guess_size += alloc_step;
774             if (guess_size < old_size || guess_size + 1 < guess_size)
775                 goto fail;
776             guess_buf = FX_Realloc(FX_BYTE, guess_buf, guess_size + 1);
777             if (!guess_buf)
778                 goto fail;
779             guess_buf[guess_size] = '\0';
780             cur_buf = guess_buf + old_size;
781             buf_size = guess_size - old_size;
782         }
783         dest_size = FPDFAPI_FlateGetTotalOut(context);
784         offset = FPDFAPI_FlateGetTotalIn(context);
785         if (guess_size / 2 > dest_size) {
786             guess_buf = FX_Realloc(FX_BYTE, guess_buf, dest_size + 1);
787             if (!guess_buf)
788                 goto fail;
789             guess_size = dest_size;
790             guess_buf[guess_size] = '\0';
791         }
792         dest_buf = guess_buf;
793     } else {
794         CFX_ArrayTemplate<FX_LPBYTE> result_tmp_bufs;
795         while (1) {
796             FX_INT32 ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size);
797             FX_INT32 avail_buf_size = FPDFAPI_FlateGetAvailOut(context);
798             if (ret != Z_OK) {
799                 last_buf_size = buf_size - avail_buf_size;
800                 result_tmp_bufs.Add(cur_buf);
801                 break;
802             }
803             if (avail_buf_size != 0) {
804                 last_buf_size = buf_size - avail_buf_size;
805                 result_tmp_bufs.Add(cur_buf);
806                 break;
807             }
808
809             // |avail_buf_size| == 0 case.
810             result_tmp_bufs.Add(cur_buf);
811             cur_buf = FX_Alloc(FX_BYTE, buf_size + 1);
812             if (!cur_buf) {
813                 for (FX_INT32 i = 0; i < result_tmp_bufs.GetSize(); i++) {
814                     FX_Free(result_tmp_bufs[i]);
815                 }
816                 goto fail;
817             }
818             cur_buf[buf_size] = '\0';
819         }
820         dest_size = FPDFAPI_FlateGetTotalOut(context);
821         offset = FPDFAPI_FlateGetTotalIn(context);
822         if (result_tmp_bufs.GetSize() == 1) {
823             dest_buf = result_tmp_bufs[0];
824         } else {
825             FX_LPBYTE result_buf = FX_Alloc(FX_BYTE, dest_size);
826             if (!result_buf) {
827                 for (FX_INT32 i = 0; i < result_tmp_bufs.GetSize(); i++) {
828                     FX_Free(result_tmp_bufs[i]);
829                 }
830                 goto fail;
831             }
832             FX_DWORD result_pos = 0;
833             for (FX_INT32 i = 0; i < result_tmp_bufs.GetSize(); i++) {
834                 FX_LPBYTE tmp_buf = result_tmp_bufs[i];
835                 FX_DWORD tmp_buf_size = buf_size;
836                 if (i == result_tmp_bufs.GetSize() - 1) {
837                     tmp_buf_size = last_buf_size;
838                 }
839                 FXSYS_memcpy32(result_buf + result_pos, tmp_buf, tmp_buf_size);
840                 result_pos += tmp_buf_size;
841                 FX_Free(result_tmp_bufs[i]);
842             }
843             dest_buf = result_buf;
844         }
845     }
846     FPDFAPI_FlateEnd(context);
847     return;
848
849 fail:
850     FX_Free(guess_buf);
851     dest_buf = nullptr;
852     dest_size = 0;
853     return;
854 }
855 ICodec_ScanlineDecoder* CCodec_FlateModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
856         int nComps, int bpc, int predictor, int Colors, int BitsPerComponent, int Columns)
857 {
858     CCodec_FlateScanlineDecoder* pDecoder = new CCodec_FlateScanlineDecoder;
859     pDecoder->Create(src_buf, src_size, width, height, nComps, bpc, predictor, Colors, BitsPerComponent, Columns);
860     return pDecoder;
861 }
862 FX_DWORD CCodec_FlateModule::FlateOrLZWDecode(FX_BOOL bLZW, const FX_BYTE* src_buf, FX_DWORD src_size, FX_BOOL bEarlyChange,
863         int predictor, int Colors, int BitsPerComponent, int Columns,
864         FX_DWORD estimated_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
865 {
866     dest_buf = NULL;
867     FX_DWORD offset = 0;
868     int predictor_type = 0;
869     if (predictor) {
870         if (predictor >= 10) {
871             predictor_type = 2;
872         } else if (predictor == 2) {
873             predictor_type = 1;
874         }
875     }
876     if (bLZW) {
877         {
878             nonstd::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder);
879             dest_size = (FX_DWORD) - 1;
880             offset = src_size;
881             int err = decoder->Decode(NULL, dest_size, src_buf, offset,
882                                       bEarlyChange);
883             if (err || dest_size == 0 || dest_size + 1 < dest_size) {
884                 return -1;
885             }
886         }
887         {
888             nonstd::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder);
889             dest_buf = FX_Alloc( FX_BYTE, dest_size + 1);
890             if (dest_buf == NULL) {
891                 return -1;
892             }
893             dest_buf[dest_size] = '\0';
894             decoder->Decode(dest_buf, dest_size, src_buf, offset, bEarlyChange);
895         }
896     } else {
897         FlateUncompress(src_buf, src_size, estimated_size, dest_buf, dest_size, offset);
898     }
899     if (predictor_type == 0) {
900         return offset;
901     }
902     FX_BOOL ret = TRUE;
903     if (predictor_type == 2) {
904         ret = PNG_Predictor(dest_buf, dest_size, Colors, BitsPerComponent,
905                             Columns);
906     } else if (predictor_type == 1) {
907         ret = TIFF_Predictor(dest_buf, dest_size, Colors, BitsPerComponent,
908                              Columns);
909     }
910     return ret ? offset : -1;
911 }
912 FX_BOOL CCodec_FlateModule::Encode(const FX_BYTE* src_buf, FX_DWORD src_size,
913                                    int predictor, int Colors, int BitsPerComponent, int Columns,
914                                    FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
915 {
916     if (predictor != 2 && predictor < 10) {
917         return Encode(src_buf, src_size, dest_buf, dest_size);
918     }
919     FX_LPBYTE pSrcBuf = NULL;
920     pSrcBuf = FX_Alloc(FX_BYTE, src_size);
921     if (pSrcBuf == NULL) {
922         return FALSE;
923     }
924     FXSYS_memcpy32(pSrcBuf, src_buf, src_size);
925     FX_BOOL ret = TRUE;
926     if (predictor == 2) {
927         ret = TIFF_PredictorEncode(pSrcBuf, src_size, Colors, BitsPerComponent,
928                                    Columns);
929     } else if (predictor >= 10) {
930         ret = PNG_PredictorEncode(pSrcBuf, src_size, predictor, Colors,
931                                   BitsPerComponent, Columns);
932     }
933     if (ret)
934         ret = Encode(pSrcBuf, src_size, dest_buf, dest_size);
935     FX_Free(pSrcBuf);
936     return ret;
937 }
938 FX_BOOL CCodec_FlateModule::Encode(FX_LPCBYTE src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
939 {
940     dest_size = src_size + src_size / 1000 + 12;
941     dest_buf = FX_Alloc( FX_BYTE, dest_size);
942     if (dest_buf == NULL) {
943         return FALSE;
944     }
945     unsigned long temp_size = dest_size;
946     FPDFAPI_FlateCompress(dest_buf, &temp_size, src_buf, src_size);
947     dest_size = (FX_DWORD)temp_size;
948     return TRUE;
949 }