1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// found in the LICENSE file.
4ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
74d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcodec/codec/codec_int.h"
8e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
94d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <algorithm>
10ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include <memory>
114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <utility>
124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <vector>
13ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcodec/fx_codec.h"
154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcrt/fx_ext.h"
164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "third_party/base/ptr_util.h"
17ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "third_party/zlib_v128/zlib.h"
18ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
19ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannextern "C" {
20ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic void* my_alloc_func(void* opaque,
21ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                           unsigned int items,
22ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                           unsigned int size) {
23ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return FX_Alloc2D(uint8_t, items, size);
24ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
25ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic void my_free_func(void* opaque, void* address) {
26ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_Free(address);
27ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
28ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic int FPDFAPI_FlateGetTotalOut(void* context) {
29ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return ((z_stream*)context)->total_out;
30ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
31ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic int FPDFAPI_FlateGetTotalIn(void* context) {
32ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return ((z_stream*)context)->total_in;
33ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic bool FPDFAPI_FlateCompress(unsigned char* dest_buf,
36ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                  unsigned long* dest_size,
37ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                  const unsigned char* src_buf,
38ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                  unsigned long src_size) {
394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return compress(dest_buf, dest_size, src_buf, src_size) == Z_OK;
40e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
42ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int),
43ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        void (*free_func)(void*, void*)) {
44ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  z_stream* p = (z_stream*)alloc_func(0, 1, sizeof(z_stream));
454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!p)
464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
48ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FXSYS_memset(p, 0, sizeof(z_stream));
49ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  p->zalloc = alloc_func;
50ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  p->zfree = free_func;
51ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  inflateInit(p);
52ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return p;
53ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
55ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid FPDFAPI_FlateInput(void* context,
56ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        const unsigned char* src_buf,
57ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        unsigned int src_size) {
58ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ((z_stream*)context)->next_in = (unsigned char*)src_buf;
59ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ((z_stream*)context)->avail_in = src_size;
60ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
62ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannint FPDFAPI_FlateOutput(void* context,
63ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        unsigned char* dest_buf,
64ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        unsigned int dest_size) {
65ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ((z_stream*)context)->next_out = dest_buf;
66ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ((z_stream*)context)->avail_out = dest_size;
67ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  unsigned int pre_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context);
68ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int ret = inflate((z_stream*)context, Z_SYNC_FLUSH);
69ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  unsigned int post_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context);
70ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  unsigned int written = post_pos - pre_pos;
71ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (written < dest_size) {
72ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FXSYS_memset(dest_buf + written, '\0', dest_size - written);
73ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
74ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return ret;
75ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
77ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannint FPDFAPI_FlateGetAvailIn(void* context) {
78ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return ((z_stream*)context)->avail_in;
79ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
81ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannint FPDFAPI_FlateGetAvailOut(void* context) {
82ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return ((z_stream*)context)->avail_out;
83ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
85ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid FPDFAPI_FlateEnd(void* context) {
86ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  inflateEnd((z_stream*)context);
87ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ((z_stream*)context)->zfree(0, context);
88ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
90ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}  // extern "C"
91ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
92ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannnamespace {
93ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
94ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannclass CLZWDecoder {
95ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann public:
96ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int Decode(uint8_t* output,
974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             uint32_t& outlen,
98ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann             const uint8_t* input,
994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             uint32_t& size,
1004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             bool bEarlyChange);
101ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
102ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann private:
1034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  void AddCode(uint32_t prefix_code, uint8_t append_char);
1044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  void DecodeString(uint32_t code);
105ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
1064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t m_InPos;
1074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t m_OutPos;
108ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* m_pOutput;
109ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const uint8_t* m_pInput;
1104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool m_Early;
1114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t m_CodeArray[5021];
1124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t m_nCodes;
113ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t m_DecodeStack[4000];
1144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t m_StackLen;
115ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int m_CodeLen;
116e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
1174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid CLZWDecoder::AddCode(uint32_t prefix_code, uint8_t append_char) {
119ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (m_nCodes + m_Early == 4094) {
120ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
121ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
122ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_CodeArray[m_nCodes++] = (prefix_code << 16) | append_char;
123ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (m_nCodes + m_Early == 512 - 258) {
124ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_CodeLen = 10;
125ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else if (m_nCodes + m_Early == 1024 - 258) {
126ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_CodeLen = 11;
127ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else if (m_nCodes + m_Early == 2048 - 258) {
128ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_CodeLen = 12;
129ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
1314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid CLZWDecoder::DecodeString(uint32_t code) {
132ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (1) {
133ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int index = code - 258;
134ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (index < 0 || index >= (int)m_nCodes) {
135ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
136e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
1374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    uint32_t data = m_CodeArray[index];
138e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_StackLen >= sizeof(m_DecodeStack)) {
139ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return;
140e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
141ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_DecodeStack[m_StackLen++] = (uint8_t)data;
142ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    code = data >> 16;
143ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
144ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (m_StackLen >= sizeof(m_DecodeStack)) {
145ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
146ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
147ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_DecodeStack[m_StackLen++] = (uint8_t)code;
148e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
149ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannint CLZWDecoder::Decode(uint8_t* dest_buf,
1504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        uint32_t& dest_size,
151ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        const uint8_t* src_buf,
1524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        uint32_t& src_size,
1534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        bool bEarlyChange) {
154ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_CodeLen = 9;
155ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_InPos = 0;
156ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_OutPos = 0;
157ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_pInput = src_buf;
158ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_pOutput = dest_buf;
159ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_Early = bEarlyChange ? 1 : 0;
160ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_nCodes = 0;
1614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t old_code = (uint32_t)-1;
1624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint8_t last_char = 0;
163ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (1) {
164ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (m_InPos + m_CodeLen > src_size * 8) {
165ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
166ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
167ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int byte_pos = m_InPos / 8;
168ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int bit_pos = m_InPos % 8, bit_left = m_CodeLen;
1694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    uint32_t code = 0;
170ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (bit_pos) {
171ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      bit_left -= 8 - bit_pos;
172ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      code = (m_pInput[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_left;
173ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
174ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (bit_left < 8) {
175ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      code |= m_pInput[byte_pos] >> (8 - bit_left);
176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else {
177ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      bit_left -= 8;
178ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      code |= m_pInput[byte_pos++] << bit_left;
179ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (bit_left) {
180ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        code |= m_pInput[byte_pos] >> (8 - bit_left);
181ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
182ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
183ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_InPos += m_CodeLen;
184ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (code < 256) {
185ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (m_OutPos == dest_size) {
186ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        return -5;
187ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
188ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (m_pOutput) {
189ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        m_pOutput[m_OutPos] = (uint8_t)code;
190ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
191ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_OutPos++;
192ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      last_char = (uint8_t)code;
1934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (old_code != (uint32_t)-1) {
194ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        AddCode(old_code, last_char);
195ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
196ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      old_code = code;
197ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else if (code == 256) {
198ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_CodeLen = 9;
199ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_nCodes = 0;
2004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      old_code = (uint32_t)-1;
201ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else if (code == 257) {
202ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
203ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else {
2044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (old_code == (uint32_t)-1) {
205ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        return 2;
206ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
207ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_StackLen = 0;
208ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (code >= m_nCodes + 258) {
209ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (m_StackLen < sizeof(m_DecodeStack)) {
210ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          m_DecodeStack[m_StackLen++] = last_char;
211ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
212ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        DecodeString(old_code);
213ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
214ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        DecodeString(code);
215ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
216ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (m_OutPos + m_StackLen > dest_size) {
217ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        return -5;
218ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
219ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (m_pOutput) {
2204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        for (uint32_t i = 0; i < m_StackLen; i++) {
221ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          m_pOutput[m_OutPos + i] = m_DecodeStack[m_StackLen - i - 1];
222ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
223ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
224ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_OutPos += m_StackLen;
225ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      last_char = m_DecodeStack[m_StackLen - 1];
226ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (old_code < 256) {
227ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        AddCode(old_code, last_char);
228ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else if (old_code - 258 >= m_nCodes) {
229ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        dest_size = m_OutPos;
230ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        src_size = (m_InPos + 7) / 8;
231ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        return 0;
232ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
233ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        AddCode(old_code, last_char);
234ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
235ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      old_code = code;
236ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
237ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
238ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  dest_size = m_OutPos;
239ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  src_size = (m_InPos + 7) / 8;
240ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return 0;
241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
242ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
2434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannuint8_t PathPredictor(int a, int b, int c) {
244ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int p = a + b - c;
245ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int pa = FXSYS_abs(p - a);
246ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int pb = FXSYS_abs(p - b);
247ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int pc = FXSYS_abs(p - c);
2484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (pa <= pb && pa <= pc)
249ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return (uint8_t)a;
2504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (pb <= pc)
251ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return (uint8_t)b;
252ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return (uint8_t)c;
253ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
254ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
2554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNG_PredictorEncode(uint8_t** data_buf, uint32_t* data_size) {
2564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const int row_size = 7;
2574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const int row_count = (*data_size + row_size - 1) / row_size;
2584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const int last_row_size = *data_size % row_size;
259ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size + 1, row_count);
260ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int byte_cnt = 0;
2614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint8_t* pSrcData = *data_buf;
262ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* pDestData = dest_buf;
263ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int row = 0; row < row_count; row++) {
2644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    for (int byte = 0; byte < row_size && byte_cnt < (int)*data_size; byte++) {
2654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      pDestData[0] = 2;
2664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      uint8_t up = 0;
2674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (row)
2684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        up = pSrcData[byte - row_size];
2694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      pDestData[byte + 1] = pSrcData[byte] - up;
2704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      ++byte_cnt;
271ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
272ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pDestData += (row_size + 1);
273ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pSrcData += row_size;
274ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
2754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FX_Free(*data_buf);
2764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *data_buf = dest_buf;
2774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *data_size = (row_size + 1) * row_count -
2784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               (last_row_size > 0 ? (row_size - last_row_size) : 0);
279ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
280ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
281ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid PNG_PredictLine(uint8_t* pDestData,
282ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     const uint8_t* pSrcData,
283ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     const uint8_t* pLastLine,
284ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     int bpc,
285ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     int nColors,
286ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     int nPixels) {
287ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int row_size = (nPixels * bpc * nColors + 7) / 8;
288ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int BytesPerPixel = (bpc * nColors + 7) / 8;
289ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t tag = pSrcData[0];
290ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (tag == 0) {
291ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FXSYS_memmove(pDestData, pSrcData + 1, row_size);
292ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
293ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
294ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int byte = 0; byte < row_size; byte++) {
295ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    uint8_t raw_byte = pSrcData[byte + 1];
296ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    switch (tag) {
297ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      case 1: {
298ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t left = 0;
299ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (byte >= BytesPerPixel) {
300ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          left = pDestData[byte - BytesPerPixel];
301ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
302ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pDestData[byte] = raw_byte + left;
303ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
304ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
305ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      case 2: {
306ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t up = 0;
307ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (pLastLine) {
308ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          up = pLastLine[byte];
309ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
310ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pDestData[byte] = raw_byte + up;
311ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
312ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
313ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      case 3: {
314ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t left = 0;
315ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (byte >= BytesPerPixel) {
316ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          left = pDestData[byte - BytesPerPixel];
317ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
318ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t up = 0;
319ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (pLastLine) {
320ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          up = pLastLine[byte];
321ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
322ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pDestData[byte] = raw_byte + (up + left) / 2;
323ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
324ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
325ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      case 4: {
326ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t left = 0;
327ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (byte >= BytesPerPixel) {
328ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          left = pDestData[byte - BytesPerPixel];
329ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
330ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t up = 0;
331ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (pLastLine) {
332ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          up = pLastLine[byte];
333ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
334ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t upper_left = 0;
335ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (byte >= BytesPerPixel && pLastLine) {
336ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          upper_left = pLastLine[byte - BytesPerPixel];
337ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
3384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        pDestData[byte] = raw_byte + PathPredictor(left, up, upper_left);
339ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
340ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
341ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      default:
342ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pDestData[byte] = raw_byte;
343ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
344ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
345ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
346ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
347ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
3484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool PNG_Predictor(uint8_t*& data_buf,
3494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   uint32_t& data_size,
3504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   int Colors,
3514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   int BitsPerComponent,
3524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   int Columns) {
353ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8;
354ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
355ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (row_size <= 0)
3564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
357ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const int row_count = (data_size + row_size) / (row_size + 1);
358ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (row_count <= 0)
3594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
360ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const int last_row_size = data_size % (row_size + 1);
361ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size, row_count);
362ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int byte_cnt = 0;
363ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* pSrcData = data_buf;
364ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* pDestData = dest_buf;
365ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int row = 0; row < row_count; row++) {
366ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    uint8_t tag = pSrcData[0];
367ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    byte_cnt++;
368ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (tag == 0) {
369ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int move_size = row_size;
370ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if ((row + 1) * (move_size + 1) > (int)data_size) {
371ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        move_size = last_row_size - 1;
372ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
373ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXSYS_memmove(pDestData, pSrcData + 1, move_size);
374ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pSrcData += move_size + 1;
375ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pDestData += move_size;
376ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      byte_cnt += move_size;
377ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
378ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
379ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte++) {
380ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      uint8_t raw_byte = pSrcData[byte + 1];
381ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      switch (tag) {
382ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case 1: {
383ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          uint8_t left = 0;
384ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (byte >= BytesPerPixel) {
385ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            left = pDestData[byte - BytesPerPixel];
386ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
387ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          pDestData[byte] = raw_byte + left;
388ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          break;
389ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
390ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case 2: {
391ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          uint8_t up = 0;
392ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (row) {
393ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            up = pDestData[byte - row_size];
394ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
395ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          pDestData[byte] = raw_byte + up;
396ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          break;
397ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
398ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case 3: {
399ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          uint8_t left = 0;
400ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (byte >= BytesPerPixel) {
401ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            left = pDestData[byte - BytesPerPixel];
402ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
403ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          uint8_t up = 0;
404ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (row) {
405ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            up = pDestData[byte - row_size];
406ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
407ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          pDestData[byte] = raw_byte + (up + left) / 2;
408ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          break;
409ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
410ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case 4: {
411ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          uint8_t left = 0;
412ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (byte >= BytesPerPixel) {
413ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            left = pDestData[byte - BytesPerPixel];
414ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
415ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          uint8_t up = 0;
416ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (row) {
417ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            up = pDestData[byte - row_size];
418ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
419ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          uint8_t upper_left = 0;
420ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (byte >= BytesPerPixel && row) {
421ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            upper_left = pDestData[byte - row_size - BytesPerPixel];
422ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
4234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          pDestData[byte] = raw_byte + PathPredictor(left, up, upper_left);
424ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          break;
425ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
426ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        default:
427ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          pDestData[byte] = raw_byte;
428ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          break;
429ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
430ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      byte_cnt++;
431ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
432ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pSrcData += row_size + 1;
433ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pDestData += row_size;
434ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
435ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_Free(data_buf);
436ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  data_buf = dest_buf;
437ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  data_size = row_size * row_count -
438ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              (last_row_size > 0 ? (row_size + 1 - last_row_size) : 0);
4394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
440ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
441ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
442ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid TIFF_PredictLine(uint8_t* dest_buf,
4434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      uint32_t row_size,
444ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      int BitsPerComponent,
445ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      int Colors,
446ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      int Columns) {
447ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (BitsPerComponent == 1) {
4484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int row_bits = std::min(BitsPerComponent * Colors * Columns,
4494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                            pdfium::base::checked_cast<int>(row_size * 8));
450ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int index_pre = 0;
451ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int col_pre = 0;
452ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int i = 1; i < row_bits; i++) {
453ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int col = i % 8;
454ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int index = i / 8;
455ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (((dest_buf[index] >> (7 - col)) & 1) ^
456ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          ((dest_buf[index_pre] >> (7 - col_pre)) & 1)) {
457ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        dest_buf[index] |= 1 << (7 - col);
458ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
459ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        dest_buf[index] &= ~(1 << (7 - col));
460ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
461ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      index_pre = index;
462ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      col_pre = col;
463e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
464ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
465ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
466ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int BytesPerPixel = BitsPerComponent * Colors / 8;
467ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (BitsPerComponent == 16) {
4684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    for (uint32_t i = BytesPerPixel; i < row_size; i += 2) {
4694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      uint16_t pixel =
470ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1];
471ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pixel += (dest_buf[i] << 8) | dest_buf[i + 1];
472ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dest_buf[i] = pixel >> 8;
473ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dest_buf[i + 1] = (uint8_t)pixel;
474ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
475ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
4764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    for (uint32_t i = BytesPerPixel; i < row_size; i++) {
477ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dest_buf[i] += dest_buf[i - BytesPerPixel];
478ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
479ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
480ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
481ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
4824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool TIFF_Predictor(uint8_t*& data_buf,
4834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    uint32_t& data_size,
4844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    int Colors,
4854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    int BitsPerComponent,
4864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    int Columns) {
487ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
488ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (row_size == 0)
4894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
490ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const int row_count = (data_size + row_size - 1) / row_size;
491ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const int last_row_size = data_size % row_size;
492ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int row = 0; row < row_count; row++) {
493ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    uint8_t* scan_line = data_buf + row * row_size;
494ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if ((row + 1) * row_size > (int)data_size) {
495ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      row_size = last_row_size;
496ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
497ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    TIFF_PredictLine(scan_line, row_size, BitsPerComponent, Colors, Columns);
498ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
4994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
500ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
501ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
502ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid FlateUncompress(const uint8_t* src_buf,
5034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     uint32_t src_size,
5044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     uint32_t orig_size,
505ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     uint8_t*& dest_buf,
5064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     uint32_t& dest_size,
5074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     uint32_t& offset) {
5084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t guess_size = orig_size ? orig_size : src_size * 2;
5094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const uint32_t kStepSize = 10240;
5104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t alloc_step = orig_size ? kStepSize : std::min(src_size, kStepSize);
5114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  static const uint32_t kMaxInitialAllocSize = 10000000;
512ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (guess_size > kMaxInitialAllocSize) {
513ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    guess_size = kMaxInitialAllocSize;
514ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    alloc_step = kMaxInitialAllocSize;
515ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
5164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t buf_size = guess_size;
5174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t last_buf_size = buf_size;
518ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
519ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  dest_buf = nullptr;
520ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  dest_size = 0;
521ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void* context = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
522ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!context)
523ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
524ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
525ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  std::unique_ptr<uint8_t, FxFreeDeleter> guess_buf(
526ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_Alloc(uint8_t, guess_size + 1));
527ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  guess_buf.get()[guess_size] = '\0';
528ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
529ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDFAPI_FlateInput(context, src_buf, src_size);
530ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
531ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (src_size < kStepSize) {
532ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    // This is the old implementation.
533ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    uint8_t* cur_buf = guess_buf.get();
534ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    while (1) {
535ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size);
536ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (ret != Z_OK)
537ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
538ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context);
539ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (avail_buf_size != 0)
540ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
541ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
5424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      uint32_t old_size = guess_size;
543ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      guess_size += alloc_step;
544ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (guess_size < old_size || guess_size + 1 < guess_size) {
545ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FPDFAPI_FlateEnd(context);
546e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
547ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
548ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
549ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      {
550ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t* new_buf =
551ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            FX_Realloc(uint8_t, guess_buf.release(), guess_size + 1);
552ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        guess_buf.reset(new_buf);
553ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
554ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      guess_buf.get()[guess_size] = '\0';
555ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      cur_buf = guess_buf.get() + old_size;
556ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      buf_size = guess_size - old_size;
557ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
558ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    dest_size = FPDFAPI_FlateGetTotalOut(context);
559ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    offset = FPDFAPI_FlateGetTotalIn(context);
560ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (guess_size / 2 > dest_size) {
561ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      {
562ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t* new_buf =
563ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            FX_Realloc(uint8_t, guess_buf.release(), dest_size + 1);
564ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        guess_buf.reset(new_buf);
565ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
566ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      guess_size = dest_size;
567ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      guess_buf.get()[guess_size] = '\0';
568ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
569ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    dest_buf = guess_buf.release();
570ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
5714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    std::vector<uint8_t*> result_tmp_bufs;
572ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    uint8_t* cur_buf = guess_buf.release();
573ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    while (1) {
574ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size);
575ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context);
576ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (ret != Z_OK) {
577ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        last_buf_size = buf_size - avail_buf_size;
5784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        result_tmp_bufs.push_back(cur_buf);
579ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
580ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
581ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (avail_buf_size != 0) {
582ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        last_buf_size = buf_size - avail_buf_size;
5834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        result_tmp_bufs.push_back(cur_buf);
584ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
585ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
5864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      result_tmp_bufs.push_back(cur_buf);
587ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      cur_buf = FX_Alloc(uint8_t, buf_size + 1);
588ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      cur_buf[buf_size] = '\0';
589ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
590ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    dest_size = FPDFAPI_FlateGetTotalOut(context);
591ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    offset = FPDFAPI_FlateGetTotalIn(context);
5924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (result_tmp_bufs.size() == 1) {
593ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dest_buf = result_tmp_bufs[0];
594e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else {
595ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      uint8_t* result_buf = FX_Alloc(uint8_t, dest_size);
5964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      uint32_t result_pos = 0;
5974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (size_t i = 0; i < result_tmp_bufs.size(); i++) {
598ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        uint8_t* tmp_buf = result_tmp_bufs[i];
5994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        uint32_t tmp_buf_size = buf_size;
6004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (i == result_tmp_bufs.size() - 1) {
601ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          tmp_buf_size = last_buf_size;
602ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
603ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FXSYS_memcpy(result_buf + result_pos, tmp_buf, tmp_buf_size);
604ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        result_pos += tmp_buf_size;
605ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FX_Free(result_tmp_bufs[i]);
606ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
607ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dest_buf = result_buf;
608ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
609ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
610ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDFAPI_FlateEnd(context);
611e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
612ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
613ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}  // namespace
614ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
615ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannclass CCodec_FlateScanlineDecoder : public CCodec_ScanlineDecoder {
616ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann public:
617ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CCodec_FlateScanlineDecoder();
618ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ~CCodec_FlateScanlineDecoder() override;
619ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
620ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void Create(const uint8_t* src_buf,
6214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann              uint32_t src_size,
622ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              int width,
623ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              int height,
624ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              int nComps,
625ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              int bpc,
626ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              int predictor,
627ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              int Colors,
628ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              int BitsPerComponent,
629ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              int Columns);
630ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
631ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  // CCodec_ScanlineDecoder
6324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool v_Rewind() override;
633ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* v_GetNextLine() override;
6344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t GetSrcOffset() override;
635ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
636ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void* m_pFlate;
637ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const uint8_t* m_SrcBuf;
6384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t m_SrcSize;
639ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* m_pScanline;
640ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* m_pLastLine;
641ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* m_pPredictBuffer;
642ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* m_pPredictRaw;
643ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int m_Predictor;
644ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int m_Colors;
645ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int m_BitsPerComponent;
646ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int m_Columns;
6474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t m_PredictPitch;
648ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  size_t m_LeftOver;
649e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
650ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
651ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannCCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder() {
6524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_pFlate = nullptr;
6534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_pScanline = nullptr;
6544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_pLastLine = nullptr;
6554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_pPredictBuffer = nullptr;
6564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_pPredictRaw = nullptr;
657ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_LeftOver = 0;
658e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
659ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannCCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder() {
660ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_Free(m_pScanline);
661ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_Free(m_pLastLine);
662ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_Free(m_pPredictBuffer);
663ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_Free(m_pPredictRaw);
664ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (m_pFlate) {
665ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FPDFAPI_FlateEnd(m_pFlate);
666ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
667e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
668ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid CCodec_FlateScanlineDecoder::Create(const uint8_t* src_buf,
6694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                         uint32_t src_size,
670ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                         int width,
671ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                         int height,
672ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                         int nComps,
673ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                         int bpc,
674ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                         int predictor,
675ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                         int Colors,
676ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                         int BitsPerComponent,
677ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                         int Columns) {
678ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_SrcBuf = src_buf;
679ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_SrcSize = src_size;
680ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_OutputWidth = m_OrigWidth = width;
681ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_OutputHeight = m_OrigHeight = height;
682ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_nComps = nComps;
683ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_bpc = bpc;
6844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_Pitch = (static_cast<uint32_t>(width) * nComps * bpc + 7) / 8;
685ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_pScanline = FX_Alloc(uint8_t, m_Pitch);
686ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_Predictor = 0;
687ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (predictor) {
688ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (predictor >= 10) {
689ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_Predictor = 2;
690ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else if (predictor == 2) {
691ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_Predictor = 1;
692e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
693e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_Predictor) {
694ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (BitsPerComponent * Colors * Columns == 0) {
695ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        BitsPerComponent = m_bpc;
696ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Colors = m_nComps;
697ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Columns = m_OrigWidth;
698ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
699ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_Colors = Colors;
700ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_BitsPerComponent = BitsPerComponent;
701ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_Columns = Columns;
702ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_PredictPitch =
7034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          (static_cast<uint32_t>(m_BitsPerComponent) * m_Colors * m_Columns +
704ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann           7) /
705ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          8;
706ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_pLastLine = FX_Alloc(uint8_t, m_PredictPitch);
707ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_pPredictRaw = FX_Alloc(uint8_t, m_PredictPitch + 1);
708ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_pPredictBuffer = FX_Alloc(uint8_t, m_PredictPitch);
709ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
710ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
711ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
7124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_FlateScanlineDecoder::v_Rewind() {
713ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (m_pFlate) {
714ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FPDFAPI_FlateEnd(m_pFlate);
715ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
716ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_pFlate = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
717ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!m_pFlate) {
7184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
719ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
720ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FPDFAPI_FlateInput(m_pFlate, m_SrcBuf, m_SrcSize);
721ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_LeftOver = 0;
7224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
723ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
724ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannuint8_t* CCodec_FlateScanlineDecoder::v_GetNextLine() {
725ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (m_Predictor) {
726ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (m_Pitch == m_PredictPitch) {
727ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (m_Predictor == 2) {
728ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
729ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine,
730ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        m_BitsPerComponent, m_Colors, m_Columns);
731ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FXSYS_memcpy(m_pLastLine, m_pScanline, m_PredictPitch);
732ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
733e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch);
734ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps,
735ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                         m_OutputWidth);
736ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
737e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else {
738ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      size_t bytes_to_go = m_Pitch;
739ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      size_t read_leftover =
740ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftOver;
741ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (read_leftover) {
742ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FXSYS_memcpy(m_pScanline,
743ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     m_pPredictBuffer + m_PredictPitch - m_LeftOver,
744ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     read_leftover);
745ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        m_LeftOver -= read_leftover;
746ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        bytes_to_go -= read_leftover;
747ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
748ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      while (bytes_to_go) {
749ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (m_Predictor == 2) {
750ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
751ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine,
752ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                          m_BitsPerComponent, m_Colors, m_Columns);
753ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          FXSYS_memcpy(m_pLastLine, m_pPredictBuffer, m_PredictPitch);
754e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
755ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          FPDFAPI_FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch);
756ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPerComponent,
757ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                           m_Colors, m_Columns);
758ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        }
759ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        size_t read_bytes =
760ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch;
761ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FXSYS_memcpy(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer,
762ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     read_bytes);
763ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        m_LeftOver += m_PredictPitch - read_bytes;
764ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        bytes_to_go -= read_bytes;
765ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
766ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
767ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
768ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch);
769ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
770ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return m_pScanline;
771ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
7724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannuint32_t CCodec_FlateScanlineDecoder::GetSrcOffset() {
773ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return FPDFAPI_FlateGetTotalIn(m_pFlate);
774ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
775e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
7764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstd::unique_ptr<CCodec_ScanlineDecoder> CCodec_FlateModule::CreateDecoder(
777ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    const uint8_t* src_buf,
7784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    uint32_t src_size,
779ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int width,
780ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int height,
781ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int nComps,
782ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int bpc,
783ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int predictor,
784ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int Colors,
785ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int BitsPerComponent,
786ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int Columns) {
7874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  auto pDecoder = pdfium::MakeUnique<CCodec_FlateScanlineDecoder>();
788ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pDecoder->Create(src_buf, src_size, width, height, nComps, bpc, predictor,
789ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                   Colors, BitsPerComponent, Columns);
7904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return std::move(pDecoder);
791e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
7924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannuint32_t CCodec_FlateModule::FlateOrLZWDecode(bool bLZW,
794ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                              const uint8_t* src_buf,
7954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                              uint32_t src_size,
7964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                              bool bEarlyChange,
797ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                              int predictor,
798ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                              int Colors,
799ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                              int BitsPerComponent,
800ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                              int Columns,
8014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                              uint32_t estimated_size,
802ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                              uint8_t*& dest_buf,
8034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                              uint32_t& dest_size) {
8044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  dest_buf = nullptr;
8054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t offset = 0;
806ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int predictor_type = 0;
807ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (predictor) {
808ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (predictor >= 10) {
809ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      predictor_type = 2;
810ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else if (predictor == 2) {
811ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      predictor_type = 1;
812ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
813ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
814ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (bLZW) {
815ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    {
816ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      std::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder);
8174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      dest_size = (uint32_t)-1;
818ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      offset = src_size;
8194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int err =
8204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          decoder->Decode(nullptr, dest_size, src_buf, offset, bEarlyChange);
821ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (err || dest_size == 0 || dest_size + 1 < dest_size) {
8224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        return FX_INVALID_OFFSET;
823ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
824e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
825ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    {
826ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      std::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder);
827ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dest_buf = FX_Alloc(uint8_t, dest_size + 1);
828ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dest_buf[dest_size] = '\0';
829ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      decoder->Decode(dest_buf, dest_size, src_buf, offset, bEarlyChange);
830ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
831ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
832ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FlateUncompress(src_buf, src_size, estimated_size, dest_buf, dest_size,
833ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                    offset);
834ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
835ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (predictor_type == 0) {
836ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return offset;
837ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
8384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool ret = true;
839ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (predictor_type == 2) {
840ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    ret = PNG_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns);
841ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else if (predictor_type == 1) {
842ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    ret =
843ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        TIFF_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns);
844ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
8454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return ret ? offset : FX_INVALID_OFFSET;
846ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
8474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_FlateModule::Encode(const uint8_t* src_buf,
8494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                uint32_t src_size,
8504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                uint8_t** dest_buf,
8514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                uint32_t* dest_size) {
8524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *dest_size = src_size + src_size / 1000 + 12;
8534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *dest_buf = FX_Alloc(uint8_t, *dest_size);
8544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  unsigned long temp_size = *dest_size;
8554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!FPDFAPI_FlateCompress(*dest_buf, &temp_size, src_buf, src_size))
8564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
8574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *dest_size = (uint32_t)temp_size;
8594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
8604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
8614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_FlateModule::PngEncode(const uint8_t* src_buf,
8634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                   uint32_t src_size,
8644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                   uint8_t** dest_buf,
8654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                   uint32_t* dest_size) {
8664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint8_t* pSrcBuf = FX_Alloc(uint8_t, src_size);
867ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FXSYS_memcpy(pSrcBuf, src_buf, src_size);
8684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  PNG_PredictorEncode(&pSrcBuf, &src_size);
8694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool ret = Encode(pSrcBuf, src_size, dest_buf, dest_size);
870ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_Free(pSrcBuf);
871ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return ret;
872ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
873