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