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