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 "codec_int.h"
8 #include "core/include/fxcodec/fx_codec.h"
9
10 namespace {
11
12 const uint8_t OneLeadPos[256] = {
13 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
14 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
15 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
16 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
18 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
20 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24 };
25 const uint8_t ZeroLeadPos[256] = {
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, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
34 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
35 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
36 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
37 };
38
FindBit(const uint8_t * data_buf,int max_pos,int start_pos,int bit)39 int FindBit(const uint8_t* data_buf, int max_pos, int start_pos, int bit) {
40 if (start_pos >= max_pos) {
41 return max_pos;
42 }
43 const uint8_t* leading_pos = bit ? OneLeadPos : ZeroLeadPos;
44 if (start_pos % 8) {
45 uint8_t data = data_buf[start_pos / 8];
46 if (bit) {
47 data &= 0xff >> (start_pos % 8);
48 } else {
49 data |= 0xff << (8 - start_pos % 8);
50 }
51 if (leading_pos[data] < 8) {
52 return start_pos / 8 * 8 + leading_pos[data];
53 }
54 start_pos += 7;
55 }
56 uint8_t skip = bit ? 0x00 : 0xff;
57 int byte_pos = start_pos / 8;
58 int max_byte = (max_pos + 7) / 8;
59 while (byte_pos < max_byte) {
60 if (data_buf[byte_pos] != skip) {
61 break;
62 }
63 byte_pos++;
64 }
65 if (byte_pos == max_byte) {
66 return max_pos;
67 }
68 int pos = leading_pos[data_buf[byte_pos]] + byte_pos * 8;
69 if (pos > max_pos) {
70 pos = max_pos;
71 }
72 return pos;
73 }
74
FaxG4FindB1B2(const uint8_t * ref_buf,int columns,int a0,bool a0color,int & b1,int & b2)75 void FaxG4FindB1B2(const uint8_t* ref_buf,
76 int columns,
77 int a0,
78 bool a0color,
79 int& b1,
80 int& b2) {
81 uint8_t first_bit =
82 (a0 < 0) ? 1 : ((ref_buf[a0 / 8] & (1 << (7 - a0 % 8))) != 0);
83 b1 = FindBit(ref_buf, columns, a0 + 1, !first_bit);
84 if (b1 >= columns) {
85 b1 = b2 = columns;
86 return;
87 }
88 if (first_bit == !a0color) {
89 b1 = FindBit(ref_buf, columns, b1 + 1, first_bit);
90 first_bit = !first_bit;
91 }
92 if (b1 >= columns) {
93 b1 = b2 = columns;
94 return;
95 }
96 b2 = FindBit(ref_buf, columns, b1 + 1, first_bit);
97 }
98
FaxFillBits(uint8_t * dest_buf,int columns,int startpos,int endpos)99 void FaxFillBits(uint8_t* dest_buf, int columns, int startpos, int endpos) {
100 if (startpos < 0) {
101 startpos = 0;
102 }
103 if (endpos < 0) {
104 endpos = 0;
105 }
106 if (endpos >= columns) {
107 endpos = columns;
108 }
109 if (startpos >= endpos) {
110 return;
111 }
112 int first_byte = startpos / 8;
113 int last_byte = (endpos - 1) / 8;
114 if (first_byte == last_byte) {
115 for (int i = startpos % 8; i <= (endpos - 1) % 8; i++) {
116 dest_buf[first_byte] -= 1 << (7 - i);
117 }
118 return;
119 }
120 int i;
121 for (i = startpos % 8; i < 8; i++) {
122 dest_buf[first_byte] -= 1 << (7 - i);
123 }
124 for (i = 0; i <= (endpos - 1) % 8; i++) {
125 dest_buf[last_byte] -= 1 << (7 - i);
126 }
127 if (last_byte > first_byte + 1) {
128 FXSYS_memset(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1);
129 }
130 }
131
132 #define NEXTBIT \
133 src_buf[bitpos / 8] & (1 << (7 - bitpos % 8)); \
134 bitpos++;
135 #define ADDBIT(code, bit) \
136 code = code << 1; \
137 if (bit) \
138 code++;
139 #define GETBIT(bitpos) src_buf[bitpos / 8] & (1 << (7 - bitpos % 8))
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 FX_DWORD 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 }
283
FaxG4GetRow(const uint8_t * src_buf,int bitsize,int & bitpos,uint8_t * dest_buf,const uint8_t * ref_buf,int columns)284 FX_BOOL FaxG4GetRow(const uint8_t* src_buf,
285 int bitsize,
286 int& bitpos,
287 uint8_t* dest_buf,
288 const uint8_t* ref_buf,
289 int columns) {
290 int a0 = -1;
291 bool a0color = true;
292 while (1) {
293 if (bitpos >= bitsize) {
294 return FALSE;
295 }
296 int a1, a2, b1, b2;
297 FaxG4FindB1B2(ref_buf, columns, a0, a0color, b1, b2);
298 FX_BOOL bit = NEXTBIT;
299 int v_delta = 0;
300 if (bit) {
301 } else {
302 if (bitpos >= bitsize) {
303 return FALSE;
304 }
305 FX_BOOL bit1 = NEXTBIT;
306 if (bitpos >= bitsize) {
307 return FALSE;
308 }
309 FX_BOOL bit2 = NEXTBIT;
310 if (bit1 && bit2) {
311 v_delta = 1;
312 } else if (bit1) {
313 v_delta = -1;
314 } else if (bit2) {
315 int run_len1 = 0;
316 while (1) {
317 int run = FaxGetRun(a0color ? FaxWhiteRunIns : FaxBlackRunIns,
318 src_buf, bitpos, bitsize);
319 run_len1 += run;
320 if (run < 64) {
321 break;
322 }
323 }
324 if (a0 < 0) {
325 run_len1++;
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 }
340 a2 = a1 + run_len2;
341 if (a0color) {
342 FaxFillBits(dest_buf, columns, a1, a2);
343 }
344 a0 = a2;
345 if (a0 < columns) {
346 continue;
347 }
348 return TRUE;
349 } else {
350 if (bitpos >= bitsize) {
351 return FALSE;
352 }
353 bit = NEXTBIT;
354 if (bit) {
355 if (!a0color) {
356 FaxFillBits(dest_buf, columns, a0, b2);
357 }
358 if (b2 >= columns) {
359 return TRUE;
360 }
361 a0 = b2;
362 continue;
363 } else {
364 if (bitpos >= bitsize) {
365 return FALSE;
366 }
367 FX_BOOL bit1 = NEXTBIT;
368 if (bitpos >= bitsize) {
369 return FALSE;
370 }
371 FX_BOOL bit2 = NEXTBIT;
372 if (bit1 && bit2) {
373 v_delta = 2;
374 } else if (bit1) {
375 v_delta = -2;
376 } else if (bit2) {
377 if (bitpos >= bitsize) {
378 return FALSE;
379 }
380 bit = NEXTBIT;
381 if (bit) {
382 v_delta = 3;
383 } else {
384 v_delta = -3;
385 }
386 } else {
387 if (bitpos >= bitsize) {
388 return FALSE;
389 }
390 bit = NEXTBIT;
391 if (bit) {
392 bitpos += 3;
393 continue;
394 } else {
395 bitpos += 5;
396 return TRUE;
397 }
398 }
399 }
400 }
401 }
402 a1 = b1 + v_delta;
403 if (!a0color) {
404 FaxFillBits(dest_buf, columns, a0, a1);
405 }
406 if (a1 >= columns) {
407 return TRUE;
408 }
409 a0 = a1;
410 a0color = !a0color;
411 }
412 }
413
FaxSkipEOL(const uint8_t * src_buf,int bitsize,int & bitpos)414 FX_BOOL FaxSkipEOL(const uint8_t* src_buf, int bitsize, int& bitpos) {
415 int startbit = bitpos;
416 while (bitpos < bitsize) {
417 int bit = NEXTBIT;
418 if (bit) {
419 if (bitpos - startbit <= 11) {
420 bitpos = startbit;
421 }
422 return TRUE;
423 }
424 }
425 return FALSE;
426 }
427
FaxGet1DLine(const uint8_t * src_buf,int bitsize,int & bitpos,uint8_t * dest_buf,int columns)428 FX_BOOL FaxGet1DLine(const uint8_t* src_buf,
429 int bitsize,
430 int& bitpos,
431 uint8_t* dest_buf,
432 int columns) {
433 bool color = true;
434 int startpos = 0;
435 while (1) {
436 if (bitpos >= bitsize) {
437 return FALSE;
438 }
439 int run_len = 0;
440 while (1) {
441 int run = FaxGetRun(color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf,
442 bitpos, bitsize);
443 if (run < 0) {
444 while (bitpos < bitsize) {
445 int bit = NEXTBIT;
446 if (bit) {
447 return TRUE;
448 }
449 }
450 return FALSE;
451 }
452 run_len += run;
453 if (run < 64) {
454 break;
455 }
456 }
457 if (!color) {
458 FaxFillBits(dest_buf, columns, startpos, startpos + run_len);
459 }
460 startpos += run_len;
461 if (startpos >= columns) {
462 break;
463 }
464 color = !color;
465 }
466 return TRUE;
467 }
468
469 const uint8_t BlackRunTerminator[128] = {
470 0x37, 10, 0x02, 3, 0x03, 2, 0x02, 2, 0x03, 3, 0x03, 4, 0x02, 4,
471 0x03, 5, 0x05, 6, 0x04, 6, 0x04, 7, 0x05, 7, 0x07, 7, 0x04, 8,
472 0x07, 8, 0x18, 9, 0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11,
473 0x6c, 11, 0x37, 11, 0x28, 11, 0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12,
474 0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12, 0x6a, 12, 0x6b, 12, 0xd2, 12,
475 0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12, 0x6c, 12, 0x6d, 12,
476 0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12, 0x64, 12,
477 0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12,
478 0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12,
479 0x67, 12,
480 };
481
482 const uint8_t BlackRunMarkup[80] = {
483 0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12,
484 0x6c, 13, 0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13,
485 0x73, 13, 0x74, 13, 0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13,
486 0x54, 13, 0x55, 13, 0x5a, 13, 0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11,
487 0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
488 0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
489 };
490
491 const uint8_t WhiteRunTerminator[128] = {
492 0x35, 8, 0x07, 6, 0x07, 4, 0x08, 4, 0x0B, 4, 0x0C, 4, 0x0E, 4, 0x0F, 4,
493 0x13, 5, 0x14, 5, 0x07, 5, 0x08, 5, 0x08, 6, 0x03, 6, 0x34, 6, 0x35, 6,
494 0x2a, 6, 0x2B, 6, 0x27, 7, 0x0c, 7, 0x08, 7, 0x17, 7, 0x03, 7, 0x04, 7,
495 0x28, 7, 0x2B, 7, 0x13, 7, 0x24, 7, 0x18, 7, 0x02, 8, 0x03, 8, 0x1a, 8,
496 0x1b, 8, 0x12, 8, 0x13, 8, 0x14, 8, 0x15, 8, 0x16, 8, 0x17, 8, 0x28, 8,
497 0x29, 8, 0x2a, 8, 0x2b, 8, 0x2c, 8, 0x2d, 8, 0x04, 8, 0x05, 8, 0x0a, 8,
498 0x0b, 8, 0x52, 8, 0x53, 8, 0x54, 8, 0x55, 8, 0x24, 8, 0x25, 8, 0x58, 8,
499 0x59, 8, 0x5a, 8, 0x5b, 8, 0x4a, 8, 0x4b, 8, 0x32, 8, 0x33, 8, 0x34, 8,
500 };
501
502 const uint8_t WhiteRunMarkup[80] = {
503 0x1b, 5, 0x12, 5, 0x17, 6, 0x37, 7, 0x36, 8, 0x37, 8, 0x64, 8,
504 0x65, 8, 0x68, 8, 0x67, 8, 0xcc, 9, 0xcd, 9, 0xd2, 9, 0xd3, 9,
505 0xd4, 9, 0xd5, 9, 0xd6, 9, 0xd7, 9, 0xd8, 9, 0xd9, 9, 0xda, 9,
506 0xdb, 9, 0x98, 9, 0x99, 9, 0x9a, 9, 0x18, 6, 0x9b, 9, 0x08, 11,
507 0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
508 0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
509 };
510
AddBitStream(uint8_t * dest_buf,int & dest_bitpos,int data,int bitlen)511 void AddBitStream(uint8_t* dest_buf, int& dest_bitpos, int data, int bitlen) {
512 for (int i = bitlen - 1; i >= 0; i--) {
513 if (data & (1 << i)) {
514 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
515 }
516 dest_bitpos++;
517 }
518 }
519
FaxEncodeRun(uint8_t * dest_buf,int & dest_bitpos,int run,bool bWhite)520 void FaxEncodeRun(uint8_t* dest_buf, int& dest_bitpos, int run, bool bWhite) {
521 while (run >= 2560) {
522 AddBitStream(dest_buf, dest_bitpos, 0x1f, 12);
523 run -= 2560;
524 }
525 if (run >= 64) {
526 int markup = run - run % 64;
527 const uint8_t* p = bWhite ? WhiteRunMarkup : BlackRunMarkup;
528 p += (markup / 64 - 1) * 2;
529 AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
530 }
531 run %= 64;
532 const uint8_t* p = bWhite ? WhiteRunTerminator : BlackRunTerminator;
533 p += run * 2;
534 AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
535 }
536
FaxEncode2DLine(uint8_t * dest_buf,int & dest_bitpos,const uint8_t * src_buf,const uint8_t * ref_buf,int cols)537 void FaxEncode2DLine(uint8_t* dest_buf,
538 int& dest_bitpos,
539 const uint8_t* src_buf,
540 const uint8_t* ref_buf,
541 int cols) {
542 int a0 = -1;
543 bool a0color = true;
544 while (1) {
545 int a1 = FindBit(src_buf, cols, a0 + 1, !a0color);
546 int b1, b2;
547 FaxG4FindB1B2(ref_buf, cols, a0, a0color, b1, b2);
548 if (b2 < a1) {
549 dest_bitpos += 3;
550 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
551 dest_bitpos++;
552 a0 = b2;
553 } else if (a1 - b1 <= 3 && b1 - a1 <= 3) {
554 int delta = a1 - b1;
555 switch (delta) {
556 case 0:
557 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
558 break;
559 case 1:
560 case 2:
561 case 3:
562 dest_bitpos += delta == 1 ? 1 : delta + 2;
563 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
564 dest_bitpos++;
565 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
566 break;
567 case -1:
568 case -2:
569 case -3:
570 dest_bitpos += delta == -1 ? 1 : -delta + 2;
571 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
572 dest_bitpos++;
573 break;
574 }
575 dest_bitpos++;
576 a0 = a1;
577 a0color = !a0color;
578 } else {
579 int a2 = FindBit(src_buf, cols, a1 + 1, a0color);
580 dest_bitpos++;
581 dest_bitpos++;
582 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
583 dest_bitpos++;
584 if (a0 < 0) {
585 a0 = 0;
586 }
587 FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color);
588 FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, !a0color);
589 a0 = a2;
590 }
591 if (a0 >= cols) {
592 return;
593 }
594 }
595 }
596
597 } // namespace
598
599 class CCodec_FaxDecoder : public CCodec_ScanlineDecoder {
600 public:
601 CCodec_FaxDecoder();
602 ~CCodec_FaxDecoder() override;
603
604 FX_BOOL Create(const uint8_t* src_buf,
605 FX_DWORD src_size,
606 int width,
607 int height,
608 int K,
609 FX_BOOL EndOfLine,
610 FX_BOOL EncodedByteAlign,
611 FX_BOOL BlackIs1,
612 int Columns,
613 int Rows);
614
615 // CCodec_ScanlineDecoder
v_DownScale(int dest_width,int dest_height)616 void v_DownScale(int dest_width, int dest_height) override {}
617 FX_BOOL v_Rewind() override;
618 uint8_t* v_GetNextLine() override;
619 FX_DWORD GetSrcOffset() override;
620
621 int m_Encoding, m_bEndOfLine, m_bByteAlign, m_bBlack;
622 int bitpos;
623 const uint8_t* m_pSrcBuf;
624 FX_DWORD m_SrcSize;
625 uint8_t* m_pScanlineBuf;
626 uint8_t* m_pRefBuf;
627 };
628
CCodec_FaxDecoder()629 CCodec_FaxDecoder::CCodec_FaxDecoder() {
630 m_pScanlineBuf = NULL;
631 m_pRefBuf = NULL;
632 }
~CCodec_FaxDecoder()633 CCodec_FaxDecoder::~CCodec_FaxDecoder() {
634 FX_Free(m_pScanlineBuf);
635 FX_Free(m_pRefBuf);
636 }
Create(const uint8_t * src_buf,FX_DWORD src_size,int width,int height,int K,FX_BOOL EndOfLine,FX_BOOL EncodedByteAlign,FX_BOOL BlackIs1,int Columns,int Rows)637 FX_BOOL CCodec_FaxDecoder::Create(const uint8_t* src_buf,
638 FX_DWORD src_size,
639 int width,
640 int height,
641 int K,
642 FX_BOOL EndOfLine,
643 FX_BOOL EncodedByteAlign,
644 FX_BOOL BlackIs1,
645 int Columns,
646 int Rows) {
647 m_Encoding = K;
648 m_bEndOfLine = EndOfLine;
649 m_bByteAlign = EncodedByteAlign;
650 m_bBlack = BlackIs1;
651 m_OrigWidth = Columns;
652 m_OrigHeight = Rows;
653 if (m_OrigWidth == 0) {
654 m_OrigWidth = width;
655 }
656 if (m_OrigHeight == 0) {
657 m_OrigHeight = height;
658 }
659 // Should not overflow. Checked by FPDFAPI_CreateFaxDecoder.
660 m_Pitch = (static_cast<FX_DWORD>(m_OrigWidth) + 31) / 32 * 4;
661 m_OutputWidth = m_OrigWidth;
662 m_OutputHeight = m_OrigHeight;
663 m_pScanlineBuf = FX_Alloc(uint8_t, m_Pitch);
664 m_pRefBuf = FX_Alloc(uint8_t, m_Pitch);
665 m_pSrcBuf = src_buf;
666 m_SrcSize = src_size;
667 m_nComps = 1;
668 m_bpc = 1;
669 m_bColorTransformed = FALSE;
670 return TRUE;
671 }
v_Rewind()672 FX_BOOL CCodec_FaxDecoder::v_Rewind() {
673 FXSYS_memset(m_pRefBuf, 0xff, m_Pitch);
674 bitpos = 0;
675 return TRUE;
676 }
v_GetNextLine()677 uint8_t* CCodec_FaxDecoder::v_GetNextLine() {
678 int bitsize = m_SrcSize * 8;
679 FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
680 if (bitpos >= bitsize) {
681 return NULL;
682 }
683 FXSYS_memset(m_pScanlineBuf, 0xff, m_Pitch);
684 if (m_Encoding < 0) {
685 FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf,
686 m_OrigWidth);
687 FXSYS_memcpy(m_pRefBuf, m_pScanlineBuf, m_Pitch);
688 } else if (m_Encoding == 0) {
689 FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
690 } else {
691 FX_BOOL bNext1D = m_pSrcBuf[bitpos / 8] & (1 << (7 - bitpos % 8));
692 bitpos++;
693 if (bNext1D) {
694 FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
695 } else {
696 FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf,
697 m_OrigWidth);
698 }
699 FXSYS_memcpy(m_pRefBuf, m_pScanlineBuf, m_Pitch);
700 }
701 if (m_bEndOfLine) {
702 FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
703 }
704 if (m_bByteAlign && bitpos < bitsize) {
705 int bitpos0 = bitpos;
706 int bitpos1 = (bitpos + 7) / 8 * 8;
707 while (m_bByteAlign && bitpos0 < bitpos1) {
708 int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8));
709 if (bit != 0) {
710 m_bByteAlign = FALSE;
711 } else {
712 bitpos0++;
713 }
714 }
715 if (m_bByteAlign) {
716 bitpos = bitpos1;
717 }
718 }
719 if (m_bBlack) {
720 for (FX_DWORD i = 0; i < m_Pitch; i++) {
721 m_pScanlineBuf[i] = ~m_pScanlineBuf[i];
722 }
723 }
724 return m_pScanlineBuf;
725 }
GetSrcOffset()726 FX_DWORD CCodec_FaxDecoder::GetSrcOffset() {
727 FX_DWORD ret = (bitpos + 7) / 8;
728 if (ret > m_SrcSize) {
729 ret = m_SrcSize;
730 }
731 return ret;
732 }
733
FaxG4Decode(const uint8_t * src_buf,FX_DWORD src_size,int * pbitpos,uint8_t * dest_buf,int width,int height,int pitch)734 void FaxG4Decode(const uint8_t* src_buf,
735 FX_DWORD src_size,
736 int* pbitpos,
737 uint8_t* dest_buf,
738 int width,
739 int height,
740 int pitch) {
741 if (pitch == 0) {
742 pitch = (width + 7) / 8;
743 }
744 uint8_t* ref_buf = FX_Alloc(uint8_t, pitch);
745 FXSYS_memset(ref_buf, 0xff, pitch);
746 int bitpos = *pbitpos;
747 for (int iRow = 0; iRow < height; iRow++) {
748 uint8_t* line_buf = dest_buf + iRow * pitch;
749 FXSYS_memset(line_buf, 0xff, pitch);
750 FaxG4GetRow(src_buf, src_size << 3, bitpos, line_buf, ref_buf, width);
751 FXSYS_memcpy(ref_buf, line_buf, pitch);
752 }
753 FX_Free(ref_buf);
754 *pbitpos = bitpos;
755 }
756
757 class CCodec_FaxEncoder {
758 public:
759 CCodec_FaxEncoder(const uint8_t* src_buf, int width, int height, int pitch);
760 ~CCodec_FaxEncoder();
761 void Encode(uint8_t*& dest_buf, FX_DWORD& dest_size);
762 void Encode2DLine(const uint8_t* scan_line);
763 CFX_BinaryBuf m_DestBuf;
764 uint8_t* m_pRefLine;
765 uint8_t* m_pLineBuf;
766 int m_Cols, m_Rows, m_Pitch;
767 const uint8_t* m_pSrcBuf;
768 };
CCodec_FaxEncoder(const uint8_t * src_buf,int width,int height,int pitch)769 CCodec_FaxEncoder::CCodec_FaxEncoder(const uint8_t* src_buf,
770 int width,
771 int height,
772 int pitch) {
773 m_pSrcBuf = src_buf;
774 m_Cols = width;
775 m_Rows = height;
776 m_Pitch = pitch;
777 m_pRefLine = FX_Alloc(uint8_t, m_Pitch);
778 FXSYS_memset(m_pRefLine, 0xff, m_Pitch);
779 m_pLineBuf = FX_Alloc2D(uint8_t, m_Pitch, 8);
780 m_DestBuf.EstimateSize(0, 10240);
781 }
~CCodec_FaxEncoder()782 CCodec_FaxEncoder::~CCodec_FaxEncoder() {
783 FX_Free(m_pRefLine);
784 FX_Free(m_pLineBuf);
785 }
Encode(uint8_t * & dest_buf,FX_DWORD & dest_size)786 void CCodec_FaxEncoder::Encode(uint8_t*& dest_buf, FX_DWORD& dest_size) {
787 int dest_bitpos = 0;
788 uint8_t last_byte = 0;
789 for (int i = 0; i < m_Rows; i++) {
790 const uint8_t* scan_line = m_pSrcBuf + i * m_Pitch;
791 FXSYS_memset(m_pLineBuf, 0, m_Pitch * 8);
792 m_pLineBuf[0] = last_byte;
793 FaxEncode2DLine(m_pLineBuf, dest_bitpos, scan_line, m_pRefLine, m_Cols);
794 m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8);
795 last_byte = m_pLineBuf[dest_bitpos / 8];
796 dest_bitpos %= 8;
797 FXSYS_memcpy(m_pRefLine, scan_line, m_Pitch);
798 }
799 if (dest_bitpos) {
800 m_DestBuf.AppendByte(last_byte);
801 }
802 dest_buf = m_DestBuf.GetBuffer();
803 dest_size = m_DestBuf.GetSize();
804 m_DestBuf.DetachBuffer();
805 }
Encode(const uint8_t * src_buf,int width,int height,int pitch,uint8_t * & dest_buf,FX_DWORD & dest_size)806 FX_BOOL CCodec_FaxModule::Encode(const uint8_t* src_buf,
807 int width,
808 int height,
809 int pitch,
810 uint8_t*& dest_buf,
811 FX_DWORD& dest_size) {
812 CCodec_FaxEncoder encoder(src_buf, width, height, pitch);
813 encoder.Encode(dest_buf, dest_size);
814 return TRUE;
815 }
CreateDecoder(const uint8_t * src_buf,FX_DWORD src_size,int width,int height,int K,FX_BOOL EndOfLine,FX_BOOL EncodedByteAlign,FX_BOOL BlackIs1,int Columns,int Rows)816 ICodec_ScanlineDecoder* CCodec_FaxModule::CreateDecoder(
817 const uint8_t* src_buf,
818 FX_DWORD src_size,
819 int width,
820 int height,
821 int K,
822 FX_BOOL EndOfLine,
823 FX_BOOL EncodedByteAlign,
824 FX_BOOL BlackIs1,
825 int Columns,
826 int Rows) {
827 CCodec_FaxDecoder* pDecoder = new CCodec_FaxDecoder;
828 pDecoder->Create(src_buf, src_size, width, height, K, EndOfLine,
829 EncodedByteAlign, BlackIs1, Columns, Rows);
830 return pDecoder;
831 }
832