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