clang-format all pdfium code, again.
[pdfium.git] / core / src / fpdfapi / fpdf_parser / fpdf_parser_filters.cpp
index 76a79f6..8cb4320 100644 (file)
-// Copyright 2014 PDFium Authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
\r
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
-\r
-#include "../../fx_zlib.h"\r
-#include "../../../include/fpdfapi/fpdf_parser.h"\r
-#include "../../../include/fxcodec/fx_codec.h"\r
-#include "../../../include/fpdfapi/fpdf_module.h"\r
-#include "filters_int.h"\r
-CFX_DataFilter::CFX_DataFilter()\r
-{\r
-    m_bEOF = FALSE;\r
-    m_pDestFilter = NULL;\r
-    m_SrcPos = 0;\r
-}\r
-CFX_DataFilter::~CFX_DataFilter()\r
-{\r
-    if (m_pDestFilter) {\r
-        delete m_pDestFilter;\r
-    }\r
-}\r
-void CFX_DataFilter::SetDestFilter(CFX_DataFilter* pFilter)\r
-{\r
-    if (m_pDestFilter) {\r
-        m_pDestFilter->SetDestFilter(pFilter);\r
-    } else {\r
-        m_pDestFilter = pFilter;\r
-    }\r
-}\r
-void CFX_DataFilter::FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    if (m_bEOF) {\r
-        return;\r
-    }\r
-    m_SrcPos += src_size;\r
-    if (m_pDestFilter) {\r
-        CFX_BinaryBuf temp_buf;\r
-        temp_buf.EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);\r
-        v_FilterIn(src_buf, src_size, temp_buf);\r
-        m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf);\r
-    } else {\r
-        v_FilterIn(src_buf, src_size, dest_buf);\r
-    }\r
-}\r
-void CFX_DataFilter::FilterFinish(CFX_BinaryBuf& dest_buf)\r
-{\r
-    if (m_pDestFilter) {\r
-        CFX_BinaryBuf temp_buf;\r
-        v_FilterFinish(temp_buf);\r
-        if (temp_buf.GetSize()) {\r
-            m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf);\r
-        }\r
-        m_pDestFilter->FilterFinish(dest_buf);\r
-    } else {\r
-        v_FilterFinish(dest_buf);\r
-    }\r
-    m_bEOF = TRUE;\r
-}\r
-void CFX_DataFilter::ReportEOF(FX_DWORD left_input)\r
-{\r
-    if (m_bEOF) {\r
-        return;\r
-    }\r
-    m_bEOF = TRUE;\r
-    m_SrcPos -= left_input;\r
-}\r
-CFX_DataFilter* FPDF_CreateFilter(FX_BSTR name, const CPDF_Dictionary* pParam, int width, int height)\r
-{\r
-    FX_DWORD id = name.GetID();\r
-    switch (id) {\r
-        case FXBSTR_ID('F', 'l', 'a', 't'):\r
-        case FXBSTR_ID('F', 'l', 0, 0):\r
-        case FXBSTR_ID('L', 'Z', 'W', 'D'):\r
-        case FXBSTR_ID('L', 'Z', 'W', 0): {\r
-                CFX_DataFilter* pFilter;\r
-                if (id == FXBSTR_ID('L', 'Z', 'W', 'D') || id == FXBSTR_ID('L', 'Z', 'W', 0)) {\r
-                    pFilter = FX_NEW CPDF_LzwFilter(pParam->GetInteger("EarlyChange", 1));\r
-                } else {\r
-                    pFilter = FX_NEW CPDF_FlateFilter;\r
-                }\r
-                if (pParam->GetInteger("Predictor", 1) > 1) {\r
-                    CFX_DataFilter* pPredictor = FX_NEW CPDF_PredictorFilter(pParam->GetInteger(FX_BSTRC("Predictor"), 1),\r
-                                                 pParam->GetInteger(FX_BSTRC("Colors"), 1), pParam->GetInteger(FX_BSTRC("BitsPerComponent"), 8),\r
-                                                 pParam->GetInteger(FX_BSTRC("Columns"), 1));\r
-                    pFilter->SetDestFilter(pPredictor);\r
-                }\r
-                return pFilter;\r
-            }\r
-        case FXBSTR_ID('A', 'S', 'C', 'I'):\r
-            if (name == "ASCIIHexDecode") {\r
-                return FX_NEW CPDF_AsciiHexFilter;\r
-            }\r
-            return FX_NEW CPDF_Ascii85Filter;\r
-        case FXBSTR_ID('A', 'H', 'x', 0):\r
-            return FX_NEW CPDF_AsciiHexFilter;\r
-        case FXBSTR_ID('A', '8', '5', 0):\r
-            return FX_NEW CPDF_Ascii85Filter;\r
-        case FXBSTR_ID('R', 'u', 'n', 'L'):\r
-            return FX_NEW CPDF_RunLenFilter;\r
-        case FXBSTR_ID('C', 'C', 'I', 'T'): {\r
-                int Encoding = 0;\r
-                int bEndOfLine = FALSE;\r
-                int bByteAlign = FALSE;\r
-                int bBlack = FALSE;\r
-                int nRows = 0;\r
-                int nColumns = 1728;\r
-                if (pParam) {\r
-                    Encoding = pParam->GetInteger(FX_BSTRC("K"));\r
-                    bEndOfLine = pParam->GetInteger(FX_BSTRC("EndOfLine"));\r
-                    bByteAlign = pParam->GetInteger(FX_BSTRC("EncodedByteAlign"));\r
-                    bBlack = pParam->GetInteger(FX_BSTRC("BlackIs1"));\r
-                    nColumns = pParam->GetInteger(FX_BSTRC("Columns"), 1728);\r
-                    nRows = pParam->GetInteger(FX_BSTRC("Rows"));\r
-                }\r
-                if (nColumns == 0) {\r
-                    nColumns = width;\r
-                }\r
-                if (nRows == 0) {\r
-                    nRows = height;\r
-                }\r
-                CPDF_FaxFilter* pFilter = FX_NEW CPDF_FaxFilter();\r
-                pFilter->Initialize(Encoding, bEndOfLine, bByteAlign, bBlack, nRows, nColumns);\r
-                return pFilter;\r
-            }\r
-        case FXBSTR_ID('D', 'C', 'T', 'D'):\r
-            return FX_NEW CPDF_JpegFilter;\r
-        default:\r
-            return NULL;\r
-    }\r
-}\r
-CFX_DataFilter* _FPDF_CreateFilterFromDict(CPDF_Dictionary* pDict)\r
-{\r
-    CPDF_Object* pDecoder = pDict->GetElementValue("Filter");\r
-    if (pDecoder == NULL) {\r
-        return NULL;\r
-    }\r
-    CFX_DataFilter* pFirstFilter = NULL;\r
-    int width = pDict->GetInteger(FX_BSTRC("Width")), height = pDict->GetInteger(FX_BSTRC("Height"));\r
-    CPDF_Object* pParams = pDict->GetElementValue("DecodeParms");\r
-    if (pDecoder->GetType() == PDFOBJ_ARRAY) {\r
-        if (pParams && pParams->GetType() != PDFOBJ_ARRAY) {\r
-            pParams = NULL;\r
-        }\r
-        for (FX_DWORD i = 0; i < ((CPDF_Array*)pDecoder)->GetCount(); i ++) {\r
-            CFX_ByteString name = ((CPDF_Array*)pDecoder)->GetString(i);\r
-            CPDF_Dictionary* pParam = NULL;\r
-            if (pParams) {\r
-                pParam = ((CPDF_Array*)pParams)->GetDict(i);\r
-            }\r
-            CFX_DataFilter* pDestFilter = FPDF_CreateFilter(name, pParam, width, height);\r
-            if (pDestFilter) {\r
-                if (pFirstFilter == NULL) {\r
-                    pFirstFilter = pDestFilter;\r
-                } else {\r
-                    pFirstFilter->SetDestFilter(pDestFilter);\r
-                }\r
-            }\r
-        }\r
-    } else {\r
-        if (pParams && pParams->GetType() != PDFOBJ_DICTIONARY) {\r
-            pParams = NULL;\r
-        }\r
-        pFirstFilter = FPDF_CreateFilter(pDecoder->GetString(), (CPDF_Dictionary*)pParams, width, height);\r
-    }\r
-    return pFirstFilter;\r
-}\r
-CPDF_StreamFilter* CPDF_Stream::GetStreamFilter(FX_BOOL bRaw) const\r
-{\r
-    CFX_DataFilter* pFirstFilter = NULL;\r
-    if (m_pCryptoHandler) {\r
-        pFirstFilter = FX_NEW CPDF_DecryptFilter(m_pCryptoHandler, m_ObjNum, m_GenNum);\r
-    }\r
-    if (!bRaw) {\r
-        CFX_DataFilter* pFilter = _FPDF_CreateFilterFromDict(m_pDict);\r
-        if (pFilter) {\r
-            if (pFirstFilter == NULL) {\r
-                pFirstFilter = pFilter;\r
-            } else {\r
-                pFirstFilter->SetDestFilter(pFilter);\r
-            }\r
-        }\r
-    }\r
-    CPDF_StreamFilter* pStreamFilter = FX_NEW CPDF_StreamFilter;\r
-    pStreamFilter->m_pStream = this;\r
-    pStreamFilter->m_pFilter = pFirstFilter;\r
-    pStreamFilter->m_pBuffer = NULL;\r
-    pStreamFilter->m_SrcOffset = 0;\r
-    return pStreamFilter;\r
-}\r
-CPDF_StreamFilter::~CPDF_StreamFilter()\r
-{\r
-    if (m_pFilter) {\r
-        delete m_pFilter;\r
-    }\r
-    if (m_pBuffer) {\r
-        delete m_pBuffer;\r
-    }\r
-}\r
-#define FPDF_FILTER_BUFFER_IN_SIZE     FPDF_FILTER_BUFFER_SIZE\r
-FX_DWORD CPDF_StreamFilter::ReadBlock(FX_LPBYTE buffer, FX_DWORD buf_size)\r
-{\r
-    if (m_pFilter == NULL) {\r
-        FX_DWORD read_size = m_pStream->GetRawSize() - m_SrcOffset;\r
-        if (read_size == 0) {\r
-            return 0;\r
-        }\r
-        if (read_size > buf_size) {\r
-            read_size = buf_size;\r
-        }\r
-        m_pStream->ReadRawData(m_SrcOffset, buffer, read_size);\r
-        m_SrcOffset += read_size;\r
-        return read_size;\r
-    }\r
-    FX_DWORD read_size = 0;\r
-    if (m_pBuffer) {\r
-        read_size = ReadLeftOver(buffer, buf_size);\r
-        if (read_size == buf_size) {\r
-            return read_size;\r
-        }\r
-        buffer += read_size;\r
-        buf_size -= read_size;\r
-    }\r
-    ASSERT(m_pBuffer == NULL);\r
-    if (m_pFilter->IsEOF()) {\r
-        return read_size;\r
-    }\r
-    m_pBuffer = FX_NEW CFX_BinaryBuf;\r
-    m_pBuffer->EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);\r
-    m_BufOffset = 0;\r
-    while (1) {\r
-        int src_size = m_pStream->GetRawSize() - m_SrcOffset;\r
-        if (src_size == 0) {\r
-            m_pFilter->FilterFinish(*m_pBuffer);\r
-            break;\r
-        }\r
-        if (src_size > FPDF_FILTER_BUFFER_IN_SIZE) {\r
-            src_size = FPDF_FILTER_BUFFER_IN_SIZE;\r
-        }\r
-        if (!m_pStream->ReadRawData(m_SrcOffset, m_SrcBuffer, src_size)) {\r
-            return 0;\r
-        }\r
-        m_SrcOffset += src_size;\r
-        m_pFilter->FilterIn(m_SrcBuffer, src_size, *m_pBuffer);\r
-        if (m_pBuffer->GetSize() >= (int)buf_size) {\r
-            break;\r
-        }\r
-    }\r
-    return read_size + ReadLeftOver(buffer, buf_size);\r
-}\r
-FX_DWORD CPDF_StreamFilter::ReadLeftOver(FX_LPBYTE buffer, FX_DWORD buf_size)\r
-{\r
-    FX_DWORD read_size = m_pBuffer->GetSize() - m_BufOffset;\r
-    if (read_size > buf_size) {\r
-        read_size = buf_size;\r
-    }\r
-    FXSYS_memcpy32(buffer, m_pBuffer->GetBuffer() + m_BufOffset, read_size);\r
-    m_BufOffset += read_size;\r
-    if (m_BufOffset == (FX_DWORD)m_pBuffer->GetSize()) {\r
-        delete m_pBuffer;\r
-        m_pBuffer = NULL;\r
-    }\r
-    return read_size;\r
-}\r
-CPDF_DecryptFilter::CPDF_DecryptFilter(CPDF_CryptoHandler* pCryptoHandler, FX_DWORD objnum, FX_DWORD gennum)\r
-{\r
-    m_pCryptoHandler = pCryptoHandler;\r
-    m_pContext = NULL;\r
-    m_ObjNum = objnum;\r
-    m_GenNum = gennum;\r
-}\r
-CPDF_DecryptFilter::~CPDF_DecryptFilter()\r
-{\r
-    CFX_BinaryBuf buf;\r
-    if (m_pContext) {\r
-        m_pCryptoHandler->DecryptFinish(m_pContext, buf);\r
-    }\r
-}\r
-void CPDF_DecryptFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    if (m_pContext == NULL) {\r
-        m_pContext = m_pCryptoHandler->DecryptStart(m_ObjNum, m_GenNum);\r
-    }\r
-    m_pCryptoHandler->DecryptStream(m_pContext, src_buf, src_size, dest_buf);\r
-}\r
-void CPDF_DecryptFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf)\r
-{\r
-    m_bEOF = TRUE;\r
-    if (m_pContext == NULL) {\r
-        return;\r
-    }\r
-    m_pCryptoHandler->DecryptFinish(m_pContext, dest_buf);\r
-    m_pContext = NULL;\r
-}\r
-extern "C" {\r
-    static void* my_alloc_func (void* opaque, unsigned int items, unsigned int size)\r
-    {\r
-        return FX_Alloc(FX_BYTE, items * size);\r
-    }\r
-    static void   my_free_func  (void* opaque, void* address)\r
-    {\r
-        FX_Free(address);\r
-    }\r
-    void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int),\r
-                            void (*free_func)(void*, void*));\r
-    void FPDFAPI_FlateInput(void* context, const unsigned char* src_buf, unsigned int src_size);\r
-    int FPDFAPI_FlateOutput(void* context, unsigned char* dest_buf, unsigned int dest_size);\r
-    int FPDFAPI_FlateGetAvailIn(void* context);\r
-    int FPDFAPI_FlateGetAvailOut(void* context);\r
-    void FPDFAPI_FlateEnd(void* context);\r
-}\r
-CPDF_FlateFilter::CPDF_FlateFilter()\r
-{\r
-    m_pContext = NULL;\r
-}\r
-CPDF_FlateFilter::~CPDF_FlateFilter()\r
-{\r
-    if (m_pContext) {\r
-        FPDFAPI_FlateEnd(m_pContext);\r
-    }\r
-}\r
-void CPDF_FlateFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    if (m_pContext == NULL) {\r
-        m_pContext = FPDFAPI_FlateInit(my_alloc_func, my_free_func);\r
-    }\r
-    FPDFAPI_FlateInput(m_pContext, src_buf, src_size);\r
-    while (1) {\r
-        int ret = FPDFAPI_FlateOutput(m_pContext, m_DestBuffer, FPDF_FILTER_BUFFER_SIZE);\r
-        int out_size = FPDF_FILTER_BUFFER_SIZE - FPDFAPI_FlateGetAvailOut(m_pContext);\r
-        dest_buf.AppendBlock(m_DestBuffer, out_size);\r
-        if (ret == Z_BUF_ERROR) {\r
-            break;\r
-        }\r
-        if (ret != Z_OK) {\r
-            ReportEOF(FPDFAPI_FlateGetAvailIn(m_pContext));\r
-            break;\r
-        }\r
-    }\r
-}\r
-CPDF_LzwFilter::CPDF_LzwFilter(FX_BOOL bEarlyChange)\r
-{\r
-    m_bEarlyChange = bEarlyChange ? 1 : 0;\r
-    m_CodeLen = 9;\r
-    m_nCodes = 0;\r
-    m_nLeftBits = 0;\r
-    m_LeftBits = 0;\r
-    m_OldCode = (FX_DWORD) - 1;\r
-}\r
-void CPDF_LzwFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    for (FX_DWORD i = 0; i < src_size; i ++) {\r
-        if (m_nLeftBits + 8 < m_CodeLen) {\r
-            m_nLeftBits += 8;\r
-            m_LeftBits = (m_LeftBits << 8) | src_buf[i];\r
-            continue;\r
-        }\r
-        FX_DWORD new_bits = m_CodeLen - m_nLeftBits;\r
-        FX_DWORD code = (m_LeftBits << new_bits) | (src_buf[i] >> (8 - new_bits));\r
-        m_nLeftBits = 8 - new_bits;\r
-        m_LeftBits = src_buf[i] % (1 << m_nLeftBits);\r
-        if (code < 256) {\r
-            dest_buf.AppendByte((FX_BYTE)code);\r
-            m_LastChar = (FX_BYTE)code;\r
-            if (m_OldCode != -1) {\r
-                AddCode(m_OldCode, m_LastChar);\r
-            }\r
-            m_OldCode = code;\r
-        } else if (code == 256) {\r
-            m_CodeLen = 9;\r
-            m_nCodes = 0;\r
-            m_OldCode = (FX_DWORD) - 1;\r
-        } else if (code == 257) {\r
-            ReportEOF(src_size - i - 1);\r
-            return;\r
-        } else {\r
-            if (m_OldCode == -1) {\r
-                ReportEOF(src_size - i - 1);\r
-                return;\r
-            }\r
-            m_StackLen = 0;\r
-            if (code >= m_nCodes + 258) {\r
-                if (m_StackLen < sizeof(m_DecodeStack)) {\r
-                    m_DecodeStack[m_StackLen++] = m_LastChar;\r
-                }\r
-                DecodeString(m_OldCode);\r
-            } else {\r
-                DecodeString(code);\r
-            }\r
-            dest_buf.AppendBlock(NULL, m_StackLen);\r
-            FX_LPBYTE pOutput = dest_buf.GetBuffer() + dest_buf.GetSize() - m_StackLen;\r
-            for (FX_DWORD cc = 0; cc < m_StackLen; cc ++) {\r
-                pOutput[cc] = m_DecodeStack[m_StackLen - cc - 1];\r
-            }\r
-            m_LastChar = m_DecodeStack[m_StackLen - 1];\r
-            if (m_OldCode < 256) {\r
-                AddCode(m_OldCode, m_LastChar);\r
-            } else if (m_OldCode - 258 >= m_nCodes) {\r
-                ReportEOF(src_size - i - 1);\r
-                return;\r
-            } else {\r
-                AddCode(m_OldCode, m_LastChar);\r
-            }\r
-            m_OldCode = code;\r
-        }\r
-    }\r
-}\r
-void CPDF_LzwFilter::AddCode(FX_DWORD prefix_code, FX_BYTE append_char)\r
-{\r
-    if (m_nCodes + m_bEarlyChange == 4094) {\r
-        return;\r
-    }\r
-    m_CodeArray[m_nCodes ++] = (prefix_code << 16) | append_char;\r
-    if (m_nCodes + m_bEarlyChange == 512 - 258) {\r
-        m_CodeLen = 10;\r
-    } else if (m_nCodes + m_bEarlyChange == 1024 - 258) {\r
-        m_CodeLen = 11;\r
-    } else if (m_nCodes + m_bEarlyChange == 2048 - 258) {\r
-        m_CodeLen = 12;\r
-    }\r
-}\r
-void CPDF_LzwFilter::DecodeString(FX_DWORD code)\r
-{\r
-    while (1) {\r
-        int index = code - 258;\r
-        if (index < 0 || index >= (int)m_nCodes) {\r
-            break;\r
-        }\r
-        FX_DWORD data = m_CodeArray[index];\r
-        if (m_StackLen >= sizeof(m_DecodeStack)) {\r
-            return;\r
-        }\r
-        m_DecodeStack[m_StackLen++] = (FX_BYTE)data;\r
-        code = data >> 16;\r
-    }\r
-    if (m_StackLen >= sizeof(m_DecodeStack)) {\r
-        return;\r
-    }\r
-    m_DecodeStack[m_StackLen++] = (FX_BYTE)code;\r
-}\r
-CPDF_PredictorFilter::CPDF_PredictorFilter(int predictor, int colors, int bpc, int cols)\r
-{\r
-    m_bTiff = predictor < 10;\r
-    m_pRefLine = NULL;\r
-    m_pCurLine = NULL;\r
-    m_iLine = 0;\r
-    m_LineInSize = 0;\r
-    m_Bpp = (colors * bpc + 7) / 8;\r
-    m_Pitch = (colors * bpc * cols + 7) / 8;\r
-    if (!m_bTiff) {\r
-        m_Pitch ++;\r
-    }\r
-}\r
-CPDF_PredictorFilter::~CPDF_PredictorFilter()\r
-{\r
-    if (m_pCurLine) {\r
-        FX_Free(m_pCurLine);\r
-    }\r
-    if (m_pRefLine) {\r
-        FX_Free(m_pRefLine);\r
-    }\r
-}\r
-static FX_BYTE PaethPredictor(int a, int b, int c)\r
-{\r
-    int p = a + b - c;\r
-    int pa = FXSYS_abs(p - a);\r
-    int pb = FXSYS_abs(p - b);\r
-    int pc = FXSYS_abs(p - c);\r
-    if (pa <= pb && pa <= pc) {\r
-        return (FX_BYTE)a;\r
-    }\r
-    if (pb <= pc) {\r
-        return (FX_BYTE)b;\r
-    }\r
-    return (FX_BYTE)c;\r
-}\r
-static void PNG_PredictorLine(FX_LPBYTE cur_buf, FX_LPBYTE ref_buf, int pitch, int Bpp)\r
-{\r
-    FX_BYTE tag = cur_buf[0];\r
-    if (tag == 0) {\r
-        return;\r
-    }\r
-    cur_buf ++;\r
-    if (ref_buf) {\r
-        ref_buf ++;\r
-    }\r
-    for (int byte = 0; byte < pitch; byte ++) {\r
-        FX_BYTE raw_byte = cur_buf[byte];\r
-        switch (tag) {\r
-            case 1:    {\r
-                    FX_BYTE left = 0;\r
-                    if (byte >= Bpp) {\r
-                        left = cur_buf[byte - Bpp];\r
-                    }\r
-                    cur_buf[byte] = raw_byte + left;\r
-                    break;\r
-                }\r
-            case 2: {\r
-                    FX_BYTE up = 0;\r
-                    if (ref_buf) {\r
-                        up = ref_buf[byte];\r
-                    }\r
-                    cur_buf[byte] = raw_byte + up;\r
-                    break;\r
-                }\r
-            case 3: {\r
-                    FX_BYTE left = 0;\r
-                    if (byte >= Bpp) {\r
-                        left = cur_buf[byte - Bpp];\r
-                    }\r
-                    FX_BYTE up = 0;\r
-                    if (ref_buf) {\r
-                        up = ref_buf[byte];\r
-                    }\r
-                    cur_buf[byte] = raw_byte + (up + left) / 2;\r
-                    break;\r
-                }\r
-            case 4: {\r
-                    FX_BYTE left = 0;\r
-                    if (byte >= Bpp) {\r
-                        left = cur_buf[byte - Bpp];\r
-                    }\r
-                    FX_BYTE up = 0;\r
-                    if (ref_buf) {\r
-                        up = ref_buf[byte];\r
-                    }\r
-                    FX_BYTE upper_left = 0;\r
-                    if (byte >= Bpp && ref_buf) {\r
-                        upper_left = ref_buf[byte - Bpp];\r
-                    }\r
-                    cur_buf[byte] = raw_byte + PaethPredictor(left, up, upper_left);\r
-                    break;\r
-                }\r
-        }\r
-    }\r
-}\r
-void CPDF_PredictorFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    if (m_pCurLine == NULL) {\r
-        m_pCurLine = FX_Alloc(FX_BYTE, m_Pitch);\r
-        if (!m_bTiff) {\r
-            m_pRefLine = FX_Alloc(FX_BYTE, m_Pitch);\r
-        }\r
-    }\r
-    while (1) {\r
-        FX_DWORD read_size = m_Pitch - m_LineInSize;\r
-        if (read_size > src_size) {\r
-            read_size = src_size;\r
-        }\r
-        FXSYS_memcpy32(m_pCurLine + m_LineInSize, src_buf, read_size);\r
-        m_LineInSize += read_size;\r
-        if (m_LineInSize < m_Pitch) {\r
-            break;\r
-        }\r
-        src_buf += read_size;\r
-        src_size -= read_size;\r
-        if (m_bTiff) {\r
-            for (FX_DWORD byte = m_Bpp; byte < m_Pitch; byte ++) {\r
-                m_pCurLine[byte] += m_pCurLine[byte - m_Bpp];\r
-            }\r
-            dest_buf.AppendBlock(m_pCurLine, m_Pitch);\r
-        } else {\r
-            PNG_PredictorLine(m_pCurLine, m_iLine ? m_pRefLine : NULL, m_Pitch - 1, m_Bpp);\r
-            dest_buf.AppendBlock(m_pCurLine + 1, m_Pitch - 1);\r
-            m_iLine ++;\r
-            FX_LPBYTE temp = m_pCurLine;\r
-            m_pCurLine = m_pRefLine;\r
-            m_pRefLine = temp;\r
-        }\r
-        m_LineInSize = 0;\r
-    }\r
-}\r
-CPDF_Ascii85Filter::CPDF_Ascii85Filter()\r
-{\r
-    m_State = 0;\r
-    m_CharCount = 0;\r
-}\r
-extern const FX_LPCSTR _PDF_CharType;\r
-void CPDF_Ascii85Filter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    for (FX_DWORD i = 0; i < src_size; i ++) {\r
-        FX_BYTE byte = src_buf[i];\r
-        if (_PDF_CharType[byte] == 'W') {\r
-            continue;\r
-        }\r
-        switch (m_State) {\r
-            case 0:\r
-                if (byte >= '!' && byte <= 'u') {\r
-                    int digit = byte - '!';\r
-                    m_CurDWord = digit;\r
-                    m_CharCount = 1;\r
-                    m_State = 1;\r
-                } else if (byte == 'z') {\r
-                    int zero = 0;\r
-                    dest_buf.AppendBlock(&zero, 4);\r
-                } else if (byte == '~') {\r
-                    m_State = 2;\r
-                }\r
-                break;\r
-            case 1: {\r
-                    if (byte >= '!' && byte <= 'u') {\r
-                        int digit = byte - '!';\r
-                        m_CurDWord = m_CurDWord * 85 + digit;\r
-                        m_CharCount ++;\r
-                        if (m_CharCount == 5) {\r
-                            for (int i = 0; i < 4; i ++) {\r
-                                dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8));\r
-                            }\r
-                            m_State = 0;\r
-                        }\r
-                    } else if (byte == '~') {\r
-                        if (m_CharCount > 1) {\r
-                            int i;\r
-                            for (i = m_CharCount; i < 5; i ++) {\r
-                                m_CurDWord = m_CurDWord * 85 + 84;\r
-                            }\r
-                            for (i = 0; i < m_CharCount - 1; i ++) {\r
-                                dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8));\r
-                            }\r
-                        }\r
-                        m_State = 2;\r
-                    }\r
-                    break;\r
-                }\r
-            case 2:\r
-                if (byte == '>') {\r
-                    ReportEOF(src_size - i - 1);\r
-                    return;\r
-                }\r
-                break;\r
-        }\r
-    }\r
-}\r
-CPDF_AsciiHexFilter::CPDF_AsciiHexFilter()\r
-{\r
-    m_State = 0;\r
-}\r
-void CPDF_AsciiHexFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    for (FX_DWORD i = 0; i < src_size; i ++) {\r
-        FX_BYTE byte = src_buf[i];\r
-        if (_PDF_CharType[byte] == 'W') {\r
-            continue;\r
-        }\r
-        int digit;\r
-        if (byte >= '0' && byte <= '9') {\r
-            digit = byte - '0';\r
-        } else if (byte >= 'a' && byte <= 'f') {\r
-            digit = byte - 'a' + 10;\r
-        } else if (byte >= 'A' && byte <= 'F') {\r
-            digit = byte - 'A' + 10;\r
-        } else {\r
-            if (m_State) {\r
-                dest_buf.AppendByte(m_FirstDigit * 16);\r
-            }\r
-            ReportEOF(src_size - i - 1);\r
-            return;\r
-        }\r
-        if (m_State == 0) {\r
-            m_FirstDigit = digit;\r
-            m_State ++;\r
-        } else {\r
-            dest_buf.AppendByte(m_FirstDigit * 16 + digit);\r
-            m_State --;\r
-        }\r
-    }\r
-}\r
-CPDF_RunLenFilter::CPDF_RunLenFilter()\r
-{\r
-    m_State = 0;\r
-    m_Count = 0;\r
-}\r
-void CPDF_RunLenFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    for (FX_DWORD i = 0; i < src_size; i ++) {\r
-        FX_BYTE byte = src_buf[i];\r
-        switch (m_State) {\r
-            case 0:\r
-                if (byte < 128) {\r
-                    m_State = 1;\r
-                    m_Count = byte + 1;\r
-                } else if (byte == 128) {\r
-                    ReportEOF(src_size - i - 1);\r
-                    return;\r
-                } else {\r
-                    m_State = 2;\r
-                    m_Count = 257 - byte;\r
-                }\r
-                break;\r
-            case 1:\r
-                dest_buf.AppendByte(byte);\r
-                m_Count --;\r
-                if (m_Count == 0) {\r
-                    m_State = 0;\r
-                }\r
-                break;\r
-            case 2:    {\r
-                    dest_buf.AppendBlock(NULL, m_Count);\r
-                    FXSYS_memset8(dest_buf.GetBuffer() + dest_buf.GetSize() - m_Count, byte, m_Count);\r
-                    m_State = 0;\r
-                    break;\r
-                }\r
-        }\r
-    }\r
-}\r
-CPDF_JpegFilter::CPDF_JpegFilter()\r
-{\r
-    m_pContext = NULL;\r
-    m_bGotHeader = FALSE;\r
-    m_pScanline = NULL;\r
-    m_iLine = 0;\r
-}\r
-CPDF_JpegFilter::~CPDF_JpegFilter()\r
-{\r
-    if (m_pScanline) {\r
-        FX_Free(m_pScanline);\r
-    }\r
-    if (m_pContext) {\r
-        CPDF_ModuleMgr::Get()->GetJpegModule()->Finish(m_pContext);\r
-    }\r
-}\r
-void CPDF_JpegFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    if (m_pContext == NULL) {\r
-        m_pContext = CPDF_ModuleMgr::Get()->GetJpegModule()->Start();\r
-    }\r
-    FX_LPCBYTE jpeg_src_buf;\r
-    FX_DWORD jpeg_src_size;\r
-    CFX_BinaryBuf temp_buf;\r
-    if (m_InputBuf.GetSize()) {\r
-        temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size);\r
-        temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize());\r
-        m_InputBuf.Clear();\r
-        temp_buf.AppendBlock(src_buf, src_size);\r
-        jpeg_src_buf = temp_buf.GetBuffer();\r
-        jpeg_src_size = temp_buf.GetSize();\r
-    } else {\r
-        jpeg_src_buf = src_buf;\r
-        jpeg_src_size = src_size;\r
-    }\r
-    CPDF_ModuleMgr::Get()->GetJpegModule()->Input(m_pContext, jpeg_src_buf, jpeg_src_size);\r
-    if (!m_bGotHeader) {\r
-        int ret = CPDF_ModuleMgr::Get()->GetJpegModule()->ReadHeader(m_pContext, &m_Width, &m_Height, &m_nComps);\r
-        int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext);\r
-        if (ret == 1) {\r
-            ReportEOF(left_size);\r
-            return;\r
-        }\r
-        if (ret == 2) {\r
-            m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size);\r
-            return;\r
-        }\r
-        CPDF_ModuleMgr::Get()->GetJpegModule()->StartScanline(m_pContext, 1);\r
-        m_bGotHeader = TRUE;\r
-        m_Pitch = m_Width * m_nComps;\r
-    }\r
-    if (m_pScanline == NULL) {\r
-        m_pScanline = FX_Alloc(FX_BYTE, m_Pitch + 4);\r
-    }\r
-    while (1) {\r
-        if (!CPDF_ModuleMgr::Get()->GetJpegModule()->ReadScanline(m_pContext, m_pScanline)) {\r
-            int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext);\r
-            m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size);\r
-            break;\r
-        }\r
-        dest_buf.AppendBlock(m_pScanline, m_Pitch);\r
-        m_iLine ++;\r
-        if (m_iLine == m_Height) {\r
-            ReportEOF(CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext));\r
-            return;\r
-        }\r
-    }\r
-}\r
-CPDF_FaxFilter::CPDF_FaxFilter()\r
-{\r
-    m_Encoding = 0;\r
-    m_bEndOfLine = FALSE;\r
-    m_bByteAlign = FALSE;\r
-    m_bBlack = FALSE;\r
-    m_nRows = 0;\r
-    m_nColumns = 0;\r
-    m_Pitch = 0;\r
-    m_pScanlineBuf = NULL;\r
-    m_pRefBuf = NULL;\r
-    m_iRow = 0;\r
-    m_InputBitPos = 0;\r
-}\r
-CPDF_FaxFilter::~CPDF_FaxFilter()\r
-{\r
-    if (m_pScanlineBuf) {\r
-        FX_Free(m_pScanlineBuf);\r
-    }\r
-    if (m_pRefBuf) {\r
-        FX_Free(m_pRefBuf);\r
-    }\r
-}\r
-FX_BOOL CPDF_FaxFilter::Initialize(int Encoding, int bEndOfLine, int bByteAlign, int bBlack, int nRows, int nColumns)\r
-{\r
-    m_Encoding = Encoding;\r
-    m_bEndOfLine = bEndOfLine;\r
-    m_bByteAlign = bByteAlign;\r
-    m_bBlack = bBlack;\r
-    m_nRows = nRows;\r
-    m_nColumns = nColumns;\r
-    m_Pitch = (m_nColumns + 7) / 8;\r
-    m_pScanlineBuf = FX_Alloc(FX_BYTE, m_Pitch);\r
-    m_pRefBuf = FX_Alloc(FX_BYTE, m_Pitch);\r
-    FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch);\r
-    FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch);\r
-    m_iRow = 0;\r
-    m_InputBitPos = 0;\r
-    return TRUE;\r
-}\r
-void CPDF_FaxFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)\r
-{\r
-    FX_LPCBYTE fax_src_buf;\r
-    FX_DWORD fax_src_size;\r
-    CFX_BinaryBuf temp_buf;\r
-    int bitpos;\r
-    if (m_InputBuf.GetSize()) {\r
-        temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size);\r
-        temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize());\r
-        m_InputBuf.Clear();\r
-        temp_buf.AppendBlock(src_buf, src_size);\r
-        fax_src_buf = temp_buf.GetBuffer();\r
-        fax_src_size = temp_buf.GetSize();\r
-        bitpos = m_InputBitPos;\r
-    } else {\r
-        fax_src_buf = src_buf;\r
-        fax_src_size = src_size;\r
-        bitpos = 0;\r
-    }\r
-    ProcessData(fax_src_buf, fax_src_size, bitpos, FALSE, dest_buf);\r
-    int left_bits = fax_src_size * 8 - bitpos;\r
-    m_InputBuf.AppendBlock(fax_src_buf + bitpos / 8, (left_bits + 7) / 8);\r
-    m_InputBitPos = bitpos % 8;\r
-}\r
-void CPDF_FaxFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf)\r
-{\r
-    ProcessData(m_InputBuf.GetBuffer(), m_InputBuf.GetSize(), m_InputBitPos, TRUE, dest_buf);\r
-}\r
-FX_BOOL _FaxSkipEOL(const FX_BYTE* src_buf, int bitsize, int& bitpos);\r
-FX_BOOL _FaxG4GetRow(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, const FX_BYTE* ref_buf, int columns);\r
-FX_BOOL _FaxGet1DLine(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, int columns);\r
-void CPDF_FaxFilter::ProcessData(FX_LPCBYTE src_buf, FX_DWORD src_size, int& bitpos, FX_BOOL bFinish,\r
-                                 CFX_BinaryBuf& dest_buf)\r
-{\r
-    int bitsize = src_size * 8;\r
-    while (1) {\r
-        if ((bitsize < bitpos + 256) && !bFinish) {\r
-            return;\r
-        }\r
-        int start_bitpos = bitpos;\r
-        FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch);\r
-        if (!ReadLine(src_buf, bitsize, bitpos)) {\r
-            bitpos = start_bitpos;\r
-            return;\r
-        }\r
-        if (m_Encoding) {\r
-            FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch);\r
-        }\r
-        if (m_bBlack) {\r
-            for (int i = 0; i < m_Pitch; i ++) {\r
-                m_pScanlineBuf[i] = ~m_pScanlineBuf[i];\r
-            }\r
-        }\r
-        dest_buf.AppendBlock(m_pScanlineBuf, m_Pitch);\r
-        m_iRow ++;\r
-        if (m_iRow == m_nRows) {\r
-            ReportEOF(src_size - (bitpos + 7) / 8);\r
-            return;\r
-        }\r
-    }\r
-}\r
-FX_BOOL CPDF_FaxFilter::ReadLine(FX_LPCBYTE src_buf, int bitsize, int& bitpos)\r
-{\r
-    if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) {\r
-        return FALSE;\r
-    }\r
-    FX_BOOL ret;\r
-    if (m_Encoding < 0) {\r
-        ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns);\r
-    } else if (m_Encoding == 0) {\r
-        ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns);\r
-    } else {\r
-        if (bitpos == bitsize) {\r
-            return FALSE;\r
-        }\r
-        FX_BOOL bNext1D = src_buf[bitpos / 8] & (1 << (7 - bitpos % 8));\r
-        bitpos ++;\r
-        if (bNext1D) {\r
-            ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns);\r
-        } else {\r
-            ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns);\r
-        }\r
-    }\r
-    if (!ret) {\r
-        return FALSE;\r
-    }\r
-    if (m_bEndOfLine)\r
-        if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) {\r
-            return FALSE;\r
-        }\r
-    if (m_bByteAlign) {\r
-        bitpos = (bitpos + 7) / 8 * 8;\r
-    }\r
-    return TRUE;\r
-}\r
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../../include/fpdfapi/fpdf_parser.h"
+#include "../../../include/fxcodec/fx_codec.h"
+#include "../../../include/fxcodec/fx_codec_flate.h"
+#include "../../../include/fpdfapi/fpdf_module.h"
+#include "filters_int.h"
+
+extern "C" {
+
+static void* my_alloc_func(void* opaque,
+                           unsigned int items,
+                           unsigned int size) {
+  return FX_Alloc2D(uint8_t, items, size);
+}
+static void my_free_func(void* opaque, void* address) {
+  FX_Free(address);
+}
+
+}  // extern "C"
+
+CFX_DataFilter::CFX_DataFilter() {
+  m_bEOF = FALSE;
+  m_pDestFilter = NULL;
+  m_SrcPos = 0;
+}
+CFX_DataFilter::~CFX_DataFilter() {
+  delete m_pDestFilter;
+}
+void CFX_DataFilter::SetDestFilter(CFX_DataFilter* pFilter) {
+  if (m_pDestFilter) {
+    m_pDestFilter->SetDestFilter(pFilter);
+  } else {
+    m_pDestFilter = pFilter;
+  }
+}
+void CFX_DataFilter::FilterIn(const uint8_t* src_buf,
+                              FX_DWORD src_size,
+                              CFX_BinaryBuf& dest_buf) {
+  if (m_bEOF) {
+    return;
+  }
+  m_SrcPos += src_size;
+  if (m_pDestFilter) {
+    CFX_BinaryBuf temp_buf;
+    temp_buf.EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);
+    v_FilterIn(src_buf, src_size, temp_buf);
+    m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf);
+  } else {
+    v_FilterIn(src_buf, src_size, dest_buf);
+  }
+}
+void CFX_DataFilter::FilterFinish(CFX_BinaryBuf& dest_buf) {
+  if (m_pDestFilter) {
+    CFX_BinaryBuf temp_buf;
+    v_FilterFinish(temp_buf);
+    if (temp_buf.GetSize()) {
+      m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(),
+                              dest_buf);
+    }
+    m_pDestFilter->FilterFinish(dest_buf);
+  } else {
+    v_FilterFinish(dest_buf);
+  }
+  m_bEOF = TRUE;
+}
+void CFX_DataFilter::ReportEOF(FX_DWORD left_input) {
+  if (m_bEOF) {
+    return;
+  }
+  m_bEOF = TRUE;
+  m_SrcPos -= left_input;
+}
+CFX_DataFilter* FPDF_CreateFilter(const CFX_ByteStringC& name,
+                                  const CPDF_Dictionary* pParam,
+                                  int width,
+                                  int height) {
+  FX_DWORD id = name.GetID();
+  switch (id) {
+    case FXBSTR_ID('F', 'l', 'a', 't'):
+    case FXBSTR_ID('F', 'l', 0, 0):
+    case FXBSTR_ID('L', 'Z', 'W', 'D'):
+    case FXBSTR_ID('L', 'Z', 'W', 0): {
+      CFX_DataFilter* pFilter;
+      if (id == FXBSTR_ID('L', 'Z', 'W', 'D') ||
+          id == FXBSTR_ID('L', 'Z', 'W', 0)) {
+        pFilter = new CPDF_LzwFilter(
+            pParam ? pParam->GetInteger("EarlyChange", 1) : 1);
+      } else {
+        pFilter = new CPDF_FlateFilter;
+      }
+      if ((pParam ? pParam->GetInteger("Predictor", 1) : 1) > 1) {
+        CFX_DataFilter* pPredictor = new CPDF_PredictorFilter(
+            pParam->GetInteger(FX_BSTRC("Predictor"), 1),
+            pParam->GetInteger(FX_BSTRC("Colors"), 1),
+            pParam->GetInteger(FX_BSTRC("BitsPerComponent"), 8),
+            pParam->GetInteger(FX_BSTRC("Columns"), 1));
+        pFilter->SetDestFilter(pPredictor);
+      }
+      return pFilter;
+    }
+    case FXBSTR_ID('A', 'S', 'C', 'I'):
+      if (name == "ASCIIHexDecode") {
+        return new CPDF_AsciiHexFilter;
+      }
+      return new CPDF_Ascii85Filter;
+    case FXBSTR_ID('A', 'H', 'x', 0):
+      return new CPDF_AsciiHexFilter;
+    case FXBSTR_ID('A', '8', '5', 0):
+      return new CPDF_Ascii85Filter;
+    case FXBSTR_ID('R', 'u', 'n', 'L'):
+      return new CPDF_RunLenFilter;
+    case FXBSTR_ID('C', 'C', 'I', 'T'): {
+      int Encoding = 0;
+      int bEndOfLine = FALSE;
+      int bByteAlign = FALSE;
+      int bBlack = FALSE;
+      int nRows = 0;
+      int nColumns = 1728;
+      if (pParam) {
+        Encoding = pParam->GetInteger(FX_BSTRC("K"));
+        bEndOfLine = pParam->GetInteger(FX_BSTRC("EndOfLine"));
+        bByteAlign = pParam->GetInteger(FX_BSTRC("EncodedByteAlign"));
+        bBlack = pParam->GetInteger(FX_BSTRC("BlackIs1"));
+        nColumns = pParam->GetInteger(FX_BSTRC("Columns"), 1728);
+        nRows = pParam->GetInteger(FX_BSTRC("Rows"));
+      }
+      if (nColumns == 0) {
+        nColumns = width;
+      }
+      if (nRows == 0) {
+        nRows = height;
+      }
+      CPDF_FaxFilter* pFilter = new CPDF_FaxFilter();
+      pFilter->Initialize(Encoding, bEndOfLine, bByteAlign, bBlack, nRows,
+                          nColumns);
+      return pFilter;
+    }
+    case FXBSTR_ID('D', 'C', 'T', 'D'):
+      return new CPDF_JpegFilter;
+    default:
+      return NULL;
+  }
+}
+CFX_DataFilter* _FPDF_CreateFilterFromDict(CPDF_Dictionary* pDict) {
+  CPDF_Object* pDecoder = pDict->GetElementValue("Filter");
+  if (pDecoder == NULL) {
+    return NULL;
+  }
+  CFX_DataFilter* pFirstFilter = NULL;
+  int width = pDict->GetInteger(FX_BSTRC("Width")),
+      height = pDict->GetInteger(FX_BSTRC("Height"));
+  CPDF_Object* pParams = pDict->GetElementValue("DecodeParms");
+  if (pDecoder->GetType() == PDFOBJ_ARRAY) {
+    if (pParams && pParams->GetType() != PDFOBJ_ARRAY) {
+      pParams = NULL;
+    }
+    for (FX_DWORD i = 0; i < ((CPDF_Array*)pDecoder)->GetCount(); i++) {
+      CFX_ByteString name = ((CPDF_Array*)pDecoder)->GetString(i);
+      CPDF_Dictionary* pParam = NULL;
+      if (pParams) {
+        pParam = ((CPDF_Array*)pParams)->GetDict(i);
+      }
+      CFX_DataFilter* pDestFilter =
+          FPDF_CreateFilter(name, pParam, width, height);
+      if (pDestFilter) {
+        if (pFirstFilter == NULL) {
+          pFirstFilter = pDestFilter;
+        } else {
+          pFirstFilter->SetDestFilter(pDestFilter);
+        }
+      }
+    }
+  } else {
+    if (pParams && pParams->GetType() != PDFOBJ_DICTIONARY) {
+      pParams = NULL;
+    }
+    pFirstFilter = FPDF_CreateFilter(pDecoder->GetString(),
+                                     (CPDF_Dictionary*)pParams, width, height);
+  }
+  return pFirstFilter;
+}
+CPDF_StreamFilter* CPDF_Stream::GetStreamFilter(FX_BOOL bRaw) const {
+  CFX_DataFilter* pFirstFilter = NULL;
+  if (m_pCryptoHandler) {
+    pFirstFilter = new CPDF_DecryptFilter(m_pCryptoHandler, m_ObjNum, m_GenNum);
+  }
+  if (!bRaw) {
+    CFX_DataFilter* pFilter = _FPDF_CreateFilterFromDict(m_pDict);
+    if (pFilter) {
+      if (pFirstFilter == NULL) {
+        pFirstFilter = pFilter;
+      } else {
+        pFirstFilter->SetDestFilter(pFilter);
+      }
+    }
+  }
+  CPDF_StreamFilter* pStreamFilter = new CPDF_StreamFilter;
+  pStreamFilter->m_pStream = this;
+  pStreamFilter->m_pFilter = pFirstFilter;
+  pStreamFilter->m_pBuffer = NULL;
+  pStreamFilter->m_SrcOffset = 0;
+  return pStreamFilter;
+}
+CPDF_StreamFilter::~CPDF_StreamFilter() {
+  delete m_pFilter;
+  delete m_pBuffer;
+}
+#define FPDF_FILTER_BUFFER_IN_SIZE FPDF_FILTER_BUFFER_SIZE
+FX_DWORD CPDF_StreamFilter::ReadBlock(uint8_t* buffer, FX_DWORD buf_size) {
+  if (m_pFilter == NULL) {
+    FX_DWORD read_size = m_pStream->GetRawSize() - m_SrcOffset;
+    if (read_size == 0) {
+      return 0;
+    }
+    if (read_size > buf_size) {
+      read_size = buf_size;
+    }
+    m_pStream->ReadRawData(m_SrcOffset, buffer, read_size);
+    m_SrcOffset += read_size;
+    return read_size;
+  }
+  FX_DWORD read_size = 0;
+  if (m_pBuffer) {
+    read_size = ReadLeftOver(buffer, buf_size);
+    if (read_size == buf_size) {
+      return read_size;
+    }
+    buffer += read_size;
+    buf_size -= read_size;
+  }
+  ASSERT(m_pBuffer == NULL);
+  if (m_pFilter->IsEOF()) {
+    return read_size;
+  }
+  m_pBuffer = new CFX_BinaryBuf;
+  m_pBuffer->EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);
+  m_BufOffset = 0;
+  while (1) {
+    int src_size = m_pStream->GetRawSize() - m_SrcOffset;
+    if (src_size == 0) {
+      m_pFilter->FilterFinish(*m_pBuffer);
+      break;
+    }
+    if (src_size > FPDF_FILTER_BUFFER_IN_SIZE) {
+      src_size = FPDF_FILTER_BUFFER_IN_SIZE;
+    }
+    if (!m_pStream->ReadRawData(m_SrcOffset, m_SrcBuffer, src_size)) {
+      return 0;
+    }
+    m_SrcOffset += src_size;
+    m_pFilter->FilterIn(m_SrcBuffer, src_size, *m_pBuffer);
+    if (m_pBuffer->GetSize() >= (int)buf_size) {
+      break;
+    }
+  }
+  return read_size + ReadLeftOver(buffer, buf_size);
+}
+FX_DWORD CPDF_StreamFilter::ReadLeftOver(uint8_t* buffer, FX_DWORD buf_size) {
+  FX_DWORD read_size = m_pBuffer->GetSize() - m_BufOffset;
+  if (read_size > buf_size) {
+    read_size = buf_size;
+  }
+  FXSYS_memcpy(buffer, m_pBuffer->GetBuffer() + m_BufOffset, read_size);
+  m_BufOffset += read_size;
+  if (m_BufOffset == (FX_DWORD)m_pBuffer->GetSize()) {
+    delete m_pBuffer;
+    m_pBuffer = NULL;
+  }
+  return read_size;
+}
+CPDF_DecryptFilter::CPDF_DecryptFilter(CPDF_CryptoHandler* pCryptoHandler,
+                                       FX_DWORD objnum,
+                                       FX_DWORD gennum) {
+  m_pCryptoHandler = pCryptoHandler;
+  m_pContext = NULL;
+  m_ObjNum = objnum;
+  m_GenNum = gennum;
+}
+CPDF_DecryptFilter::~CPDF_DecryptFilter() {
+  CFX_BinaryBuf buf;
+  if (m_pContext) {
+    m_pCryptoHandler->DecryptFinish(m_pContext, buf);
+  }
+}
+void CPDF_DecryptFilter::v_FilterIn(const uint8_t* src_buf,
+                                    FX_DWORD src_size,
+                                    CFX_BinaryBuf& dest_buf) {
+  if (m_pContext == NULL) {
+    m_pContext = m_pCryptoHandler->DecryptStart(m_ObjNum, m_GenNum);
+  }
+  m_pCryptoHandler->DecryptStream(m_pContext, src_buf, src_size, dest_buf);
+}
+void CPDF_DecryptFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf) {
+  m_bEOF = TRUE;
+  if (m_pContext == NULL) {
+    return;
+  }
+  m_pCryptoHandler->DecryptFinish(m_pContext, dest_buf);
+  m_pContext = NULL;
+}
+CPDF_FlateFilter::CPDF_FlateFilter() {
+  m_pContext = NULL;
+}
+CPDF_FlateFilter::~CPDF_FlateFilter() {
+  if (m_pContext) {
+    FPDFAPI_FlateEnd(m_pContext);
+  }
+}
+void CPDF_FlateFilter::v_FilterIn(const uint8_t* src_buf,
+                                  FX_DWORD src_size,
+                                  CFX_BinaryBuf& dest_buf) {
+  if (m_pContext == NULL) {
+    m_pContext = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
+  }
+  FPDFAPI_FlateInput(m_pContext, src_buf, src_size);
+  while (1) {
+    int ret =
+        FPDFAPI_FlateOutput(m_pContext, m_DestBuffer, FPDF_FILTER_BUFFER_SIZE);
+    int out_size =
+        FPDF_FILTER_BUFFER_SIZE - FPDFAPI_FlateGetAvailOut(m_pContext);
+    dest_buf.AppendBlock(m_DestBuffer, out_size);
+    if (ret == Z_BUF_ERROR) {
+      break;
+    }
+    if (ret != Z_OK) {
+      ReportEOF(FPDFAPI_FlateGetAvailIn(m_pContext));
+      break;
+    }
+  }
+}
+CPDF_LzwFilter::CPDF_LzwFilter(FX_BOOL bEarlyChange) {
+  m_bEarlyChange = bEarlyChange ? 1 : 0;
+  m_CodeLen = 9;
+  m_nCodes = 0;
+  m_nLeftBits = 0;
+  m_LeftBits = 0;
+  m_OldCode = (FX_DWORD)-1;
+}
+void CPDF_LzwFilter::v_FilterIn(const uint8_t* src_buf,
+                                FX_DWORD src_size,
+                                CFX_BinaryBuf& dest_buf) {
+  for (FX_DWORD i = 0; i < src_size; i++) {
+    if (m_nLeftBits + 8 < m_CodeLen) {
+      m_nLeftBits += 8;
+      m_LeftBits = (m_LeftBits << 8) | src_buf[i];
+      continue;
+    }
+    FX_DWORD new_bits = m_CodeLen - m_nLeftBits;
+    FX_DWORD code = (m_LeftBits << new_bits) | (src_buf[i] >> (8 - new_bits));
+    m_nLeftBits = 8 - new_bits;
+    m_LeftBits = src_buf[i] % (1 << m_nLeftBits);
+    if (code < 256) {
+      dest_buf.AppendByte((uint8_t)code);
+      m_LastChar = (uint8_t)code;
+      if (m_OldCode != -1) {
+        AddCode(m_OldCode, m_LastChar);
+      }
+      m_OldCode = code;
+    } else if (code == 256) {
+      m_CodeLen = 9;
+      m_nCodes = 0;
+      m_OldCode = (FX_DWORD)-1;
+    } else if (code == 257) {
+      ReportEOF(src_size - i - 1);
+      return;
+    } else {
+      if (m_OldCode == -1) {
+        ReportEOF(src_size - i - 1);
+        return;
+      }
+      m_StackLen = 0;
+      if (code >= m_nCodes + 258) {
+        if (m_StackLen < sizeof(m_DecodeStack)) {
+          m_DecodeStack[m_StackLen++] = m_LastChar;
+        }
+        DecodeString(m_OldCode);
+      } else {
+        DecodeString(code);
+      }
+      dest_buf.AppendBlock(NULL, m_StackLen);
+      uint8_t* pOutput = dest_buf.GetBuffer() + dest_buf.GetSize() - m_StackLen;
+      for (FX_DWORD cc = 0; cc < m_StackLen; cc++) {
+        pOutput[cc] = m_DecodeStack[m_StackLen - cc - 1];
+      }
+      m_LastChar = m_DecodeStack[m_StackLen - 1];
+      if (m_OldCode < 256) {
+        AddCode(m_OldCode, m_LastChar);
+      } else if (m_OldCode - 258 >= m_nCodes) {
+        ReportEOF(src_size - i - 1);
+        return;
+      } else {
+        AddCode(m_OldCode, m_LastChar);
+      }
+      m_OldCode = code;
+    }
+  }
+}
+void CPDF_LzwFilter::AddCode(FX_DWORD prefix_code, uint8_t append_char) {
+  if (m_nCodes + m_bEarlyChange == 4094) {
+    return;
+  }
+  m_CodeArray[m_nCodes++] = (prefix_code << 16) | append_char;
+  if (m_nCodes + m_bEarlyChange == 512 - 258) {
+    m_CodeLen = 10;
+  } else if (m_nCodes + m_bEarlyChange == 1024 - 258) {
+    m_CodeLen = 11;
+  } else if (m_nCodes + m_bEarlyChange == 2048 - 258) {
+    m_CodeLen = 12;
+  }
+}
+void CPDF_LzwFilter::DecodeString(FX_DWORD code) {
+  while (1) {
+    int index = code - 258;
+    if (index < 0 || index >= (int)m_nCodes) {
+      break;
+    }
+    FX_DWORD data = m_CodeArray[index];
+    if (m_StackLen >= sizeof(m_DecodeStack)) {
+      return;
+    }
+    m_DecodeStack[m_StackLen++] = (uint8_t)data;
+    code = data >> 16;
+  }
+  if (m_StackLen >= sizeof(m_DecodeStack)) {
+    return;
+  }
+  m_DecodeStack[m_StackLen++] = (uint8_t)code;
+}
+CPDF_PredictorFilter::CPDF_PredictorFilter(int predictor,
+                                           int colors,
+                                           int bpc,
+                                           int cols) {
+  m_bTiff = predictor < 10;
+  m_pRefLine = NULL;
+  m_pCurLine = NULL;
+  m_iLine = 0;
+  m_LineInSize = 0;
+  m_Bpp = (colors * bpc + 7) / 8;
+  m_Pitch = (colors * bpc * cols + 7) / 8;
+  if (!m_bTiff) {
+    m_Pitch++;
+  }
+}
+CPDF_PredictorFilter::~CPDF_PredictorFilter() {
+  if (m_pCurLine) {
+    FX_Free(m_pCurLine);
+  }
+  if (m_pRefLine) {
+    FX_Free(m_pRefLine);
+  }
+}
+static uint8_t PaethPredictor(int a, int b, int c) {
+  int p = a + b - c;
+  int pa = FXSYS_abs(p - a);
+  int pb = FXSYS_abs(p - b);
+  int pc = FXSYS_abs(p - c);
+  if (pa <= pb && pa <= pc) {
+    return (uint8_t)a;
+  }
+  if (pb <= pc) {
+    return (uint8_t)b;
+  }
+  return (uint8_t)c;
+}
+static void PNG_PredictorLine(uint8_t* cur_buf,
+                              uint8_t* ref_buf,
+                              int pitch,
+                              int Bpp) {
+  uint8_t tag = cur_buf[0];
+  if (tag == 0) {
+    return;
+  }
+  cur_buf++;
+  if (ref_buf) {
+    ref_buf++;
+  }
+  for (int byte = 0; byte < pitch; byte++) {
+    uint8_t raw_byte = cur_buf[byte];
+    switch (tag) {
+      case 1: {
+        uint8_t left = 0;
+        if (byte >= Bpp) {
+          left = cur_buf[byte - Bpp];
+        }
+        cur_buf[byte] = raw_byte + left;
+        break;
+      }
+      case 2: {
+        uint8_t up = 0;
+        if (ref_buf) {
+          up = ref_buf[byte];
+        }
+        cur_buf[byte] = raw_byte + up;
+        break;
+      }
+      case 3: {
+        uint8_t left = 0;
+        if (byte >= Bpp) {
+          left = cur_buf[byte - Bpp];
+        }
+        uint8_t up = 0;
+        if (ref_buf) {
+          up = ref_buf[byte];
+        }
+        cur_buf[byte] = raw_byte + (up + left) / 2;
+        break;
+      }
+      case 4: {
+        uint8_t left = 0;
+        if (byte >= Bpp) {
+          left = cur_buf[byte - Bpp];
+        }
+        uint8_t up = 0;
+        if (ref_buf) {
+          up = ref_buf[byte];
+        }
+        uint8_t upper_left = 0;
+        if (byte >= Bpp && ref_buf) {
+          upper_left = ref_buf[byte - Bpp];
+        }
+        cur_buf[byte] = raw_byte + PaethPredictor(left, up, upper_left);
+        break;
+      }
+    }
+  }
+}
+void CPDF_PredictorFilter::v_FilterIn(const uint8_t* src_buf,
+                                      FX_DWORD src_size,
+                                      CFX_BinaryBuf& dest_buf) {
+  if (m_pCurLine == NULL) {
+    m_pCurLine = FX_Alloc(uint8_t, m_Pitch);
+    if (!m_bTiff) {
+      m_pRefLine = FX_Alloc(uint8_t, m_Pitch);
+    }
+  }
+  while (1) {
+    FX_DWORD read_size = m_Pitch - m_LineInSize;
+    if (read_size > src_size) {
+      read_size = src_size;
+    }
+    FXSYS_memcpy(m_pCurLine + m_LineInSize, src_buf, read_size);
+    m_LineInSize += read_size;
+    if (m_LineInSize < m_Pitch) {
+      break;
+    }
+    src_buf += read_size;
+    src_size -= read_size;
+    if (m_bTiff) {
+      for (FX_DWORD byte = m_Bpp; byte < m_Pitch; byte++) {
+        m_pCurLine[byte] += m_pCurLine[byte - m_Bpp];
+      }
+      dest_buf.AppendBlock(m_pCurLine, m_Pitch);
+    } else {
+      PNG_PredictorLine(m_pCurLine, m_iLine ? m_pRefLine : NULL, m_Pitch - 1,
+                        m_Bpp);
+      dest_buf.AppendBlock(m_pCurLine + 1, m_Pitch - 1);
+      m_iLine++;
+      uint8_t* temp = m_pCurLine;
+      m_pCurLine = m_pRefLine;
+      m_pRefLine = temp;
+    }
+    m_LineInSize = 0;
+  }
+}
+CPDF_Ascii85Filter::CPDF_Ascii85Filter() {
+  m_State = 0;
+  m_CharCount = 0;
+}
+void CPDF_Ascii85Filter::v_FilterIn(const uint8_t* src_buf,
+                                    FX_DWORD src_size,
+                                    CFX_BinaryBuf& dest_buf) {
+  for (FX_DWORD i = 0; i < src_size; i++) {
+    uint8_t byte = src_buf[i];
+    if (PDF_CharType[byte] == 'W') {
+      continue;
+    }
+    switch (m_State) {
+      case 0:
+        if (byte >= '!' && byte <= 'u') {
+          int digit = byte - '!';
+          m_CurDWord = digit;
+          m_CharCount = 1;
+          m_State = 1;
+        } else if (byte == 'z') {
+          int zero = 0;
+          dest_buf.AppendBlock(&zero, 4);
+        } else if (byte == '~') {
+          m_State = 2;
+        }
+        break;
+      case 1: {
+        if (byte >= '!' && byte <= 'u') {
+          int digit = byte - '!';
+          m_CurDWord = m_CurDWord * 85 + digit;
+          m_CharCount++;
+          if (m_CharCount == 5) {
+            for (int i = 0; i < 4; i++) {
+              dest_buf.AppendByte((uint8_t)(m_CurDWord >> (3 - i) * 8));
+            }
+            m_State = 0;
+          }
+        } else if (byte == '~') {
+          if (m_CharCount > 1) {
+            int i;
+            for (i = m_CharCount; i < 5; i++) {
+              m_CurDWord = m_CurDWord * 85 + 84;
+            }
+            for (i = 0; i < m_CharCount - 1; i++) {
+              dest_buf.AppendByte((uint8_t)(m_CurDWord >> (3 - i) * 8));
+            }
+          }
+          m_State = 2;
+        }
+        break;
+      }
+      case 2:
+        if (byte == '>') {
+          ReportEOF(src_size - i - 1);
+          return;
+        }
+        break;
+    }
+  }
+}
+CPDF_AsciiHexFilter::CPDF_AsciiHexFilter() {
+  m_State = 0;
+}
+void CPDF_AsciiHexFilter::v_FilterIn(const uint8_t* src_buf,
+                                     FX_DWORD src_size,
+                                     CFX_BinaryBuf& dest_buf) {
+  for (FX_DWORD i = 0; i < src_size; i++) {
+    uint8_t byte = src_buf[i];
+    if (PDF_CharType[byte] == 'W') {
+      continue;
+    }
+    int digit;
+    if (byte >= '0' && byte <= '9') {
+      digit = byte - '0';
+    } else if (byte >= 'a' && byte <= 'f') {
+      digit = byte - 'a' + 10;
+    } else if (byte >= 'A' && byte <= 'F') {
+      digit = byte - 'A' + 10;
+    } else {
+      if (m_State) {
+        dest_buf.AppendByte(m_FirstDigit * 16);
+      }
+      ReportEOF(src_size - i - 1);
+      return;
+    }
+    if (m_State == 0) {
+      m_FirstDigit = digit;
+      m_State++;
+    } else {
+      dest_buf.AppendByte(m_FirstDigit * 16 + digit);
+      m_State--;
+    }
+  }
+}
+CPDF_RunLenFilter::CPDF_RunLenFilter() {
+  m_State = 0;
+  m_Count = 0;
+}
+void CPDF_RunLenFilter::v_FilterIn(const uint8_t* src_buf,
+                                   FX_DWORD src_size,
+                                   CFX_BinaryBuf& dest_buf) {
+  for (FX_DWORD i = 0; i < src_size; i++) {
+    uint8_t byte = src_buf[i];
+    switch (m_State) {
+      case 0:
+        if (byte < 128) {
+          m_State = 1;
+          m_Count = byte + 1;
+        } else if (byte == 128) {
+          ReportEOF(src_size - i - 1);
+          return;
+        } else {
+          m_State = 2;
+          m_Count = 257 - byte;
+        }
+        break;
+      case 1:
+        dest_buf.AppendByte(byte);
+        m_Count--;
+        if (m_Count == 0) {
+          m_State = 0;
+        }
+        break;
+      case 2: {
+        dest_buf.AppendBlock(NULL, m_Count);
+        FXSYS_memset(dest_buf.GetBuffer() + dest_buf.GetSize() - m_Count, byte,
+                     m_Count);
+        m_State = 0;
+        break;
+      }
+    }
+  }
+}
+CPDF_JpegFilter::CPDF_JpegFilter() {
+  m_pContext = NULL;
+  m_bGotHeader = FALSE;
+  m_pScanline = NULL;
+  m_iLine = 0;
+}
+CPDF_JpegFilter::~CPDF_JpegFilter() {
+  if (m_pScanline) {
+    FX_Free(m_pScanline);
+  }
+  if (m_pContext) {
+    CPDF_ModuleMgr::Get()->GetJpegModule()->Finish(m_pContext);
+  }
+}
+void CPDF_JpegFilter::v_FilterIn(const uint8_t* src_buf,
+                                 FX_DWORD src_size,
+                                 CFX_BinaryBuf& dest_buf) {
+  if (m_pContext == NULL) {
+    m_pContext = CPDF_ModuleMgr::Get()->GetJpegModule()->Start();
+  }
+  const uint8_t* jpeg_src_buf;
+  FX_DWORD jpeg_src_size;
+  CFX_BinaryBuf temp_buf;
+  if (m_InputBuf.GetSize()) {
+    temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size);
+    temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize());
+    m_InputBuf.Clear();
+    temp_buf.AppendBlock(src_buf, src_size);
+    jpeg_src_buf = temp_buf.GetBuffer();
+    jpeg_src_size = temp_buf.GetSize();
+  } else {
+    jpeg_src_buf = src_buf;
+    jpeg_src_size = src_size;
+  }
+  CPDF_ModuleMgr::Get()->GetJpegModule()->Input(m_pContext, jpeg_src_buf,
+                                                jpeg_src_size);
+  if (!m_bGotHeader) {
+    int ret = CPDF_ModuleMgr::Get()->GetJpegModule()->ReadHeader(
+        m_pContext, &m_Width, &m_Height, &m_nComps);
+    int left_size =
+        CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext);
+    if (ret == 1) {
+      ReportEOF(left_size);
+      return;
+    }
+    if (ret == 2) {
+      m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size,
+                             left_size);
+      return;
+    }
+    CPDF_ModuleMgr::Get()->GetJpegModule()->StartScanline(m_pContext, 1);
+    m_bGotHeader = TRUE;
+    m_Pitch = m_Width * m_nComps;
+  }
+  if (m_pScanline == NULL) {
+    m_pScanline = FX_Alloc(uint8_t, m_Pitch + 4);
+  }
+  while (1) {
+    if (!CPDF_ModuleMgr::Get()->GetJpegModule()->ReadScanline(m_pContext,
+                                                              m_pScanline)) {
+      int left_size =
+          CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext);
+      m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size,
+                             left_size);
+      break;
+    }
+    dest_buf.AppendBlock(m_pScanline, m_Pitch);
+    m_iLine++;
+    if (m_iLine == m_Height) {
+      ReportEOF(
+          CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext));
+      return;
+    }
+  }
+}
+CPDF_FaxFilter::CPDF_FaxFilter() {
+  m_Encoding = 0;
+  m_bEndOfLine = FALSE;
+  m_bByteAlign = FALSE;
+  m_bBlack = FALSE;
+  m_nRows = 0;
+  m_nColumns = 0;
+  m_Pitch = 0;
+  m_pScanlineBuf = NULL;
+  m_pRefBuf = NULL;
+  m_iRow = 0;
+  m_InputBitPos = 0;
+}
+CPDF_FaxFilter::~CPDF_FaxFilter() {
+  if (m_pScanlineBuf) {
+    FX_Free(m_pScanlineBuf);
+  }
+  if (m_pRefBuf) {
+    FX_Free(m_pRefBuf);
+  }
+}
+FX_BOOL CPDF_FaxFilter::Initialize(int Encoding,
+                                   int bEndOfLine,
+                                   int bByteAlign,
+                                   int bBlack,
+                                   int nRows,
+                                   int nColumns) {
+  m_Encoding = Encoding;
+  m_bEndOfLine = bEndOfLine;
+  m_bByteAlign = bByteAlign;
+  m_bBlack = bBlack;
+  m_nRows = nRows;
+  m_nColumns = nColumns;
+  m_Pitch = (m_nColumns + 7) / 8;
+  m_pScanlineBuf = FX_Alloc(uint8_t, m_Pitch);
+  m_pRefBuf = FX_Alloc(uint8_t, m_Pitch);
+  FXSYS_memset(m_pScanlineBuf, 0xff, m_Pitch);
+  FXSYS_memset(m_pRefBuf, 0xff, m_Pitch);
+  m_iRow = 0;
+  m_InputBitPos = 0;
+  return TRUE;
+}
+void CPDF_FaxFilter::v_FilterIn(const uint8_t* src_buf,
+                                FX_DWORD src_size,
+                                CFX_BinaryBuf& dest_buf) {
+  const uint8_t* fax_src_buf;
+  FX_DWORD fax_src_size;
+  CFX_BinaryBuf temp_buf;
+  int bitpos;
+  if (m_InputBuf.GetSize()) {
+    temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size);
+    temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize());
+    m_InputBuf.Clear();
+    temp_buf.AppendBlock(src_buf, src_size);
+    fax_src_buf = temp_buf.GetBuffer();
+    fax_src_size = temp_buf.GetSize();
+    bitpos = m_InputBitPos;
+  } else {
+    fax_src_buf = src_buf;
+    fax_src_size = src_size;
+    bitpos = 0;
+  }
+  ProcessData(fax_src_buf, fax_src_size, bitpos, FALSE, dest_buf);
+  int left_bits = fax_src_size * 8 - bitpos;
+  m_InputBuf.AppendBlock(fax_src_buf + bitpos / 8, (left_bits + 7) / 8);
+  m_InputBitPos = bitpos % 8;
+}
+void CPDF_FaxFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf) {
+  ProcessData(m_InputBuf.GetBuffer(), m_InputBuf.GetSize(), m_InputBitPos, TRUE,
+              dest_buf);
+}
+FX_BOOL _FaxSkipEOL(const uint8_t* src_buf, int bitsize, int& bitpos);
+FX_BOOL _FaxG4GetRow(const uint8_t* src_buf,
+                     int bitsize,
+                     int& bitpos,
+                     uint8_t* dest_buf,
+                     const uint8_t* ref_buf,
+                     int columns);
+FX_BOOL _FaxGet1DLine(const uint8_t* src_buf,
+                      int bitsize,
+                      int& bitpos,
+                      uint8_t* dest_buf,
+                      int columns);
+void CPDF_FaxFilter::ProcessData(const uint8_t* src_buf,
+                                 FX_DWORD src_size,
+                                 int& bitpos,
+                                 FX_BOOL bFinish,
+                                 CFX_BinaryBuf& dest_buf) {
+  int bitsize = src_size * 8;
+  while (1) {
+    if ((bitsize < bitpos + 256) && !bFinish) {
+      return;
+    }
+    int start_bitpos = bitpos;
+    FXSYS_memset(m_pScanlineBuf, 0xff, m_Pitch);
+    if (!ReadLine(src_buf, bitsize, bitpos)) {
+      bitpos = start_bitpos;
+      return;
+    }
+    if (m_Encoding) {
+      FXSYS_memcpy(m_pRefBuf, m_pScanlineBuf, m_Pitch);
+    }
+    if (m_bBlack) {
+      for (int i = 0; i < m_Pitch; i++) {
+        m_pScanlineBuf[i] = ~m_pScanlineBuf[i];
+      }
+    }
+    dest_buf.AppendBlock(m_pScanlineBuf, m_Pitch);
+    m_iRow++;
+    if (m_iRow == m_nRows) {
+      ReportEOF(src_size - (bitpos + 7) / 8);
+      return;
+    }
+  }
+}
+FX_BOOL CPDF_FaxFilter::ReadLine(const uint8_t* src_buf,
+                                 int bitsize,
+                                 int& bitpos) {
+  if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) {
+    return FALSE;
+  }
+  FX_BOOL ret;
+  if (m_Encoding < 0) {
+    ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf,
+                       m_nColumns);
+  } else if (m_Encoding == 0) {
+    ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns);
+  } else {
+    if (bitpos == bitsize) {
+      return FALSE;
+    }
+    FX_BOOL bNext1D = src_buf[bitpos / 8] & (1 << (7 - bitpos % 8));
+    bitpos++;
+    if (bNext1D) {
+      ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns);
+    } else {
+      ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf,
+                         m_nColumns);
+    }
+  }
+  if (!ret) {
+    return FALSE;
+  }
+  if (m_bEndOfLine)
+    if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) {
+      return FALSE;
+    }
+  if (m_bByteAlign) {
+    bitpos = (bitpos + 7) / 8 * 8;
+  }
+  return TRUE;
+}