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