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