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