ead5e2474aa47b63af319479cbf12e9aee6b391f
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_filters.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../../include/fpdfapi/fpdf_parser.h"
8 #include "../../../include/fxcodec/fx_codec.h"
9 #include "../../../include/fpdfapi/fpdf_module.h"
10 #include "../../fxcodec/fx_zlib/include/fx_zlib.h"
11 #include "filters_int.h"
12
13 CFX_DataFilter::CFX_DataFilter()
14 {
15     m_bEOF = FALSE;
16     m_pDestFilter = NULL;
17     m_SrcPos = 0;
18 }
19 CFX_DataFilter::~CFX_DataFilter()
20 {
21     if (m_pDestFilter) {
22         delete m_pDestFilter;
23     }
24 }
25 void CFX_DataFilter::SetDestFilter(CFX_DataFilter* pFilter)
26 {
27     if (m_pDestFilter) {
28         m_pDestFilter->SetDestFilter(pFilter);
29     } else {
30         m_pDestFilter = pFilter;
31     }
32 }
33 void CFX_DataFilter::FilterIn(const uint8_t* src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
34 {
35     if (m_bEOF) {
36         return;
37     }
38     m_SrcPos += src_size;
39     if (m_pDestFilter) {
40         CFX_BinaryBuf temp_buf;
41         temp_buf.EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);
42         v_FilterIn(src_buf, src_size, temp_buf);
43         m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf);
44     } else {
45         v_FilterIn(src_buf, src_size, dest_buf);
46     }
47 }
48 void CFX_DataFilter::FilterFinish(CFX_BinaryBuf& dest_buf)
49 {
50     if (m_pDestFilter) {
51         CFX_BinaryBuf temp_buf;
52         v_FilterFinish(temp_buf);
53         if (temp_buf.GetSize()) {
54             m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf);
55         }
56         m_pDestFilter->FilterFinish(dest_buf);
57     } else {
58         v_FilterFinish(dest_buf);
59     }
60     m_bEOF = TRUE;
61 }
62 void CFX_DataFilter::ReportEOF(FX_DWORD left_input)
63 {
64     if (m_bEOF) {
65         return;
66     }
67     m_bEOF = TRUE;
68     m_SrcPos -= left_input;
69 }
70 CFX_DataFilter* FPDF_CreateFilter(const CFX_ByteStringC& name, const CPDF_Dictionary* pParam, int width, int height)
71 {
72     FX_DWORD id = name.GetID();
73     switch (id) {
74         case FXBSTR_ID('F', 'l', 'a', 't'):
75         case FXBSTR_ID('F', 'l', 0, 0):
76         case FXBSTR_ID('L', 'Z', 'W', 'D'):
77         case FXBSTR_ID('L', 'Z', 'W', 0): {
78                 CFX_DataFilter* pFilter;
79                 if (id == FXBSTR_ID('L', 'Z', 'W', 'D') || id == FXBSTR_ID('L', 'Z', 'W', 0)) {
80                     pFilter = new CPDF_LzwFilter(pParam ? pParam->GetInteger("EarlyChange", 1) : 1);
81                 } else {
82                     pFilter = new CPDF_FlateFilter;
83                 }
84                 if ((pParam ? pParam->GetInteger("Predictor", 1) : 1) > 1) {
85                     CFX_DataFilter* pPredictor = new CPDF_PredictorFilter(pParam->GetInteger(FX_BSTRC("Predictor"), 1),
86                                                  pParam->GetInteger(FX_BSTRC("Colors"), 1), pParam->GetInteger(FX_BSTRC("BitsPerComponent"), 8),
87                                                  pParam->GetInteger(FX_BSTRC("Columns"), 1));
88                     pFilter->SetDestFilter(pPredictor);
89                 }
90                 return pFilter;
91             }
92         case FXBSTR_ID('A', 'S', 'C', 'I'):
93             if (name == "ASCIIHexDecode") {
94                 return new CPDF_AsciiHexFilter;
95             }
96             return new CPDF_Ascii85Filter;
97         case FXBSTR_ID('A', 'H', 'x', 0):
98             return new CPDF_AsciiHexFilter;
99         case FXBSTR_ID('A', '8', '5', 0):
100             return new CPDF_Ascii85Filter;
101         case FXBSTR_ID('R', 'u', 'n', 'L'):
102             return new CPDF_RunLenFilter;
103         case FXBSTR_ID('C', 'C', 'I', 'T'): {
104                 int Encoding = 0;
105                 int bEndOfLine = FALSE;
106                 int bByteAlign = FALSE;
107                 int bBlack = FALSE;
108                 int nRows = 0;
109                 int nColumns = 1728;
110                 if (pParam) {
111                     Encoding = pParam->GetInteger(FX_BSTRC("K"));
112                     bEndOfLine = pParam->GetInteger(FX_BSTRC("EndOfLine"));
113                     bByteAlign = pParam->GetInteger(FX_BSTRC("EncodedByteAlign"));
114                     bBlack = pParam->GetInteger(FX_BSTRC("BlackIs1"));
115                     nColumns = pParam->GetInteger(FX_BSTRC("Columns"), 1728);
116                     nRows = pParam->GetInteger(FX_BSTRC("Rows"));
117                 }
118                 if (nColumns == 0) {
119                     nColumns = width;
120                 }
121                 if (nRows == 0) {
122                     nRows = height;
123                 }
124                 CPDF_FaxFilter* pFilter = new CPDF_FaxFilter();
125                 pFilter->Initialize(Encoding, bEndOfLine, bByteAlign, bBlack, nRows, nColumns);
126                 return pFilter;
127             }
128         case FXBSTR_ID('D', 'C', 'T', 'D'):
129             return new CPDF_JpegFilter;
130         default:
131             return NULL;
132     }
133 }
134 CFX_DataFilter* _FPDF_CreateFilterFromDict(CPDF_Dictionary* pDict)
135 {
136     CPDF_Object* pDecoder = pDict->GetElementValue("Filter");
137     if (pDecoder == NULL) {
138         return NULL;
139     }
140     CFX_DataFilter* pFirstFilter = NULL;
141     int width = pDict->GetInteger(FX_BSTRC("Width")), height = pDict->GetInteger(FX_BSTRC("Height"));
142     CPDF_Object* pParams = pDict->GetElementValue("DecodeParms");
143     if (pDecoder->GetType() == PDFOBJ_ARRAY) {
144         if (pParams && pParams->GetType() != PDFOBJ_ARRAY) {
145             pParams = NULL;
146         }
147         for (FX_DWORD i = 0; i < ((CPDF_Array*)pDecoder)->GetCount(); i ++) {
148             CFX_ByteString name = ((CPDF_Array*)pDecoder)->GetString(i);
149             CPDF_Dictionary* pParam = NULL;
150             if (pParams) {
151                 pParam = ((CPDF_Array*)pParams)->GetDict(i);
152             }
153             CFX_DataFilter* pDestFilter = FPDF_CreateFilter(name, pParam, width, height);
154             if (pDestFilter) {
155                 if (pFirstFilter == NULL) {
156                     pFirstFilter = pDestFilter;
157                 } else {
158                     pFirstFilter->SetDestFilter(pDestFilter);
159                 }
160             }
161         }
162     } else {
163         if (pParams && pParams->GetType() != PDFOBJ_DICTIONARY) {
164             pParams = NULL;
165         }
166         pFirstFilter = FPDF_CreateFilter(pDecoder->GetString(), (CPDF_Dictionary*)pParams, width, height);
167     }
168     return pFirstFilter;
169 }
170 CPDF_StreamFilter* CPDF_Stream::GetStreamFilter(FX_BOOL bRaw) const
171 {
172     CFX_DataFilter* pFirstFilter = NULL;
173     if (m_pCryptoHandler) {
174         pFirstFilter = new CPDF_DecryptFilter(m_pCryptoHandler, m_ObjNum, m_GenNum);
175     }
176     if (!bRaw) {
177         CFX_DataFilter* pFilter = _FPDF_CreateFilterFromDict(m_pDict);
178         if (pFilter) {
179             if (pFirstFilter == NULL) {
180                 pFirstFilter = pFilter;
181             } else {
182                 pFirstFilter->SetDestFilter(pFilter);
183             }
184         }
185     }
186     CPDF_StreamFilter* pStreamFilter = new CPDF_StreamFilter;
187     pStreamFilter->m_pStream = this;
188     pStreamFilter->m_pFilter = pFirstFilter;
189     pStreamFilter->m_pBuffer = NULL;
190     pStreamFilter->m_SrcOffset = 0;
191     return pStreamFilter;
192 }
193 CPDF_StreamFilter::~CPDF_StreamFilter()
194 {
195     if (m_pFilter) {
196         delete m_pFilter;
197     }
198     if (m_pBuffer) {
199         delete m_pBuffer;
200     }
201 }
202 #define FPDF_FILTER_BUFFER_IN_SIZE      FPDF_FILTER_BUFFER_SIZE
203 FX_DWORD CPDF_StreamFilter::ReadBlock(uint8_t* buffer, FX_DWORD buf_size)
204 {
205     if (m_pFilter == NULL) {
206         FX_DWORD read_size = m_pStream->GetRawSize() - m_SrcOffset;
207         if (read_size == 0) {
208             return 0;
209         }
210         if (read_size > buf_size) {
211             read_size = buf_size;
212         }
213         m_pStream->ReadRawData(m_SrcOffset, buffer, read_size);
214         m_SrcOffset += read_size;
215         return read_size;
216     }
217     FX_DWORD read_size = 0;
218     if (m_pBuffer) {
219         read_size = ReadLeftOver(buffer, buf_size);
220         if (read_size == buf_size) {
221             return read_size;
222         }
223         buffer += read_size;
224         buf_size -= read_size;
225     }
226     ASSERT(m_pBuffer == NULL);
227     if (m_pFilter->IsEOF()) {
228         return read_size;
229     }
230     m_pBuffer = new CFX_BinaryBuf;
231     m_pBuffer->EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);
232     m_BufOffset = 0;
233     while (1) {
234         int src_size = m_pStream->GetRawSize() - m_SrcOffset;
235         if (src_size == 0) {
236             m_pFilter->FilterFinish(*m_pBuffer);
237             break;
238         }
239         if (src_size > FPDF_FILTER_BUFFER_IN_SIZE) {
240             src_size = FPDF_FILTER_BUFFER_IN_SIZE;
241         }
242         if (!m_pStream->ReadRawData(m_SrcOffset, m_SrcBuffer, src_size)) {
243             return 0;
244         }
245         m_SrcOffset += src_size;
246         m_pFilter->FilterIn(m_SrcBuffer, src_size, *m_pBuffer);
247         if (m_pBuffer->GetSize() >= (int)buf_size) {
248             break;
249         }
250     }
251     return read_size + ReadLeftOver(buffer, buf_size);
252 }
253 FX_DWORD CPDF_StreamFilter::ReadLeftOver(uint8_t* buffer, FX_DWORD buf_size)
254 {
255     FX_DWORD read_size = m_pBuffer->GetSize() - m_BufOffset;
256     if (read_size > buf_size) {
257         read_size = buf_size;
258     }
259     FXSYS_memcpy(buffer, m_pBuffer->GetBuffer() + m_BufOffset, read_size);
260     m_BufOffset += read_size;
261     if (m_BufOffset == (FX_DWORD)m_pBuffer->GetSize()) {
262         delete m_pBuffer;
263         m_pBuffer = NULL;
264     }
265     return read_size;
266 }
267 CPDF_DecryptFilter::CPDF_DecryptFilter(CPDF_CryptoHandler* pCryptoHandler, FX_DWORD objnum, FX_DWORD gennum)
268 {
269     m_pCryptoHandler = pCryptoHandler;
270     m_pContext = NULL;
271     m_ObjNum = objnum;
272     m_GenNum = gennum;
273 }
274 CPDF_DecryptFilter::~CPDF_DecryptFilter()
275 {
276     CFX_BinaryBuf buf;
277     if (m_pContext) {
278         m_pCryptoHandler->DecryptFinish(m_pContext, buf);
279     }
280 }
281 void CPDF_DecryptFilter::v_FilterIn(const uint8_t* src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
282 {
283     if (m_pContext == NULL) {
284         m_pContext = m_pCryptoHandler->DecryptStart(m_ObjNum, m_GenNum);
285     }
286     m_pCryptoHandler->DecryptStream(m_pContext, src_buf, src_size, dest_buf);
287 }
288 void CPDF_DecryptFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf)
289 {
290     m_bEOF = TRUE;
291     if (m_pContext == NULL) {
292         return;
293     }
294     m_pCryptoHandler->DecryptFinish(m_pContext, dest_buf);
295     m_pContext = NULL;
296 }
297 extern "C" {
298     static void* my_alloc_func (void* opaque, unsigned int items, unsigned int size)
299     {
300         return FX_Alloc2D(uint8_t, items, size);
301     }
302     static void   my_free_func  (void* opaque, void* address)
303     {
304         FX_Free(address);
305     }
306     void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int),
307                             void (*free_func)(void*, void*));
308     void FPDFAPI_FlateInput(void* context, const unsigned char* src_buf, unsigned int src_size);
309     int FPDFAPI_FlateOutput(void* context, unsigned char* dest_buf, unsigned int dest_size);
310     int FPDFAPI_FlateGetAvailIn(void* context);
311     int FPDFAPI_FlateGetAvailOut(void* context);
312     void FPDFAPI_FlateEnd(void* context);
313 }
314 CPDF_FlateFilter::CPDF_FlateFilter()
315 {
316     m_pContext = NULL;
317 }
318 CPDF_FlateFilter::~CPDF_FlateFilter()
319 {
320     if (m_pContext) {
321         FPDFAPI_FlateEnd(m_pContext);
322     }
323 }
324 void CPDF_FlateFilter::v_FilterIn(const uint8_t* src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
325 {
326     if (m_pContext == NULL) {
327         m_pContext = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
328     }
329     FPDFAPI_FlateInput(m_pContext, src_buf, src_size);
330     while (1) {
331         int ret = FPDFAPI_FlateOutput(m_pContext, m_DestBuffer, FPDF_FILTER_BUFFER_SIZE);
332         int out_size = FPDF_FILTER_BUFFER_SIZE - FPDFAPI_FlateGetAvailOut(m_pContext);
333         dest_buf.AppendBlock(m_DestBuffer, out_size);
334         if (ret == Z_BUF_ERROR) {
335             break;
336         }
337         if (ret != Z_OK) {
338             ReportEOF(FPDFAPI_FlateGetAvailIn(m_pContext));
339             break;
340         }
341     }
342 }
343 CPDF_LzwFilter::CPDF_LzwFilter(FX_BOOL bEarlyChange)
344 {
345     m_bEarlyChange = bEarlyChange ? 1 : 0;
346     m_CodeLen = 9;
347     m_nCodes = 0;
348     m_nLeftBits = 0;
349     m_LeftBits = 0;
350     m_OldCode = (FX_DWORD) - 1;
351 }
352 void CPDF_LzwFilter::v_FilterIn(const uint8_t* src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
353 {
354     for (FX_DWORD i = 0; i < src_size; i ++) {
355         if (m_nLeftBits + 8 < m_CodeLen) {
356             m_nLeftBits += 8;
357             m_LeftBits = (m_LeftBits << 8) | src_buf[i];
358             continue;
359         }
360         FX_DWORD new_bits = m_CodeLen - m_nLeftBits;
361         FX_DWORD code = (m_LeftBits << new_bits) | (src_buf[i] >> (8 - new_bits));
362         m_nLeftBits = 8 - new_bits;
363         m_LeftBits = src_buf[i] % (1 << m_nLeftBits);
364         if (code < 256) {
365             dest_buf.AppendByte((uint8_t)code);
366             m_LastChar = (uint8_t)code;
367             if (m_OldCode != -1) {
368                 AddCode(m_OldCode, m_LastChar);
369             }
370             m_OldCode = code;
371         } else if (code == 256) {
372             m_CodeLen = 9;
373             m_nCodes = 0;
374             m_OldCode = (FX_DWORD) - 1;
375         } else if (code == 257) {
376             ReportEOF(src_size - i - 1);
377             return;
378         } else {
379             if (m_OldCode == -1) {
380                 ReportEOF(src_size - i - 1);
381                 return;
382             }
383             m_StackLen = 0;
384             if (code >= m_nCodes + 258) {
385                 if (m_StackLen < sizeof(m_DecodeStack)) {
386                     m_DecodeStack[m_StackLen++] = m_LastChar;
387                 }
388                 DecodeString(m_OldCode);
389             } else {
390                 DecodeString(code);
391             }
392             dest_buf.AppendBlock(NULL, m_StackLen);
393             uint8_t* pOutput = dest_buf.GetBuffer() + dest_buf.GetSize() - m_StackLen;
394             for (FX_DWORD cc = 0; cc < m_StackLen; cc ++) {
395                 pOutput[cc] = m_DecodeStack[m_StackLen - cc - 1];
396             }
397             m_LastChar = m_DecodeStack[m_StackLen - 1];
398             if (m_OldCode < 256) {
399                 AddCode(m_OldCode, m_LastChar);
400             } else if (m_OldCode - 258 >= m_nCodes) {
401                 ReportEOF(src_size - i - 1);
402                 return;
403             } else {
404                 AddCode(m_OldCode, m_LastChar);
405             }
406             m_OldCode = code;
407         }
408     }
409 }
410 void CPDF_LzwFilter::AddCode(FX_DWORD prefix_code, uint8_t append_char)
411 {
412     if (m_nCodes + m_bEarlyChange == 4094) {
413         return;
414     }
415     m_CodeArray[m_nCodes ++] = (prefix_code << 16) | append_char;
416     if (m_nCodes + m_bEarlyChange == 512 - 258) {
417         m_CodeLen = 10;
418     } else if (m_nCodes + m_bEarlyChange == 1024 - 258) {
419         m_CodeLen = 11;
420     } else if (m_nCodes + m_bEarlyChange == 2048 - 258) {
421         m_CodeLen = 12;
422     }
423 }
424 void CPDF_LzwFilter::DecodeString(FX_DWORD code)
425 {
426     while (1) {
427         int index = code - 258;
428         if (index < 0 || index >= (int)m_nCodes) {
429             break;
430         }
431         FX_DWORD data = m_CodeArray[index];
432         if (m_StackLen >= sizeof(m_DecodeStack)) {
433             return;
434         }
435         m_DecodeStack[m_StackLen++] = (uint8_t)data;
436         code = data >> 16;
437     }
438     if (m_StackLen >= sizeof(m_DecodeStack)) {
439         return;
440     }
441     m_DecodeStack[m_StackLen++] = (uint8_t)code;
442 }
443 CPDF_PredictorFilter::CPDF_PredictorFilter(int predictor, int colors, int bpc, int cols)
444 {
445     m_bTiff = predictor < 10;
446     m_pRefLine = NULL;
447     m_pCurLine = NULL;
448     m_iLine = 0;
449     m_LineInSize = 0;
450     m_Bpp = (colors * bpc + 7) / 8;
451     m_Pitch = (colors * bpc * cols + 7) / 8;
452     if (!m_bTiff) {
453         m_Pitch ++;
454     }
455 }
456 CPDF_PredictorFilter::~CPDF_PredictorFilter()
457 {
458     if (m_pCurLine) {
459         FX_Free(m_pCurLine);
460     }
461     if (m_pRefLine) {
462         FX_Free(m_pRefLine);
463     }
464 }
465 static uint8_t PaethPredictor(int a, int b, int c)
466 {
467     int p = a + b - c;
468     int pa = FXSYS_abs(p - a);
469     int pb = FXSYS_abs(p - b);
470     int pc = FXSYS_abs(p - c);
471     if (pa <= pb && pa <= pc) {
472         return (uint8_t)a;
473     }
474     if (pb <= pc) {
475         return (uint8_t)b;
476     }
477     return (uint8_t)c;
478 }
479 static void PNG_PredictorLine(uint8_t* cur_buf, uint8_t* ref_buf, int pitch, int Bpp)
480 {
481     uint8_t tag = cur_buf[0];
482     if (tag == 0) {
483         return;
484     }
485     cur_buf ++;
486     if (ref_buf) {
487         ref_buf ++;
488     }
489     for (int byte = 0; byte < pitch; byte ++) {
490         uint8_t raw_byte = cur_buf[byte];
491         switch (tag) {
492             case 1:     {
493                     uint8_t left = 0;
494                     if (byte >= Bpp) {
495                         left = cur_buf[byte - Bpp];
496                     }
497                     cur_buf[byte] = raw_byte + left;
498                     break;
499                 }
500             case 2: {
501                     uint8_t up = 0;
502                     if (ref_buf) {
503                         up = ref_buf[byte];
504                     }
505                     cur_buf[byte] = raw_byte + up;
506                     break;
507                 }
508             case 3: {
509                     uint8_t left = 0;
510                     if (byte >= Bpp) {
511                         left = cur_buf[byte - Bpp];
512                     }
513                     uint8_t up = 0;
514                     if (ref_buf) {
515                         up = ref_buf[byte];
516                     }
517                     cur_buf[byte] = raw_byte + (up + left) / 2;
518                     break;
519                 }
520             case 4: {
521                     uint8_t left = 0;
522                     if (byte >= Bpp) {
523                         left = cur_buf[byte - Bpp];
524                     }
525                     uint8_t up = 0;
526                     if (ref_buf) {
527                         up = ref_buf[byte];
528                     }
529                     uint8_t upper_left = 0;
530                     if (byte >= Bpp && ref_buf) {
531                         upper_left = ref_buf[byte - Bpp];
532                     }
533                     cur_buf[byte] = raw_byte + PaethPredictor(left, up, upper_left);
534                     break;
535                 }
536         }
537     }
538 }
539 void CPDF_PredictorFilter::v_FilterIn(const uint8_t* src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
540 {
541     if (m_pCurLine == NULL) {
542         m_pCurLine = FX_Alloc(uint8_t, m_Pitch);
543         if (!m_bTiff) {
544             m_pRefLine = FX_Alloc(uint8_t, m_Pitch);
545         }
546     }
547     while (1) {
548         FX_DWORD read_size = m_Pitch - m_LineInSize;
549         if (read_size > src_size) {
550             read_size = src_size;
551         }
552         FXSYS_memcpy(m_pCurLine + m_LineInSize, src_buf, read_size);
553         m_LineInSize += read_size;
554         if (m_LineInSize < m_Pitch) {
555             break;
556         }
557         src_buf += read_size;
558         src_size -= read_size;
559         if (m_bTiff) {
560             for (FX_DWORD byte = m_Bpp; byte < m_Pitch; byte ++) {
561                 m_pCurLine[byte] += m_pCurLine[byte - m_Bpp];
562             }
563             dest_buf.AppendBlock(m_pCurLine, m_Pitch);
564         } else {
565             PNG_PredictorLine(m_pCurLine, m_iLine ? m_pRefLine : NULL, m_Pitch - 1, m_Bpp);
566             dest_buf.AppendBlock(m_pCurLine + 1, m_Pitch - 1);
567             m_iLine ++;
568             uint8_t* temp = m_pCurLine;
569             m_pCurLine = m_pRefLine;
570             m_pRefLine = temp;
571         }
572         m_LineInSize = 0;
573     }
574 }
575 CPDF_Ascii85Filter::CPDF_Ascii85Filter()
576 {
577     m_State = 0;
578     m_CharCount = 0;
579 }
580 void CPDF_Ascii85Filter::v_FilterIn(const uint8_t* src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
581 {
582     for (FX_DWORD i = 0; i < src_size; i ++) {
583         uint8_t 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((uint8_t)(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((uint8_t)(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 }
635 CPDF_AsciiHexFilter::CPDF_AsciiHexFilter()
636 {
637     m_State = 0;
638 }
639 void CPDF_AsciiHexFilter::v_FilterIn(const uint8_t* src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
640 {
641     for (FX_DWORD i = 0; i < src_size; i ++) {
642         uint8_t 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 }
669 CPDF_RunLenFilter::CPDF_RunLenFilter()
670 {
671     m_State = 0;
672     m_Count = 0;
673 }
674 void CPDF_RunLenFilter::v_FilterIn(const uint8_t* src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
675 {
676     for (FX_DWORD i = 0; i < src_size; i ++) {
677         uint8_t 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_memset(dest_buf.GetBuffer() + dest_buf.GetSize() - m_Count, byte, m_Count);
701                     m_State = 0;
702                     break;
703                 }
704         }
705     }
706 }
707 CPDF_JpegFilter::CPDF_JpegFilter()
708 {
709     m_pContext = NULL;
710     m_bGotHeader = FALSE;
711     m_pScanline = NULL;
712     m_iLine = 0;
713 }
714 CPDF_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 }
723 void CPDF_JpegFilter::v_FilterIn(const uint8_t* 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     const uint8_t* 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(uint8_t, 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 }
775 CPDF_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 }
789 CPDF_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 }
798 FX_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(uint8_t, m_Pitch);
808     m_pRefBuf = FX_Alloc(uint8_t, m_Pitch);
809     FXSYS_memset(m_pScanlineBuf, 0xff, m_Pitch);
810     FXSYS_memset(m_pRefBuf, 0xff, m_Pitch);
811     m_iRow = 0;
812     m_InputBitPos = 0;
813     return TRUE;
814 }
815 void CPDF_FaxFilter::v_FilterIn(const uint8_t* src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
816 {
817     const uint8_t* 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 }
839 void CPDF_FaxFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf)
840 {
841     ProcessData(m_InputBuf.GetBuffer(), m_InputBuf.GetSize(), m_InputBitPos, TRUE, dest_buf);
842 }
843 FX_BOOL _FaxSkipEOL(const uint8_t* src_buf, int bitsize, int& bitpos);
844 FX_BOOL _FaxG4GetRow(const uint8_t* src_buf, int bitsize, int& bitpos, uint8_t* dest_buf, const uint8_t* ref_buf, int columns);
845 FX_BOOL _FaxGet1DLine(const uint8_t* src_buf, int bitsize, int& bitpos, uint8_t* dest_buf, int columns);
846 void CPDF_FaxFilter::ProcessData(const uint8_t* 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_memset(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_memcpy(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 }
876 FX_BOOL CPDF_FaxFilter::ReadLine(const uint8_t* 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 }