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