1// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include <algorithm>
8#include <memory>
9#include <vector>
10
11#include "core/fxcodec/codec/codec_int.h"
12#include "core/fxcodec/fx_codec.h"
13#include "core/fxcrt/fx_memory.h"
14#include "third_party/base/ptr_util.h"
15
16namespace {
17
18const uint8_t OneLeadPos[256] = {
19    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
20    3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
21    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
22    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
23    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
24    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
25    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
27    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
28    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30};
31const uint8_t ZeroLeadPos[256] = {
32    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
38    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
39    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
40    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
41    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
42    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
43};
44
45// Limit of image dimension, an arbitrary large number.
46const int kMaxImageDimension = 0x01FFFF;
47
48int FindBit(const uint8_t* data_buf, int max_pos, int start_pos, int bit) {
49  ASSERT(start_pos >= 0);
50  if (start_pos >= max_pos)
51    return max_pos;
52
53  const uint8_t* leading_pos = bit ? OneLeadPos : ZeroLeadPos;
54  if (start_pos % 8) {
55    uint8_t data = data_buf[start_pos / 8];
56    if (bit)
57      data &= 0xff >> (start_pos % 8);
58    else
59      data |= 0xff << (8 - start_pos % 8);
60
61    if (leading_pos[data] < 8)
62      return start_pos / 8 * 8 + leading_pos[data];
63
64    start_pos += 7;
65  }
66  uint8_t skip = bit ? 0x00 : 0xff;
67  int byte_pos = start_pos / 8;
68  int max_byte = (max_pos + 7) / 8;
69  while (byte_pos < max_byte) {
70    if (data_buf[byte_pos] != skip)
71      break;
72
73    ++byte_pos;
74  }
75  if (byte_pos == max_byte)
76    return max_pos;
77
78  return std::min(leading_pos[data_buf[byte_pos]] + byte_pos * 8, max_pos);
79}
80
81void FaxG4FindB1B2(const std::vector<uint8_t>& ref_buf,
82                   int columns,
83                   int a0,
84                   bool a0color,
85                   int* b1,
86                   int* b2) {
87  uint8_t first_bit =
88      (a0 < 0) ? 1 : ((ref_buf[a0 / 8] & (1 << (7 - a0 % 8))) != 0);
89  *b1 = FindBit(ref_buf.data(), columns, a0 + 1, !first_bit);
90  if (*b1 >= columns) {
91    *b1 = *b2 = columns;
92    return;
93  }
94  if (first_bit == !a0color) {
95    *b1 = FindBit(ref_buf.data(), columns, *b1 + 1, first_bit);
96    first_bit = !first_bit;
97  }
98  if (*b1 >= columns) {
99    *b1 = *b2 = columns;
100    return;
101  }
102  *b2 = FindBit(ref_buf.data(), columns, *b1 + 1, first_bit);
103}
104
105void FaxFillBits(uint8_t* dest_buf, int columns, int startpos, int endpos) {
106  startpos = std::max(startpos, 0);
107  endpos = std::min(std::max(endpos, 0), columns);
108  if (startpos >= endpos)
109    return;
110
111  int first_byte = startpos / 8;
112  int last_byte = (endpos - 1) / 8;
113  if (first_byte == last_byte) {
114    for (int i = startpos % 8; i <= (endpos - 1) % 8; ++i)
115      dest_buf[first_byte] -= 1 << (7 - i);
116    return;
117  }
118
119  for (int i = startpos % 8; i < 8; ++i)
120    dest_buf[first_byte] -= 1 << (7 - i);
121  for (int i = 0; i <= (endpos - 1) % 8; ++i)
122    dest_buf[last_byte] -= 1 << (7 - i);
123
124  if (last_byte > first_byte + 1)
125    FXSYS_memset(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1);
126}
127
128inline bool NextBit(const uint8_t* src_buf, int* bitpos) {
129  int pos = (*bitpos)++;
130  return !!(src_buf[pos / 8] & (1 << (7 - pos % 8)));
131}
132
133const uint8_t FaxBlackRunIns[] = {
134    0,          2,          0x02,       3,          0,          0x03,
135    2,          0,          2,          0x02,       1,          0,
136    0x03,       4,          0,          2,          0x02,       6,
137    0,          0x03,       5,          0,          1,          0x03,
138    7,          0,          2,          0x04,       9,          0,
139    0x05,       8,          0,          3,          0x04,       10,
140    0,          0x05,       11,         0,          0x07,       12,
141    0,          2,          0x04,       13,         0,          0x07,
142    14,         0,          1,          0x18,       15,         0,
143    5,          0x08,       18,         0,          0x0f,       64,
144    0,          0x17,       16,         0,          0x18,       17,
145    0,          0x37,       0,          0,          10,         0x08,
146    0x00,       0x07,       0x0c,       0x40,       0x07,       0x0d,
147    0x80,       0x07,       0x17,       24,         0,          0x18,
148    25,         0,          0x28,       23,         0,          0x37,
149    22,         0,          0x67,       19,         0,          0x68,
150    20,         0,          0x6c,       21,         0,          54,
151    0x12,       1984 % 256, 1984 / 256, 0x13,       2048 % 256, 2048 / 256,
152    0x14,       2112 % 256, 2112 / 256, 0x15,       2176 % 256, 2176 / 256,
153    0x16,       2240 % 256, 2240 / 256, 0x17,       2304 % 256, 2304 / 256,
154    0x1c,       2368 % 256, 2368 / 256, 0x1d,       2432 % 256, 2432 / 256,
155    0x1e,       2496 % 256, 2496 / 256, 0x1f,       2560 % 256, 2560 / 256,
156    0x24,       52,         0,          0x27,       55,         0,
157    0x28,       56,         0,          0x2b,       59,         0,
158    0x2c,       60,         0,          0x33,       320 % 256,  320 / 256,
159    0x34,       384 % 256,  384 / 256,  0x35,       448 % 256,  448 / 256,
160    0x37,       53,         0,          0x38,       54,         0,
161    0x52,       50,         0,          0x53,       51,         0,
162    0x54,       44,         0,          0x55,       45,         0,
163    0x56,       46,         0,          0x57,       47,         0,
164    0x58,       57,         0,          0x59,       58,         0,
165    0x5a,       61,         0,          0x5b,       256 % 256,  256 / 256,
166    0x64,       48,         0,          0x65,       49,         0,
167    0x66,       62,         0,          0x67,       63,         0,
168    0x68,       30,         0,          0x69,       31,         0,
169    0x6a,       32,         0,          0x6b,       33,         0,
170    0x6c,       40,         0,          0x6d,       41,         0,
171    0xc8,       128,        0,          0xc9,       192,        0,
172    0xca,       26,         0,          0xcb,       27,         0,
173    0xcc,       28,         0,          0xcd,       29,         0,
174    0xd2,       34,         0,          0xd3,       35,         0,
175    0xd4,       36,         0,          0xd5,       37,         0,
176    0xd6,       38,         0,          0xd7,       39,         0,
177    0xda,       42,         0,          0xdb,       43,         0,
178    20,         0x4a,       640 % 256,  640 / 256,  0x4b,       704 % 256,
179    704 / 256,  0x4c,       768 % 256,  768 / 256,  0x4d,       832 % 256,
180    832 / 256,  0x52,       1280 % 256, 1280 / 256, 0x53,       1344 % 256,
181    1344 / 256, 0x54,       1408 % 256, 1408 / 256, 0x55,       1472 % 256,
182    1472 / 256, 0x5a,       1536 % 256, 1536 / 256, 0x5b,       1600 % 256,
183    1600 / 256, 0x64,       1664 % 256, 1664 / 256, 0x65,       1728 % 256,
184    1728 / 256, 0x6c,       512 % 256,  512 / 256,  0x6d,       576 % 256,
185    576 / 256,  0x72,       896 % 256,  896 / 256,  0x73,       960 % 256,
186    960 / 256,  0x74,       1024 % 256, 1024 / 256, 0x75,       1088 % 256,
187    1088 / 256, 0x76,       1152 % 256, 1152 / 256, 0x77,       1216 % 256,
188    1216 / 256, 0xff};
189
190const uint8_t FaxWhiteRunIns[] = {
191    0,          0,          0,          6,          0x07,       2,
192    0,          0x08,       3,          0,          0x0B,       4,
193    0,          0x0C,       5,          0,          0x0E,       6,
194    0,          0x0F,       7,          0,          6,          0x07,
195    10,         0,          0x08,       11,         0,          0x12,
196    128,        0,          0x13,       8,          0,          0x14,
197    9,          0,          0x1b,       64,         0,          9,
198    0x03,       13,         0,          0x07,       1,          0,
199    0x08,       12,         0,          0x17,       192,        0,
200    0x18,       1664 % 256, 1664 / 256, 0x2a,       16,         0,
201    0x2B,       17,         0,          0x34,       14,         0,
202    0x35,       15,         0,          12,         0x03,       22,
203    0,          0x04,       23,         0,          0x08,       20,
204    0,          0x0c,       19,         0,          0x13,       26,
205    0,          0x17,       21,         0,          0x18,       28,
206    0,          0x24,       27,         0,          0x27,       18,
207    0,          0x28,       24,         0,          0x2B,       25,
208    0,          0x37,       256 % 256,  256 / 256,  42,         0x02,
209    29,         0,          0x03,       30,         0,          0x04,
210    45,         0,          0x05,       46,         0,          0x0a,
211    47,         0,          0x0b,       48,         0,          0x12,
212    33,         0,          0x13,       34,         0,          0x14,
213    35,         0,          0x15,       36,         0,          0x16,
214    37,         0,          0x17,       38,         0,          0x1a,
215    31,         0,          0x1b,       32,         0,          0x24,
216    53,         0,          0x25,       54,         0,          0x28,
217    39,         0,          0x29,       40,         0,          0x2a,
218    41,         0,          0x2b,       42,         0,          0x2c,
219    43,         0,          0x2d,       44,         0,          0x32,
220    61,         0,          0x33,       62,         0,          0x34,
221    63,         0,          0x35,       0,          0,          0x36,
222    320 % 256,  320 / 256,  0x37,       384 % 256,  384 / 256,  0x4a,
223    59,         0,          0x4b,       60,         0,          0x52,
224    49,         0,          0x53,       50,         0,          0x54,
225    51,         0,          0x55,       52,         0,          0x58,
226    55,         0,          0x59,       56,         0,          0x5a,
227    57,         0,          0x5b,       58,         0,          0x64,
228    448 % 256,  448 / 256,  0x65,       512 % 256,  512 / 256,  0x67,
229    640 % 256,  640 / 256,  0x68,       576 % 256,  576 / 256,  16,
230    0x98,       1472 % 256, 1472 / 256, 0x99,       1536 % 256, 1536 / 256,
231    0x9a,       1600 % 256, 1600 / 256, 0x9b,       1728 % 256, 1728 / 256,
232    0xcc,       704 % 256,  704 / 256,  0xcd,       768 % 256,  768 / 256,
233    0xd2,       832 % 256,  832 / 256,  0xd3,       896 % 256,  896 / 256,
234    0xd4,       960 % 256,  960 / 256,  0xd5,       1024 % 256, 1024 / 256,
235    0xd6,       1088 % 256, 1088 / 256, 0xd7,       1152 % 256, 1152 / 256,
236    0xd8,       1216 % 256, 1216 / 256, 0xd9,       1280 % 256, 1280 / 256,
237    0xda,       1344 % 256, 1344 / 256, 0xdb,       1408 % 256, 1408 / 256,
238    0,          3,          0x08,       1792 % 256, 1792 / 256, 0x0c,
239    1856 % 256, 1856 / 256, 0x0d,       1920 % 256, 1920 / 256, 10,
240    0x12,       1984 % 256, 1984 / 256, 0x13,       2048 % 256, 2048 / 256,
241    0x14,       2112 % 256, 2112 / 256, 0x15,       2176 % 256, 2176 / 256,
242    0x16,       2240 % 256, 2240 / 256, 0x17,       2304 % 256, 2304 / 256,
243    0x1c,       2368 % 256, 2368 / 256, 0x1d,       2432 % 256, 2432 / 256,
244    0x1e,       2496 % 256, 2496 / 256, 0x1f,       2560 % 256, 2560 / 256,
245    0xff,
246};
247
248int FaxGetRun(const uint8_t* ins_array,
249              const uint8_t* src_buf,
250              int* bitpos,
251              int bitsize) {
252  uint32_t code = 0;
253  int ins_off = 0;
254  while (1) {
255    uint8_t ins = ins_array[ins_off++];
256    if (ins == 0xff)
257      return -1;
258
259    if (*bitpos >= bitsize)
260      return -1;
261
262    code <<= 1;
263    if (src_buf[*bitpos / 8] & (1 << (7 - *bitpos % 8)))
264      ++code;
265
266    ++(*bitpos);
267    int next_off = ins_off + ins * 3;
268    for (; ins_off < next_off; ins_off += 3) {
269      if (ins_array[ins_off] == code) {
270        return ins_array[ins_off + 1] + ins_array[ins_off + 2] * 256;
271      }
272    }
273  }
274}
275
276bool FaxG4GetRow(const uint8_t* src_buf,
277                 int bitsize,
278                 int* bitpos,
279                 uint8_t* dest_buf,
280                 const std::vector<uint8_t>& ref_buf,
281                 int columns) {
282  int a0 = -1;
283  bool a0color = true;
284  while (1) {
285    if (*bitpos >= bitsize)
286      return false;
287
288    int a1;
289    int a2;
290    int b1;
291    int b2;
292    FaxG4FindB1B2(ref_buf, columns, a0, a0color, &b1, &b2);
293
294    int v_delta = 0;
295    if (!NextBit(src_buf, bitpos)) {
296      if (*bitpos >= bitsize)
297        return false;
298
299      bool bit1 = NextBit(src_buf, bitpos);
300      if (*bitpos >= bitsize)
301        return false;
302
303      bool bit2 = NextBit(src_buf, bitpos);
304      if (bit1) {
305        v_delta = bit2 ? 1 : -1;
306      } else if (bit2) {
307        int run_len1 = 0;
308        while (1) {
309          int run = FaxGetRun(a0color ? FaxWhiteRunIns : FaxBlackRunIns,
310                              src_buf, bitpos, bitsize);
311          run_len1 += run;
312          if (run < 64) {
313            break;
314          }
315        }
316        if (a0 < 0)
317          ++run_len1;
318
319        a1 = a0 + run_len1;
320        if (!a0color)
321          FaxFillBits(dest_buf, columns, a0, a1);
322
323        int run_len2 = 0;
324        while (1) {
325          int run = FaxGetRun(a0color ? FaxBlackRunIns : FaxWhiteRunIns,
326                              src_buf, bitpos, bitsize);
327          run_len2 += run;
328          if (run < 64) {
329            break;
330          }
331        }
332        a2 = a1 + run_len2;
333        if (a0color)
334          FaxFillBits(dest_buf, columns, a1, a2);
335
336        a0 = a2;
337        if (a0 < columns)
338          continue;
339
340        return true;
341      } else {
342        if (*bitpos >= bitsize)
343          return false;
344
345        if (NextBit(src_buf, bitpos)) {
346          if (!a0color)
347            FaxFillBits(dest_buf, columns, a0, b2);
348
349          if (b2 >= columns)
350            return true;
351
352          a0 = b2;
353          continue;
354        }
355
356        if (*bitpos >= bitsize)
357          return false;
358
359        bool next_bit1 = NextBit(src_buf, bitpos);
360        if (*bitpos >= bitsize)
361          return false;
362
363        bool next_bit2 = NextBit(src_buf, bitpos);
364        if (next_bit1) {
365          v_delta = next_bit2 ? 2 : -2;
366        } else if (next_bit2) {
367          if (*bitpos >= bitsize)
368            return false;
369
370          v_delta = NextBit(src_buf, bitpos) ? 3 : -3;
371        } else {
372          if (*bitpos >= bitsize)
373            return false;
374
375          if (NextBit(src_buf, bitpos)) {
376            *bitpos += 3;
377            continue;
378          }
379          *bitpos += 5;
380          return true;
381        }
382      }
383    }
384    a1 = b1 + v_delta;
385    if (!a0color)
386      FaxFillBits(dest_buf, columns, a0, a1);
387
388    if (a1 >= columns)
389      return true;
390
391    // The position of picture element must be monotonic increasing.
392    if (a0 >= a1)
393      return false;
394
395    a0 = a1;
396    a0color = !a0color;
397  }
398}
399
400bool FaxSkipEOL(const uint8_t* src_buf, int bitsize, int* bitpos) {
401  int startbit = *bitpos;
402  while (*bitpos < bitsize) {
403    if (!NextBit(src_buf, bitpos))
404      continue;
405    if (*bitpos - startbit <= 11)
406      *bitpos = startbit;
407    return true;
408  }
409  return false;
410}
411
412bool FaxGet1DLine(const uint8_t* src_buf,
413                  int bitsize,
414                  int* bitpos,
415                  std::vector<uint8_t>* dest_buf,
416                  int columns) {
417  bool color = true;
418  int startpos = 0;
419  while (1) {
420    if (*bitpos >= bitsize)
421      return false;
422
423    int run_len = 0;
424    while (1) {
425      int run = FaxGetRun(color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf,
426                          bitpos, bitsize);
427      if (run < 0) {
428        while (*bitpos < bitsize) {
429          if (NextBit(src_buf, bitpos))
430            return true;
431        }
432        return false;
433      }
434      run_len += run;
435      if (run < 64) {
436        break;
437      }
438    }
439    if (!color)
440      FaxFillBits(dest_buf->data(), columns, startpos, startpos + run_len);
441
442    startpos += run_len;
443    if (startpos >= columns)
444      break;
445
446    color = !color;
447  }
448  return true;
449}
450
451}  // namespace
452
453class CCodec_FaxDecoder : public CCodec_ScanlineDecoder {
454 public:
455  CCodec_FaxDecoder(const uint8_t* src_buf,
456                    uint32_t src_size,
457                    int width,
458                    int height,
459                    uint32_t pitch,
460                    int K,
461                    bool EndOfLine,
462                    bool EncodedByteAlign,
463                    bool BlackIs1);
464  ~CCodec_FaxDecoder() override;
465
466  // CCodec_ScanlineDecoder
467  bool v_Rewind() override;
468  uint8_t* v_GetNextLine() override;
469  uint32_t GetSrcOffset() override;
470
471 private:
472  const int m_Encoding;
473  int m_bitpos;
474  bool m_bByteAlign;
475  const bool m_bEndOfLine;
476  const bool m_bBlack;
477  const uint32_t m_SrcSize;
478  const uint8_t* const m_pSrcBuf;
479  std::vector<uint8_t> m_ScanlineBuf;
480  std::vector<uint8_t> m_RefBuf;
481};
482
483CCodec_FaxDecoder::CCodec_FaxDecoder(const uint8_t* src_buf,
484                                     uint32_t src_size,
485                                     int width,
486                                     int height,
487                                     uint32_t pitch,
488                                     int K,
489                                     bool EndOfLine,
490                                     bool EncodedByteAlign,
491                                     bool BlackIs1)
492    : CCodec_ScanlineDecoder(width, height, width, height, 1, 1, pitch),
493      m_Encoding(K),
494      m_bitpos(0),
495      m_bByteAlign(EncodedByteAlign),
496      m_bEndOfLine(EndOfLine),
497      m_bBlack(BlackIs1),
498      m_SrcSize(src_size),
499      m_pSrcBuf(src_buf),
500      m_ScanlineBuf(pitch),
501      m_RefBuf(pitch) {}
502
503CCodec_FaxDecoder::~CCodec_FaxDecoder() {}
504
505bool CCodec_FaxDecoder::v_Rewind() {
506  FXSYS_memset(m_RefBuf.data(), 0xff, m_RefBuf.size());
507  m_bitpos = 0;
508  return true;
509}
510
511uint8_t* CCodec_FaxDecoder::v_GetNextLine() {
512  int bitsize = m_SrcSize * 8;
513  FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
514  if (m_bitpos >= bitsize)
515    return nullptr;
516
517  FXSYS_memset(m_ScanlineBuf.data(), 0xff, m_ScanlineBuf.size());
518  if (m_Encoding < 0) {
519    FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
520                m_OrigWidth);
521    m_RefBuf = m_ScanlineBuf;
522  } else if (m_Encoding == 0) {
523    FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
524  } else {
525    if (NextBit(m_pSrcBuf, &m_bitpos)) {
526      FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
527    } else {
528      FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
529                  m_OrigWidth);
530    }
531    m_RefBuf = m_ScanlineBuf;
532  }
533  if (m_bEndOfLine)
534    FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
535
536  if (m_bByteAlign && m_bitpos < bitsize) {
537    int bitpos0 = m_bitpos;
538    int bitpos1 = (m_bitpos + 7) / 8 * 8;
539    while (m_bByteAlign && bitpos0 < bitpos1) {
540      int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8));
541      if (bit != 0) {
542        m_bByteAlign = false;
543      } else {
544        ++bitpos0;
545      }
546    }
547    if (m_bByteAlign)
548      m_bitpos = bitpos1;
549  }
550  if (m_bBlack) {
551    for (uint32_t i = 0; i < m_Pitch; ++i) {
552      m_ScanlineBuf[i] = ~m_ScanlineBuf[i];
553    }
554  }
555  return m_ScanlineBuf.data();
556}
557
558uint32_t CCodec_FaxDecoder::GetSrcOffset() {
559  return std::min(static_cast<uint32_t>((m_bitpos + 7) / 8), m_SrcSize);
560}
561
562void FaxG4Decode(const uint8_t* src_buf,
563                 uint32_t src_size,
564                 int* pbitpos,
565                 uint8_t* dest_buf,
566                 int width,
567                 int height,
568                 int pitch) {
569  if (pitch == 0)
570    pitch = (width + 7) / 8;
571
572  std::vector<uint8_t> ref_buf(pitch, 0xff);
573  int bitpos = *pbitpos;
574  for (int iRow = 0; iRow < height; iRow++) {
575    uint8_t* line_buf = dest_buf + iRow * pitch;
576    FXSYS_memset(line_buf, 0xff, pitch);
577    FaxG4GetRow(src_buf, src_size << 3, &bitpos, line_buf, ref_buf, width);
578    FXSYS_memcpy(ref_buf.data(), line_buf, pitch);
579  }
580  *pbitpos = bitpos;
581}
582
583std::unique_ptr<CCodec_ScanlineDecoder> CCodec_FaxModule::CreateDecoder(
584    const uint8_t* src_buf,
585    uint32_t src_size,
586    int width,
587    int height,
588    int K,
589    bool EndOfLine,
590    bool EncodedByteAlign,
591    bool BlackIs1,
592    int Columns,
593    int Rows) {
594  int actual_width = Columns ? Columns : width;
595  int actual_height = Rows ? Rows : height;
596
597  // Reject invalid values.
598  if (actual_width <= 0 || actual_height <= 0)
599    return nullptr;
600
601  // Reject unreasonable large input.
602  if (actual_width > kMaxImageDimension || actual_height > kMaxImageDimension)
603    return nullptr;
604
605  uint32_t pitch = (static_cast<uint32_t>(actual_width) + 31) / 32 * 4;
606  return pdfium::MakeUnique<CCodec_FaxDecoder>(
607      src_buf, src_size, actual_width, actual_height, pitch, K, EndOfLine,
608      EncodedByteAlign, BlackIs1);
609}
610
611#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
612namespace {
613const uint8_t BlackRunTerminator[128] = {
614    0x37, 10, 0x02, 3,  0x03, 2,  0x02, 2,  0x03, 3,  0x03, 4,  0x02, 4,
615    0x03, 5,  0x05, 6,  0x04, 6,  0x04, 7,  0x05, 7,  0x07, 7,  0x04, 8,
616    0x07, 8,  0x18, 9,  0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11,
617    0x6c, 11, 0x37, 11, 0x28, 11, 0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12,
618    0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12, 0x6a, 12, 0x6b, 12, 0xd2, 12,
619    0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12, 0x6c, 12, 0x6d, 12,
620    0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12, 0x64, 12,
621    0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12,
622    0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12,
623    0x67, 12,
624};
625
626const uint8_t BlackRunMarkup[80] = {
627    0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12,
628    0x6c, 13, 0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13,
629    0x73, 13, 0x74, 13, 0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13,
630    0x54, 13, 0x55, 13, 0x5a, 13, 0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11,
631    0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
632    0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
633};
634
635const uint8_t WhiteRunTerminator[128] = {
636    0x35, 8, 0x07, 6, 0x07, 4, 0x08, 4, 0x0B, 4, 0x0C, 4, 0x0E, 4, 0x0F, 4,
637    0x13, 5, 0x14, 5, 0x07, 5, 0x08, 5, 0x08, 6, 0x03, 6, 0x34, 6, 0x35, 6,
638    0x2a, 6, 0x2B, 6, 0x27, 7, 0x0c, 7, 0x08, 7, 0x17, 7, 0x03, 7, 0x04, 7,
639    0x28, 7, 0x2B, 7, 0x13, 7, 0x24, 7, 0x18, 7, 0x02, 8, 0x03, 8, 0x1a, 8,
640    0x1b, 8, 0x12, 8, 0x13, 8, 0x14, 8, 0x15, 8, 0x16, 8, 0x17, 8, 0x28, 8,
641    0x29, 8, 0x2a, 8, 0x2b, 8, 0x2c, 8, 0x2d, 8, 0x04, 8, 0x05, 8, 0x0a, 8,
642    0x0b, 8, 0x52, 8, 0x53, 8, 0x54, 8, 0x55, 8, 0x24, 8, 0x25, 8, 0x58, 8,
643    0x59, 8, 0x5a, 8, 0x5b, 8, 0x4a, 8, 0x4b, 8, 0x32, 8, 0x33, 8, 0x34, 8,
644};
645
646const uint8_t WhiteRunMarkup[80] = {
647    0x1b, 5,  0x12, 5,  0x17, 6,  0x37, 7,  0x36, 8,  0x37, 8,  0x64, 8,
648    0x65, 8,  0x68, 8,  0x67, 8,  0xcc, 9,  0xcd, 9,  0xd2, 9,  0xd3, 9,
649    0xd4, 9,  0xd5, 9,  0xd6, 9,  0xd7, 9,  0xd8, 9,  0xd9, 9,  0xda, 9,
650    0xdb, 9,  0x98, 9,  0x99, 9,  0x9a, 9,  0x18, 6,  0x9b, 9,  0x08, 11,
651    0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
652    0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
653};
654
655void AddBitStream(uint8_t* dest_buf, int* dest_bitpos, int data, int bitlen) {
656  for (int i = bitlen - 1; i >= 0; i--) {
657    if (data & (1 << i)) {
658      dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
659    }
660    (*dest_bitpos)++;
661  }
662}
663
664void FaxEncodeRun(uint8_t* dest_buf, int* dest_bitpos, int run, bool bWhite) {
665  while (run >= 2560) {
666    AddBitStream(dest_buf, dest_bitpos, 0x1f, 12);
667    run -= 2560;
668  }
669  if (run >= 64) {
670    int markup = run - run % 64;
671    const uint8_t* p = bWhite ? WhiteRunMarkup : BlackRunMarkup;
672    p += (markup / 64 - 1) * 2;
673    AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
674  }
675  run %= 64;
676  const uint8_t* p = bWhite ? WhiteRunTerminator : BlackRunTerminator;
677  p += run * 2;
678  AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
679}
680
681void FaxEncode2DLine(uint8_t* dest_buf,
682                     int* dest_bitpos,
683                     const uint8_t* src_buf,
684                     const std::vector<uint8_t>& ref_buf,
685                     int cols) {
686  int a0 = -1;
687  bool a0color = true;
688  while (1) {
689    int a1 = FindBit(src_buf, cols, a0 + 1, !a0color);
690    int b1;
691    int b2;
692    FaxG4FindB1B2(ref_buf, cols, a0, a0color, &b1, &b2);
693    if (b2 < a1) {
694      *dest_bitpos += 3;
695      dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
696      (*dest_bitpos)++;
697      a0 = b2;
698    } else if (a1 - b1 <= 3 && b1 - a1 <= 3) {
699      int delta = a1 - b1;
700      switch (delta) {
701        case 0:
702          dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
703          break;
704        case 1:
705        case 2:
706        case 3:
707          *dest_bitpos += delta == 1 ? 1 : delta + 2;
708          dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
709          (*dest_bitpos)++;
710          dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
711          break;
712        case -1:
713        case -2:
714        case -3:
715          *dest_bitpos += delta == -1 ? 1 : -delta + 2;
716          dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
717          (*dest_bitpos)++;
718          break;
719      }
720      (*dest_bitpos)++;
721      a0 = a1;
722      a0color = !a0color;
723    } else {
724      int a2 = FindBit(src_buf, cols, a1 + 1, a0color);
725      (*dest_bitpos)++;
726      (*dest_bitpos)++;
727      dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
728      (*dest_bitpos)++;
729      if (a0 < 0) {
730        a0 = 0;
731      }
732      FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color);
733      FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, !a0color);
734      a0 = a2;
735    }
736    if (a0 >= cols) {
737      return;
738    }
739  }
740}
741
742class CCodec_FaxEncoder {
743 public:
744  CCodec_FaxEncoder(const uint8_t* src_buf, int width, int height, int pitch);
745  ~CCodec_FaxEncoder();
746  void Encode(std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
747              uint32_t* dest_size);
748
749 private:
750  CFX_BinaryBuf m_DestBuf;
751  std::vector<uint8_t> m_RefLine;
752  uint8_t* m_pLineBuf;
753  const int m_Cols;
754  const int m_Rows;
755  const int m_Pitch;
756  const uint8_t* m_pSrcBuf;
757};
758
759CCodec_FaxEncoder::CCodec_FaxEncoder(const uint8_t* src_buf,
760                                     int width,
761                                     int height,
762                                     int pitch)
763    : m_Cols(width), m_Rows(height), m_Pitch(pitch), m_pSrcBuf(src_buf) {
764  m_RefLine.resize(m_Pitch);
765  FXSYS_memset(m_RefLine.data(), 0xff, m_Pitch);
766  m_pLineBuf = FX_Alloc2D(uint8_t, m_Pitch, 8);
767  m_DestBuf.EstimateSize(0, 10240);
768}
769
770CCodec_FaxEncoder::~CCodec_FaxEncoder() {
771  FX_Free(m_pLineBuf);
772}
773
774void CCodec_FaxEncoder::Encode(
775    std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
776    uint32_t* dest_size) {
777  int dest_bitpos = 0;
778  uint8_t last_byte = 0;
779  for (int i = 0; i < m_Rows; i++) {
780    const uint8_t* scan_line = m_pSrcBuf + i * m_Pitch;
781    FXSYS_memset(m_pLineBuf, 0, m_Pitch * 8);
782    m_pLineBuf[0] = last_byte;
783    FaxEncode2DLine(m_pLineBuf, &dest_bitpos, scan_line, m_RefLine, m_Cols);
784    m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8);
785    last_byte = m_pLineBuf[dest_bitpos / 8];
786    dest_bitpos %= 8;
787    FXSYS_memcpy(m_RefLine.data(), scan_line, m_Pitch);
788  }
789  if (dest_bitpos) {
790    m_DestBuf.AppendByte(last_byte);
791  }
792  *dest_size = m_DestBuf.GetSize();
793  *dest_buf = m_DestBuf.DetachBuffer();
794}
795
796}  // namespace
797
798void CCodec_FaxModule::FaxEncode(
799    const uint8_t* src_buf,
800    int width,
801    int height,
802    int pitch,
803    std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
804    uint32_t* dest_size) {
805  CCodec_FaxEncoder encoder(src_buf, width, height, pitch);
806  encoder.Encode(dest_buf, dest_size);
807}
808
809#endif
810