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