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/fpdfapi/fpdf_parser.h"
9#include "../../../include/fxcodec/fx_codec.h"
10#include "../../../include/fpdfapi/fpdf_module.h"
11#include "filters_int.h"
12CFX_DataFilter::CFX_DataFilter()
13{
14    m_bEOF = FALSE;
15    m_pDestFilter = NULL;
16    m_SrcPos = 0;
17}
18CFX_DataFilter::~CFX_DataFilter()
19{
20    if (m_pDestFilter) {
21        delete m_pDestFilter;
22    }
23}
24void CFX_DataFilter::SetDestFilter(CFX_DataFilter* pFilter)
25{
26    if (m_pDestFilter) {
27        m_pDestFilter->SetDestFilter(pFilter);
28    } else {
29        m_pDestFilter = pFilter;
30    }
31}
32void CFX_DataFilter::FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
33{
34    if (m_bEOF) {
35        return;
36    }
37    m_SrcPos += src_size;
38    if (m_pDestFilter) {
39        CFX_BinaryBuf temp_buf;
40        temp_buf.EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);
41        v_FilterIn(src_buf, src_size, temp_buf);
42        m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf);
43    } else {
44        v_FilterIn(src_buf, src_size, dest_buf);
45    }
46}
47void CFX_DataFilter::FilterFinish(CFX_BinaryBuf& dest_buf)
48{
49    if (m_pDestFilter) {
50        CFX_BinaryBuf temp_buf;
51        v_FilterFinish(temp_buf);
52        if (temp_buf.GetSize()) {
53            m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf);
54        }
55        m_pDestFilter->FilterFinish(dest_buf);
56    } else {
57        v_FilterFinish(dest_buf);
58    }
59    m_bEOF = TRUE;
60}
61void CFX_DataFilter::ReportEOF(FX_DWORD left_input)
62{
63    if (m_bEOF) {
64        return;
65    }
66    m_bEOF = TRUE;
67    m_SrcPos -= left_input;
68}
69CFX_DataFilter* FPDF_CreateFilter(FX_BSTR name, const CPDF_Dictionary* pParam, int width, int height)
70{
71    FX_DWORD id = name.GetID();
72    switch (id) {
73        case FXBSTR_ID('F', 'l', 'a', 't'):
74        case FXBSTR_ID('F', 'l', 0, 0):
75        case FXBSTR_ID('L', 'Z', 'W', 'D'):
76        case FXBSTR_ID('L', 'Z', 'W', 0): {
77                CFX_DataFilter* pFilter;
78                if (id == FXBSTR_ID('L', 'Z', 'W', 'D') || id == FXBSTR_ID('L', 'Z', 'W', 0)) {
79                    pFilter = FX_NEW CPDF_LzwFilter(pParam->GetInteger("EarlyChange", 1));
80                } else {
81                    pFilter = FX_NEW CPDF_FlateFilter;
82                }
83                if (pParam->GetInteger("Predictor", 1) > 1) {
84                    CFX_DataFilter* pPredictor = FX_NEW CPDF_PredictorFilter(pParam->GetInteger(FX_BSTRC("Predictor"), 1),
85                                                 pParam->GetInteger(FX_BSTRC("Colors"), 1), pParam->GetInteger(FX_BSTRC("BitsPerComponent"), 8),
86                                                 pParam->GetInteger(FX_BSTRC("Columns"), 1));
87                    pFilter->SetDestFilter(pPredictor);
88                }
89                return pFilter;
90            }
91        case FXBSTR_ID('A', 'S', 'C', 'I'):
92            if (name == "ASCIIHexDecode") {
93                return FX_NEW CPDF_AsciiHexFilter;
94            }
95            return FX_NEW CPDF_Ascii85Filter;
96        case FXBSTR_ID('A', 'H', 'x', 0):
97            return FX_NEW CPDF_AsciiHexFilter;
98        case FXBSTR_ID('A', '8', '5', 0):
99            return FX_NEW CPDF_Ascii85Filter;
100        case FXBSTR_ID('R', 'u', 'n', 'L'):
101            return FX_NEW CPDF_RunLenFilter;
102        case FXBSTR_ID('C', 'C', 'I', 'T'): {
103                int Encoding = 0;
104                int bEndOfLine = FALSE;
105                int bByteAlign = FALSE;
106                int bBlack = FALSE;
107                int nRows = 0;
108                int nColumns = 1728;
109                if (pParam) {
110                    Encoding = pParam->GetInteger(FX_BSTRC("K"));
111                    bEndOfLine = pParam->GetInteger(FX_BSTRC("EndOfLine"));
112                    bByteAlign = pParam->GetInteger(FX_BSTRC("EncodedByteAlign"));
113                    bBlack = pParam->GetInteger(FX_BSTRC("BlackIs1"));
114                    nColumns = pParam->GetInteger(FX_BSTRC("Columns"), 1728);
115                    nRows = pParam->GetInteger(FX_BSTRC("Rows"));
116                }
117                if (nColumns == 0) {
118                    nColumns = width;
119                }
120                if (nRows == 0) {
121                    nRows = height;
122                }
123                CPDF_FaxFilter* pFilter = FX_NEW CPDF_FaxFilter();
124                pFilter->Initialize(Encoding, bEndOfLine, bByteAlign, bBlack, nRows, nColumns);
125                return pFilter;
126            }
127        case FXBSTR_ID('D', 'C', 'T', 'D'):
128            return FX_NEW CPDF_JpegFilter;
129        default:
130            return NULL;
131    }
132}
133CFX_DataFilter* _FPDF_CreateFilterFromDict(CPDF_Dictionary* pDict)
134{
135    CPDF_Object* pDecoder = pDict->GetElementValue("Filter");
136    if (pDecoder == NULL) {
137        return NULL;
138    }
139    CFX_DataFilter* pFirstFilter = NULL;
140    int width = pDict->GetInteger(FX_BSTRC("Width")), height = pDict->GetInteger(FX_BSTRC("Height"));
141    CPDF_Object* pParams = pDict->GetElementValue("DecodeParms");
142    if (pDecoder->GetType() == PDFOBJ_ARRAY) {
143        if (pParams && pParams->GetType() != PDFOBJ_ARRAY) {
144            pParams = NULL;
145        }
146        for (FX_DWORD i = 0; i < ((CPDF_Array*)pDecoder)->GetCount(); i ++) {
147            CFX_ByteString name = ((CPDF_Array*)pDecoder)->GetString(i);
148            CPDF_Dictionary* pParam = NULL;
149            if (pParams) {
150                pParam = ((CPDF_Array*)pParams)->GetDict(i);
151            }
152            CFX_DataFilter* pDestFilter = FPDF_CreateFilter(name, pParam, width, height);
153            if (pDestFilter) {
154                if (pFirstFilter == NULL) {
155                    pFirstFilter = pDestFilter;
156                } else {
157                    pFirstFilter->SetDestFilter(pDestFilter);
158                }
159            }
160        }
161    } else {
162        if (pParams && pParams->GetType() != PDFOBJ_DICTIONARY) {
163            pParams = NULL;
164        }
165        pFirstFilter = FPDF_CreateFilter(pDecoder->GetString(), (CPDF_Dictionary*)pParams, width, height);
166    }
167    return pFirstFilter;
168}
169CPDF_StreamFilter* CPDF_Stream::GetStreamFilter(FX_BOOL bRaw) const
170{
171    CFX_DataFilter* pFirstFilter = NULL;
172    if (m_pCryptoHandler) {
173        pFirstFilter = FX_NEW CPDF_DecryptFilter(m_pCryptoHandler, m_ObjNum, m_GenNum);
174    }
175    if (!bRaw) {
176        CFX_DataFilter* pFilter = _FPDF_CreateFilterFromDict(m_pDict);
177        if (pFilter) {
178            if (pFirstFilter == NULL) {
179                pFirstFilter = pFilter;
180            } else {
181                pFirstFilter->SetDestFilter(pFilter);
182            }
183        }
184    }
185    CPDF_StreamFilter* pStreamFilter = FX_NEW CPDF_StreamFilter;
186    pStreamFilter->m_pStream = this;
187    pStreamFilter->m_pFilter = pFirstFilter;
188    pStreamFilter->m_pBuffer = NULL;
189    pStreamFilter->m_SrcOffset = 0;
190    return pStreamFilter;
191}
192CPDF_StreamFilter::~CPDF_StreamFilter()
193{
194    if (m_pFilter) {
195        delete m_pFilter;
196    }
197    if (m_pBuffer) {
198        delete m_pBuffer;
199    }
200}
201#define FPDF_FILTER_BUFFER_IN_SIZE	FPDF_FILTER_BUFFER_SIZE
202FX_DWORD CPDF_StreamFilter::ReadBlock(FX_LPBYTE buffer, FX_DWORD buf_size)
203{
204    if (m_pFilter == NULL) {
205        FX_DWORD read_size = m_pStream->GetRawSize() - m_SrcOffset;
206        if (read_size == 0) {
207            return 0;
208        }
209        if (read_size > buf_size) {
210            read_size = buf_size;
211        }
212        m_pStream->ReadRawData(m_SrcOffset, buffer, read_size);
213        m_SrcOffset += read_size;
214        return read_size;
215    }
216    FX_DWORD read_size = 0;
217    if (m_pBuffer) {
218        read_size = ReadLeftOver(buffer, buf_size);
219        if (read_size == buf_size) {
220            return read_size;
221        }
222        buffer += read_size;
223        buf_size -= read_size;
224    }
225    ASSERT(m_pBuffer == NULL);
226    if (m_pFilter->IsEOF()) {
227        return read_size;
228    }
229    m_pBuffer = FX_NEW CFX_BinaryBuf;
230    m_pBuffer->EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);
231    m_BufOffset = 0;
232    while (1) {
233        int src_size = m_pStream->GetRawSize() - m_SrcOffset;
234        if (src_size == 0) {
235            m_pFilter->FilterFinish(*m_pBuffer);
236            break;
237        }
238        if (src_size > FPDF_FILTER_BUFFER_IN_SIZE) {
239            src_size = FPDF_FILTER_BUFFER_IN_SIZE;
240        }
241        if (!m_pStream->ReadRawData(m_SrcOffset, m_SrcBuffer, src_size)) {
242            return 0;
243        }
244        m_SrcOffset += src_size;
245        m_pFilter->FilterIn(m_SrcBuffer, src_size, *m_pBuffer);
246        if (m_pBuffer->GetSize() >= (int)buf_size) {
247            break;
248        }
249    }
250    return read_size + ReadLeftOver(buffer, buf_size);
251}
252FX_DWORD CPDF_StreamFilter::ReadLeftOver(FX_LPBYTE buffer, FX_DWORD buf_size)
253{
254    FX_DWORD read_size = m_pBuffer->GetSize() - m_BufOffset;
255    if (read_size > buf_size) {
256        read_size = buf_size;
257    }
258    FXSYS_memcpy32(buffer, m_pBuffer->GetBuffer() + m_BufOffset, read_size);
259    m_BufOffset += read_size;
260    if (m_BufOffset == (FX_DWORD)m_pBuffer->GetSize()) {
261        delete m_pBuffer;
262        m_pBuffer = NULL;
263    }
264    return read_size;
265}
266CPDF_DecryptFilter::CPDF_DecryptFilter(CPDF_CryptoHandler* pCryptoHandler, FX_DWORD objnum, FX_DWORD gennum)
267{
268    m_pCryptoHandler = pCryptoHandler;
269    m_pContext = NULL;
270    m_ObjNum = objnum;
271    m_GenNum = gennum;
272}
273CPDF_DecryptFilter::~CPDF_DecryptFilter()
274{
275    CFX_BinaryBuf buf;
276    if (m_pContext) {
277        m_pCryptoHandler->DecryptFinish(m_pContext, buf);
278    }
279}
280void CPDF_DecryptFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
281{
282    if (m_pContext == NULL) {
283        m_pContext = m_pCryptoHandler->DecryptStart(m_ObjNum, m_GenNum);
284    }
285    m_pCryptoHandler->DecryptStream(m_pContext, src_buf, src_size, dest_buf);
286}
287void CPDF_DecryptFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf)
288{
289    m_bEOF = TRUE;
290    if (m_pContext == NULL) {
291        return;
292    }
293    m_pCryptoHandler->DecryptFinish(m_pContext, dest_buf);
294    m_pContext = NULL;
295}
296extern "C" {
297    static void* my_alloc_func (void* opaque, unsigned int items, unsigned int size)
298    {
299        return FX_Alloc(FX_BYTE, items * size);
300    }
301    static void   my_free_func  (void* opaque, void* address)
302    {
303        FX_Free(address);
304    }
305    void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int),
306                            void (*free_func)(void*, void*));
307    void FPDFAPI_FlateInput(void* context, const unsigned char* src_buf, unsigned int src_size);
308    int FPDFAPI_FlateOutput(void* context, unsigned char* dest_buf, unsigned int dest_size);
309    int FPDFAPI_FlateGetAvailIn(void* context);
310    int FPDFAPI_FlateGetAvailOut(void* context);
311    void FPDFAPI_FlateEnd(void* context);
312}
313CPDF_FlateFilter::CPDF_FlateFilter()
314{
315    m_pContext = NULL;
316}
317CPDF_FlateFilter::~CPDF_FlateFilter()
318{
319    if (m_pContext) {
320        FPDFAPI_FlateEnd(m_pContext);
321    }
322}
323void CPDF_FlateFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
324{
325    if (m_pContext == NULL) {
326        m_pContext = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
327    }
328    FPDFAPI_FlateInput(m_pContext, src_buf, src_size);
329    while (1) {
330        int ret = FPDFAPI_FlateOutput(m_pContext, m_DestBuffer, FPDF_FILTER_BUFFER_SIZE);
331        int out_size = FPDF_FILTER_BUFFER_SIZE - FPDFAPI_FlateGetAvailOut(m_pContext);
332        dest_buf.AppendBlock(m_DestBuffer, out_size);
333        if (ret == Z_BUF_ERROR) {
334            break;
335        }
336        if (ret != Z_OK) {
337            ReportEOF(FPDFAPI_FlateGetAvailIn(m_pContext));
338            break;
339        }
340    }
341}
342CPDF_LzwFilter::CPDF_LzwFilter(FX_BOOL bEarlyChange)
343{
344    m_bEarlyChange = bEarlyChange ? 1 : 0;
345    m_CodeLen = 9;
346    m_nCodes = 0;
347    m_nLeftBits = 0;
348    m_LeftBits = 0;
349    m_OldCode = (FX_DWORD) - 1;
350}
351void CPDF_LzwFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
352{
353    for (FX_DWORD i = 0; i < src_size; i ++) {
354        if (m_nLeftBits + 8 < m_CodeLen) {
355            m_nLeftBits += 8;
356            m_LeftBits = (m_LeftBits << 8) | src_buf[i];
357            continue;
358        }
359        FX_DWORD new_bits = m_CodeLen - m_nLeftBits;
360        FX_DWORD code = (m_LeftBits << new_bits) | (src_buf[i] >> (8 - new_bits));
361        m_nLeftBits = 8 - new_bits;
362        m_LeftBits = src_buf[i] % (1 << m_nLeftBits);
363        if (code < 256) {
364            dest_buf.AppendByte((FX_BYTE)code);
365            m_LastChar = (FX_BYTE)code;
366            if (m_OldCode != -1) {
367                AddCode(m_OldCode, m_LastChar);
368            }
369            m_OldCode = code;
370        } else if (code == 256) {
371            m_CodeLen = 9;
372            m_nCodes = 0;
373            m_OldCode = (FX_DWORD) - 1;
374        } else if (code == 257) {
375            ReportEOF(src_size - i - 1);
376            return;
377        } else {
378            if (m_OldCode == -1) {
379                ReportEOF(src_size - i - 1);
380                return;
381            }
382            m_StackLen = 0;
383            if (code >= m_nCodes + 258) {
384                if (m_StackLen < sizeof(m_DecodeStack)) {
385                    m_DecodeStack[m_StackLen++] = m_LastChar;
386                }
387                DecodeString(m_OldCode);
388            } else {
389                DecodeString(code);
390            }
391            dest_buf.AppendBlock(NULL, m_StackLen);
392            FX_LPBYTE pOutput = dest_buf.GetBuffer() + dest_buf.GetSize() - m_StackLen;
393            for (FX_DWORD cc = 0; cc < m_StackLen; cc ++) {
394                pOutput[cc] = m_DecodeStack[m_StackLen - cc - 1];
395            }
396            m_LastChar = m_DecodeStack[m_StackLen - 1];
397            if (m_OldCode < 256) {
398                AddCode(m_OldCode, m_LastChar);
399            } else if (m_OldCode - 258 >= m_nCodes) {
400                ReportEOF(src_size - i - 1);
401                return;
402            } else {
403                AddCode(m_OldCode, m_LastChar);
404            }
405            m_OldCode = code;
406        }
407    }
408}
409void CPDF_LzwFilter::AddCode(FX_DWORD prefix_code, FX_BYTE append_char)
410{
411    if (m_nCodes + m_bEarlyChange == 4094) {
412        return;
413    }
414    m_CodeArray[m_nCodes ++] = (prefix_code << 16) | append_char;
415    if (m_nCodes + m_bEarlyChange == 512 - 258) {
416        m_CodeLen = 10;
417    } else if (m_nCodes + m_bEarlyChange == 1024 - 258) {
418        m_CodeLen = 11;
419    } else if (m_nCodes + m_bEarlyChange == 2048 - 258) {
420        m_CodeLen = 12;
421    }
422}
423void CPDF_LzwFilter::DecodeString(FX_DWORD code)
424{
425    while (1) {
426        int index = code - 258;
427        if (index < 0 || index >= (int)m_nCodes) {
428            break;
429        }
430        FX_DWORD data = m_CodeArray[index];
431        if (m_StackLen >= sizeof(m_DecodeStack)) {
432            return;
433        }
434        m_DecodeStack[m_StackLen++] = (FX_BYTE)data;
435        code = data >> 16;
436    }
437    if (m_StackLen >= sizeof(m_DecodeStack)) {
438        return;
439    }
440    m_DecodeStack[m_StackLen++] = (FX_BYTE)code;
441}
442CPDF_PredictorFilter::CPDF_PredictorFilter(int predictor, int colors, int bpc, int cols)
443{
444    m_bTiff = predictor < 10;
445    m_pRefLine = NULL;
446    m_pCurLine = NULL;
447    m_iLine = 0;
448    m_LineInSize = 0;
449    m_Bpp = (colors * bpc + 7) / 8;
450    m_Pitch = (colors * bpc * cols + 7) / 8;
451    if (!m_bTiff) {
452        m_Pitch ++;
453    }
454}
455CPDF_PredictorFilter::~CPDF_PredictorFilter()
456{
457    if (m_pCurLine) {
458        FX_Free(m_pCurLine);
459    }
460    if (m_pRefLine) {
461        FX_Free(m_pRefLine);
462    }
463}
464static FX_BYTE PaethPredictor(int a, int b, int c)
465{
466    int p = a + b - c;
467    int pa = FXSYS_abs(p - a);
468    int pb = FXSYS_abs(p - b);
469    int pc = FXSYS_abs(p - c);
470    if (pa <= pb && pa <= pc) {
471        return (FX_BYTE)a;
472    }
473    if (pb <= pc) {
474        return (FX_BYTE)b;
475    }
476    return (FX_BYTE)c;
477}
478static void PNG_PredictorLine(FX_LPBYTE cur_buf, FX_LPBYTE ref_buf, int pitch, int Bpp)
479{
480    FX_BYTE tag = cur_buf[0];
481    if (tag == 0) {
482        return;
483    }
484    cur_buf ++;
485    if (ref_buf) {
486        ref_buf ++;
487    }
488    for (int byte = 0; byte < pitch; byte ++) {
489        FX_BYTE raw_byte = cur_buf[byte];
490        switch (tag) {
491            case 1:	{
492                    FX_BYTE left = 0;
493                    if (byte >= Bpp) {
494                        left = cur_buf[byte - Bpp];
495                    }
496                    cur_buf[byte] = raw_byte + left;
497                    break;
498                }
499            case 2: {
500                    FX_BYTE up = 0;
501                    if (ref_buf) {
502                        up = ref_buf[byte];
503                    }
504                    cur_buf[byte] = raw_byte + up;
505                    break;
506                }
507            case 3: {
508                    FX_BYTE left = 0;
509                    if (byte >= Bpp) {
510                        left = cur_buf[byte - Bpp];
511                    }
512                    FX_BYTE up = 0;
513                    if (ref_buf) {
514                        up = ref_buf[byte];
515                    }
516                    cur_buf[byte] = raw_byte + (up + left) / 2;
517                    break;
518                }
519            case 4: {
520                    FX_BYTE left = 0;
521                    if (byte >= Bpp) {
522                        left = cur_buf[byte - Bpp];
523                    }
524                    FX_BYTE up = 0;
525                    if (ref_buf) {
526                        up = ref_buf[byte];
527                    }
528                    FX_BYTE upper_left = 0;
529                    if (byte >= Bpp && ref_buf) {
530                        upper_left = ref_buf[byte - Bpp];
531                    }
532                    cur_buf[byte] = raw_byte + PaethPredictor(left, up, upper_left);
533                    break;
534                }
535        }
536    }
537}
538void CPDF_PredictorFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
539{
540    if (m_pCurLine == NULL) {
541        m_pCurLine = FX_Alloc(FX_BYTE, m_Pitch);
542        if (!m_bTiff) {
543            m_pRefLine = FX_Alloc(FX_BYTE, m_Pitch);
544        }
545    }
546    while (1) {
547        FX_DWORD read_size = m_Pitch - m_LineInSize;
548        if (read_size > src_size) {
549            read_size = src_size;
550        }
551        FXSYS_memcpy32(m_pCurLine + m_LineInSize, src_buf, read_size);
552        m_LineInSize += read_size;
553        if (m_LineInSize < m_Pitch) {
554            break;
555        }
556        src_buf += read_size;
557        src_size -= read_size;
558        if (m_bTiff) {
559            for (FX_DWORD byte = m_Bpp; byte < m_Pitch; byte ++) {
560                m_pCurLine[byte] += m_pCurLine[byte - m_Bpp];
561            }
562            dest_buf.AppendBlock(m_pCurLine, m_Pitch);
563        } else {
564            PNG_PredictorLine(m_pCurLine, m_iLine ? m_pRefLine : NULL, m_Pitch - 1, m_Bpp);
565            dest_buf.AppendBlock(m_pCurLine + 1, m_Pitch - 1);
566            m_iLine ++;
567            FX_LPBYTE temp = m_pCurLine;
568            m_pCurLine = m_pRefLine;
569            m_pRefLine = temp;
570        }
571        m_LineInSize = 0;
572    }
573}
574CPDF_Ascii85Filter::CPDF_Ascii85Filter()
575{
576    m_State = 0;
577    m_CharCount = 0;
578}
579extern const FX_LPCSTR _PDF_CharType;
580void CPDF_Ascii85Filter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
581{
582    for (FX_DWORD i = 0; i < src_size; i ++) {
583        FX_BYTE byte = src_buf[i];
584        if (_PDF_CharType[byte] == 'W') {
585            continue;
586        }
587        switch (m_State) {
588            case 0:
589                if (byte >= '!' && byte <= 'u') {
590                    int digit = byte - '!';
591                    m_CurDWord = digit;
592                    m_CharCount = 1;
593                    m_State = 1;
594                } else if (byte == 'z') {
595                    int zero = 0;
596                    dest_buf.AppendBlock(&zero, 4);
597                } else if (byte == '~') {
598                    m_State = 2;
599                }
600                break;
601            case 1: {
602                    if (byte >= '!' && byte <= 'u') {
603                        int digit = byte - '!';
604                        m_CurDWord = m_CurDWord * 85 + digit;
605                        m_CharCount ++;
606                        if (m_CharCount == 5) {
607                            for (int i = 0; i < 4; i ++) {
608                                dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8));
609                            }
610                            m_State = 0;
611                        }
612                    } else if (byte == '~') {
613                        if (m_CharCount > 1) {
614                            int i;
615                            for (i = m_CharCount; i < 5; i ++) {
616                                m_CurDWord = m_CurDWord * 85 + 84;
617                            }
618                            for (i = 0; i < m_CharCount - 1; i ++) {
619                                dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8));
620                            }
621                        }
622                        m_State = 2;
623                    }
624                    break;
625                }
626            case 2:
627                if (byte == '>') {
628                    ReportEOF(src_size - i - 1);
629                    return;
630                }
631                break;
632        }
633    }
634}
635CPDF_AsciiHexFilter::CPDF_AsciiHexFilter()
636{
637    m_State = 0;
638}
639void CPDF_AsciiHexFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
640{
641    for (FX_DWORD i = 0; i < src_size; i ++) {
642        FX_BYTE byte = src_buf[i];
643        if (_PDF_CharType[byte] == 'W') {
644            continue;
645        }
646        int digit;
647        if (byte >= '0' && byte <= '9') {
648            digit = byte - '0';
649        } else if (byte >= 'a' && byte <= 'f') {
650            digit = byte - 'a' + 10;
651        } else if (byte >= 'A' && byte <= 'F') {
652            digit = byte - 'A' + 10;
653        } else {
654            if (m_State) {
655                dest_buf.AppendByte(m_FirstDigit * 16);
656            }
657            ReportEOF(src_size - i - 1);
658            return;
659        }
660        if (m_State == 0) {
661            m_FirstDigit = digit;
662            m_State ++;
663        } else {
664            dest_buf.AppendByte(m_FirstDigit * 16 + digit);
665            m_State --;
666        }
667    }
668}
669CPDF_RunLenFilter::CPDF_RunLenFilter()
670{
671    m_State = 0;
672    m_Count = 0;
673}
674void CPDF_RunLenFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
675{
676    for (FX_DWORD i = 0; i < src_size; i ++) {
677        FX_BYTE byte = src_buf[i];
678        switch (m_State) {
679            case 0:
680                if (byte < 128) {
681                    m_State = 1;
682                    m_Count = byte + 1;
683                } else if (byte == 128) {
684                    ReportEOF(src_size - i - 1);
685                    return;
686                } else {
687                    m_State = 2;
688                    m_Count = 257 - byte;
689                }
690                break;
691            case 1:
692                dest_buf.AppendByte(byte);
693                m_Count --;
694                if (m_Count == 0) {
695                    m_State = 0;
696                }
697                break;
698            case 2:	{
699                    dest_buf.AppendBlock(NULL, m_Count);
700                    FXSYS_memset8(dest_buf.GetBuffer() + dest_buf.GetSize() - m_Count, byte, m_Count);
701                    m_State = 0;
702                    break;
703                }
704        }
705    }
706}
707CPDF_JpegFilter::CPDF_JpegFilter()
708{
709    m_pContext = NULL;
710    m_bGotHeader = FALSE;
711    m_pScanline = NULL;
712    m_iLine = 0;
713}
714CPDF_JpegFilter::~CPDF_JpegFilter()
715{
716    if (m_pScanline) {
717        FX_Free(m_pScanline);
718    }
719    if (m_pContext) {
720        CPDF_ModuleMgr::Get()->GetJpegModule()->Finish(m_pContext);
721    }
722}
723void CPDF_JpegFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
724{
725    if (m_pContext == NULL) {
726        m_pContext = CPDF_ModuleMgr::Get()->GetJpegModule()->Start();
727    }
728    FX_LPCBYTE jpeg_src_buf;
729    FX_DWORD jpeg_src_size;
730    CFX_BinaryBuf temp_buf;
731    if (m_InputBuf.GetSize()) {
732        temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size);
733        temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize());
734        m_InputBuf.Clear();
735        temp_buf.AppendBlock(src_buf, src_size);
736        jpeg_src_buf = temp_buf.GetBuffer();
737        jpeg_src_size = temp_buf.GetSize();
738    } else {
739        jpeg_src_buf = src_buf;
740        jpeg_src_size = src_size;
741    }
742    CPDF_ModuleMgr::Get()->GetJpegModule()->Input(m_pContext, jpeg_src_buf, jpeg_src_size);
743    if (!m_bGotHeader) {
744        int ret = CPDF_ModuleMgr::Get()->GetJpegModule()->ReadHeader(m_pContext, &m_Width, &m_Height, &m_nComps);
745        int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext);
746        if (ret == 1) {
747            ReportEOF(left_size);
748            return;
749        }
750        if (ret == 2) {
751            m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size);
752            return;
753        }
754        CPDF_ModuleMgr::Get()->GetJpegModule()->StartScanline(m_pContext, 1);
755        m_bGotHeader = TRUE;
756        m_Pitch = m_Width * m_nComps;
757    }
758    if (m_pScanline == NULL) {
759        m_pScanline = FX_Alloc(FX_BYTE, m_Pitch + 4);
760    }
761    while (1) {
762        if (!CPDF_ModuleMgr::Get()->GetJpegModule()->ReadScanline(m_pContext, m_pScanline)) {
763            int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext);
764            m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size);
765            break;
766        }
767        dest_buf.AppendBlock(m_pScanline, m_Pitch);
768        m_iLine ++;
769        if (m_iLine == m_Height) {
770            ReportEOF(CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext));
771            return;
772        }
773    }
774}
775CPDF_FaxFilter::CPDF_FaxFilter()
776{
777    m_Encoding = 0;
778    m_bEndOfLine = FALSE;
779    m_bByteAlign = FALSE;
780    m_bBlack = FALSE;
781    m_nRows = 0;
782    m_nColumns = 0;
783    m_Pitch = 0;
784    m_pScanlineBuf = NULL;
785    m_pRefBuf = NULL;
786    m_iRow = 0;
787    m_InputBitPos = 0;
788}
789CPDF_FaxFilter::~CPDF_FaxFilter()
790{
791    if (m_pScanlineBuf) {
792        FX_Free(m_pScanlineBuf);
793    }
794    if (m_pRefBuf) {
795        FX_Free(m_pRefBuf);
796    }
797}
798FX_BOOL CPDF_FaxFilter::Initialize(int Encoding, int bEndOfLine, int bByteAlign, int bBlack, int nRows, int nColumns)
799{
800    m_Encoding = Encoding;
801    m_bEndOfLine = bEndOfLine;
802    m_bByteAlign = bByteAlign;
803    m_bBlack = bBlack;
804    m_nRows = nRows;
805    m_nColumns = nColumns;
806    m_Pitch = (m_nColumns + 7) / 8;
807    m_pScanlineBuf = FX_Alloc(FX_BYTE, m_Pitch);
808    m_pRefBuf = FX_Alloc(FX_BYTE, m_Pitch);
809    FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch);
810    FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch);
811    m_iRow = 0;
812    m_InputBitPos = 0;
813    return TRUE;
814}
815void CPDF_FaxFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
816{
817    FX_LPCBYTE fax_src_buf;
818    FX_DWORD fax_src_size;
819    CFX_BinaryBuf temp_buf;
820    int bitpos;
821    if (m_InputBuf.GetSize()) {
822        temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size);
823        temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize());
824        m_InputBuf.Clear();
825        temp_buf.AppendBlock(src_buf, src_size);
826        fax_src_buf = temp_buf.GetBuffer();
827        fax_src_size = temp_buf.GetSize();
828        bitpos = m_InputBitPos;
829    } else {
830        fax_src_buf = src_buf;
831        fax_src_size = src_size;
832        bitpos = 0;
833    }
834    ProcessData(fax_src_buf, fax_src_size, bitpos, FALSE, dest_buf);
835    int left_bits = fax_src_size * 8 - bitpos;
836    m_InputBuf.AppendBlock(fax_src_buf + bitpos / 8, (left_bits + 7) / 8);
837    m_InputBitPos = bitpos % 8;
838}
839void CPDF_FaxFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf)
840{
841    ProcessData(m_InputBuf.GetBuffer(), m_InputBuf.GetSize(), m_InputBitPos, TRUE, dest_buf);
842}
843FX_BOOL _FaxSkipEOL(const FX_BYTE* src_buf, int bitsize, int& bitpos);
844FX_BOOL _FaxG4GetRow(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, const FX_BYTE* ref_buf, int columns);
845FX_BOOL _FaxGet1DLine(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, int columns);
846void CPDF_FaxFilter::ProcessData(FX_LPCBYTE src_buf, FX_DWORD src_size, int& bitpos, FX_BOOL bFinish,
847                                 CFX_BinaryBuf& dest_buf)
848{
849    int bitsize = src_size * 8;
850    while (1) {
851        if ((bitsize < bitpos + 256) && !bFinish) {
852            return;
853        }
854        int start_bitpos = bitpos;
855        FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch);
856        if (!ReadLine(src_buf, bitsize, bitpos)) {
857            bitpos = start_bitpos;
858            return;
859        }
860        if (m_Encoding) {
861            FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch);
862        }
863        if (m_bBlack) {
864            for (int i = 0; i < m_Pitch; i ++) {
865                m_pScanlineBuf[i] = ~m_pScanlineBuf[i];
866            }
867        }
868        dest_buf.AppendBlock(m_pScanlineBuf, m_Pitch);
869        m_iRow ++;
870        if (m_iRow == m_nRows) {
871            ReportEOF(src_size - (bitpos + 7) / 8);
872            return;
873        }
874    }
875}
876FX_BOOL CPDF_FaxFilter::ReadLine(FX_LPCBYTE src_buf, int bitsize, int& bitpos)
877{
878    if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) {
879        return FALSE;
880    }
881    FX_BOOL ret;
882    if (m_Encoding < 0) {
883        ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns);
884    } else if (m_Encoding == 0) {
885        ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns);
886    } else {
887        if (bitpos == bitsize) {
888            return FALSE;
889        }
890        FX_BOOL bNext1D = src_buf[bitpos / 8] & (1 << (7 - bitpos % 8));
891        bitpos ++;
892        if (bNext1D) {
893            ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns);
894        } else {
895            ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns);
896        }
897    }
898    if (!ret) {
899        return FALSE;
900    }
901    if (m_bEndOfLine)
902        if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) {
903            return FALSE;
904        }
905    if (m_bByteAlign) {
906        bitpos = (bitpos + 7) / 8 * 8;
907    }
908    return TRUE;
909}
910