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