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