1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// found in the LICENSE file.
4e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
7e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../../include/fxcodec/fx_codec.h"
8e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "codec_int.h"
9e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovconst FX_BYTE OneLeadPos[256] = {
10e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
11e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
12e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
13e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
15e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
16e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
25e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
27e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovconst FX_BYTE ZeroLeadPos[256] = {
28e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
37e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
38e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
39e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
40e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
41e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
42e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
43e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
44e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
45e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
46e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovint _FindBit(const FX_BYTE* data_buf, int max_pos, int start_pos, int bit)
47e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
48e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (start_pos >= max_pos) {
49e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return max_pos;
50e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
51e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_LPCBYTE leading_pos = bit ? OneLeadPos : ZeroLeadPos;
52e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (start_pos % 8) {
53e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_BYTE data = data_buf[start_pos / 8];
54e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (bit) {
55e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            data &= 0xff >> (start_pos % 8);
56e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
57e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            data |= 0xff << (8 - start_pos % 8);
58e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
59e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (leading_pos[data] < 8) {
60e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return start_pos / 8 * 8 + leading_pos[data];
61e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
62e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        start_pos += 7;
63e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
64e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_BYTE skip = bit ? 0x00 : 0xff;
65e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int byte_pos = start_pos / 8;
66e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int max_byte = (max_pos + 7) / 8;
67e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    while (byte_pos < max_byte) {
68e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (data_buf[byte_pos] != skip) {
69e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            break;
70e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
71e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        byte_pos ++;
72e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
73e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (byte_pos == max_byte) {
74e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return max_pos;
75e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
76e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int pos = leading_pos[data_buf[byte_pos]] + byte_pos * 8;
77e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pos > max_pos) {
78e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pos = max_pos;
79e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
80e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pos;
81e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
82e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid _FaxG4FindB1B2(const FX_BYTE* ref_buf, int columns, int a0, FX_BOOL a0color, int& b1, int& b2)
83e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
84e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (a0color) {
85e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        a0color = 1;
86e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
87e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_BYTE first_bit = (a0 < 0) ? 1 : ((ref_buf[a0 / 8] & (1 << (7 - a0 % 8))) != 0);
88e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    b1 = _FindBit(ref_buf, columns, a0 + 1, !first_bit);
89e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (b1 >= columns) {
90e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        b1 = b2 = columns;
91e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
92e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
93e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (first_bit == !a0color) {
94e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        b1 = _FindBit(ref_buf, columns, b1 + 1, first_bit);
95e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        first_bit = !first_bit;
96e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
97e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (b1 >= columns) {
98e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        b1 = b2 = columns;
99e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
100e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
101e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    b2 = _FindBit(ref_buf, columns, b1 + 1, first_bit);
102e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
103e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid _FaxFillBits(FX_LPBYTE dest_buf, int columns, int startpos, int endpos)
104e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
105e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (startpos < 0) {
106e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        startpos = 0;
107e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
108e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (endpos < 0) {
109e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        endpos = 0;
110e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
111e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (endpos >= columns) {
112e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        endpos = columns;
113e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
114e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (startpos >= endpos) {
115e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
116e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
117e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int first_byte = startpos / 8;
118e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int last_byte = (endpos - 1) / 8;
119e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (first_byte == last_byte) {
120e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (int i = startpos % 8; i <= (endpos - 1) % 8; i ++) {
121e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_buf[first_byte] -= 1 << (7 - i);
122e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
123e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
124e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
125e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int i;
126e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    for (i = startpos % 8; i < 8; i ++) {
127e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        dest_buf[first_byte] -= 1 << (7 - i);
128e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
129e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    for (i = 0; i <= (endpos - 1) % 8; i ++) {
130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        dest_buf[last_byte] -= 1 << (7 - i);
131e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
132e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (last_byte > first_byte + 1) {
133e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FXSYS_memset32(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1);
134e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
135e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
136e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define NEXTBIT src_buf[bitpos/8] & (1 << (7-bitpos%8)); bitpos ++;
137e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define ADDBIT(code, bit) code = code << 1; if (bit) code ++;
138e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define GETBIT(bitpos) src_buf[bitpos/8] & (1 << (7-bitpos%8))
139e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE FaxBlackRunIns[] = {
140e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0,
141e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    2,
142e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x02, 3, 0,
143e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 2, 0,
144e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    2,
145e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x02, 1, 0,
146e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 4, 0,
147e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    2,
148e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x02, 6, 0,
149e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 5, 0,
150e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1,
151e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 7, 0,
152e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    2,
153e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x04, 9, 0,
154e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x05, 8, 0,
155e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    3,
156e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x04, 10, 0,
157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x05, 11, 0,
158e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x07, 12, 0,
159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    2,
160e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x04, 13, 0,
161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x07, 14, 0,
162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    1,
163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x18, 15, 0,
164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    5,
165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 18, 0,
166e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0f, 64, 0,
167e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 16, 0,
168e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x18, 17, 0,
169e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x37, 0, 0,
170e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    10,
171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 0x00, 0x07,
172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0c, 0x40, 0x07,
173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0d, 0x80, 0x07,
174e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 24, 0,
175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x18, 25, 0,
176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x28, 23, 0,
177e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x37, 22, 0,
178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x67, 19, 0,
179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x68, 20, 0,
180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6c, 21, 0,
181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    54,
182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x12, 1984 % 256, 1984 / 256,
183e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x13, 2048 % 256, 2048 / 256,
184e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x14, 2112 % 256, 2112 / 256,
185e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x15, 2176 % 256, 2176 / 256,
186e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x16, 2240 % 256, 2240 / 256,
187e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 2304 % 256, 2304 / 256,
188e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1c, 2368 % 256, 2368 / 256,
189e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1d, 2432 % 256, 2432 / 256,
190e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1e, 2496 % 256, 2496 / 256,
191e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1f, 2560 % 256, 2560 / 256,
192e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x24, 52, 0,
193e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x27, 55, 0,
194e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x28, 56, 0,
195e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2b, 59, 0,
196e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2c, 60, 0,
197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x33, 320 % 256, 320 / 256,
198e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x34, 384 % 256, 384 / 256,
199e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x35, 448 % 256, 448 / 256,
200e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x37, 53, 0,
201e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x38, 54, 0,
202e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x52, 50, 0,
203e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x53, 51, 0,
204e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x54, 44, 0,
205e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x55, 45, 0,
206e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x56, 46, 0,
207e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x57, 47, 0,
208e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x58, 57, 0,
209e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x59, 58, 0,
210e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x5a, 61, 0,
211e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x5b, 256 % 256, 256 / 256,
212e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x64, 48, 0,
213e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x65, 49, 0,
214e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x66, 62, 0,
215e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x67, 63, 0,
216e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x68, 30, 0,
217e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x69, 31, 0,
218e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6a, 32, 0,
219e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6b, 33, 0,
220e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6c, 40, 0,
221e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6d, 41, 0,
222e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xc8, 128, 0,
223e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xc9, 192, 0,
224e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xca, 26, 0,
225e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xcb, 27, 0,
226e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xcc, 28, 0,
227e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xcd, 29, 0,
228e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd2, 34, 0,
229e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd3, 35, 0,
230e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd4, 36, 0,
231e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd5, 37, 0,
232e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd6, 38, 0,
233e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd7, 39, 0,
234e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xda, 42, 0,
235e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xdb, 43, 0,
236e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    20,
237e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x4a, 640 % 256, 640 / 256,
238e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x4b, 704 % 256, 704 / 256,
239e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x4c, 768 % 256, 768 / 256,
240e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x4d, 832 % 256, 832 / 256,
241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x52, 1280 % 256, 1280 / 256,
242e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x53, 1344 % 256, 1344 / 256,
243e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x54, 1408 % 256, 1408 / 256,
244e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x55, 1472 % 256, 1472 / 256,
245e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x5a, 1536 % 256, 1536 / 256,
246e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x5b, 1600 % 256, 1600 / 256,
247e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x64, 1664 % 256, 1664 / 256,
248e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x65, 1728 % 256, 1728 / 256,
249e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6c, 512 % 256, 512 / 256,
250e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6d, 576 % 256, 576 / 256,
251e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x72, 896 % 256, 896 / 256,
252e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x73, 960 % 256, 960 / 256,
253e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x74, 1024 % 256, 1024 / 256,
254e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x75, 1088 % 256, 1088 / 256,
255e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x76, 1152 % 256, 1152 / 256,
256e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x77, 1216 % 256, 1216 / 256,
257e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xff
258e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
259e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE FaxWhiteRunIns[] = {
260e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0,
261e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0,
262e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0,
263e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    6,
264e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x07, 2, 0,
265e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 3, 0,
266e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0B, 4, 0,
267e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0C, 5, 0,
268e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0E, 6, 0,
269e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0F, 7, 0,
270e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    6,
271e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x07, 10, 0,
272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 11, 0,
273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x12, 128, 0,
274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x13, 8, 0,
275e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x14, 9, 0,
276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1b, 64, 0,
277e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    9,
278e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 13, 0,
279e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x07, 1, 0,
280e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 12, 0,
281e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 192, 0,
282e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x18, 1664 % 256, 1664 / 256,
283e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2a, 16, 0,
284e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2B, 17, 0,
285e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x34, 14, 0,
286e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x35, 15, 0,
287e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    12,
288e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 22, 0,
289e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x04, 23, 0,
290e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 20, 0,
291e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0c, 19, 0,
292e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x13, 26, 0,
293e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 21, 0,
294e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x18, 28, 0,
295e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x24, 27, 0,
296e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x27, 18, 0,
297e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x28, 24, 0,
298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2B, 25, 0,
299e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x37, 256 % 256, 256 / 256,
300e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    42,
301e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x02, 29, 0,
302e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 30, 0,
303e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x04, 45, 0,
304e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x05, 46, 0,
305e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0a, 47, 0,
306e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0b, 48, 0,
307e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x12, 33, 0,
308e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x13, 34, 0,
309e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x14, 35, 0,
310e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x15, 36, 0,
311e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x16, 37, 0,
312e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 38, 0,
313e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1a, 31, 0,
314e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1b, 32, 0,
315e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x24, 53, 0,
316e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x25, 54, 0,
317e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x28, 39, 0,
318e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x29, 40, 0,
319e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2a, 41, 0,
320e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2b, 42, 0,
321e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2c, 43, 0,
322e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2d, 44, 0,
323e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x32, 61, 0,
324e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x33, 62, 0,
325e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x34, 63, 0,
326e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x35, 0, 0,
327e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x36, 320 % 256, 320 / 256,
328e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x37, 384 % 256, 384 / 256,
329e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x4a, 59, 0,
330e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x4b, 60, 0,
331e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x52, 49, 0,
332e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x53, 50, 0,
333e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x54, 51, 0,
334e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x55, 52, 0,
335e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x58, 55, 0,
336e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x59, 56, 0,
337e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x5a, 57, 0,
338e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x5b, 58, 0,
339e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x64, 448 % 256, 448 / 256,
340e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x65, 512 % 256, 512 / 256,
341e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x67, 640 % 256, 640 / 256,
342e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x68, 576 % 256, 576 / 256,
343e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    16,
344e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x98, 1472 % 256, 1472 / 256,
345e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x99, 1536 % 256, 1536 / 256,
346e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x9a, 1600 % 256, 1600 / 256,
347e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x9b, 1728 % 256, 1728 / 256,
348e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xcc, 704 % 256, 704 / 256,
349e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xcd, 768 % 256, 768 / 256,
350e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd2, 832 % 256, 832 / 256,
351e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd3, 896 % 256, 896 / 256,
352e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd4, 960 % 256, 960 / 256,
353e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd5, 1024 % 256, 1024 / 256,
354e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd6, 1088 % 256, 1088 / 256,
355e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd7, 1152 % 256, 1152 / 256,
356e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd8, 1216 % 256, 1216 / 256,
357e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd9, 1280 % 256, 1280 / 256,
358e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xda, 1344 % 256, 1344 / 256,
359e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xdb, 1408 % 256, 1408 / 256,
360e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0,
361e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    3,
362e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 1792 % 256, 1792 / 256,
363e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0c, 1856 % 256, 1856 / 256,
364e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0d, 1920 % 256, 1920 / 256,
365e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    10,
366e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x12, 1984 % 256, 1984 / 256,
367e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x13, 2048 % 256, 2048 / 256,
368e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x14, 2112 % 256, 2112 / 256,
369e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x15, 2176 % 256, 2176 / 256,
370e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x16, 2240 % 256, 2240 / 256,
371e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 2304 % 256, 2304 / 256,
372e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1c, 2368 % 256, 2368 / 256,
373e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1d, 2432 % 256, 2432 / 256,
374e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1e, 2496 % 256, 2496 / 256,
375e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1f, 2560 % 256, 2560 / 256,
376e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xff,
377e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
378e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovint _FaxGetRun(FX_LPCBYTE ins_array, const FX_BYTE* src_buf, int& bitpos, int bitsize)
379e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
380e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_DWORD code = 0;
381e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int ins_off = 0;
382e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    while (1) {
383e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_BYTE ins = ins_array[ins_off++];
384e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (ins == 0xff) {
385e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return -1;
386e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (bitpos >= bitsize) {
388e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return -1;
389e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        code <<= 1;
391e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (src_buf[bitpos / 8] & (1 << (7 - bitpos % 8))) {
392e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            code ++;
393e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
394e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        bitpos ++;
395e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int next_off = ins_off + ins * 3;
396e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (; ins_off < next_off; ins_off += 3) {
397e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (ins_array[ins_off] == code) {
398e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                return ins_array[ins_off + 1] + ins_array[ins_off + 2] * 256;
399e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
400e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
401e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
402e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
403e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL _FaxG4GetRow(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, const FX_BYTE* ref_buf, int columns)
404e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
405e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int a0 = -1, a0color = 1;
406e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    while (1) {
407e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (bitpos >= bitsize) {
408e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return FALSE;
409e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
410e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int a1, a2, b1, b2;
411e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        _FaxG4FindB1B2(ref_buf, columns, a0, a0color, b1, b2);
412e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_BOOL bit = NEXTBIT;
413e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int v_delta = 0;
414e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (bit) {
415e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
416e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (bitpos >= bitsize) {
417e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                return FALSE;
418e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
419e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            FX_BOOL bit1 = NEXTBIT;
420e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (bitpos >= bitsize) {
421e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                return FALSE;
422e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
423e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            FX_BOOL bit2 = NEXTBIT;
424e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (bit1 && bit2) {
425e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                v_delta = 1;
426e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            } else if (bit1) {
427e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                v_delta = -1;
428e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            } else if (bit2) {
429e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                int run_len1 = 0;
430e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                while (1) {
431e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    int run = _FaxGetRun(a0color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf, bitpos, bitsize);
432e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    run_len1 += run;
433e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    if (run < 64) {
434e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        break;
435e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    }
436e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                }
437e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                if (a0 < 0) {
438e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    run_len1 ++;
439e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                }
440e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                a1 = a0 + run_len1;
441e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                if (!a0color) {
442e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    _FaxFillBits(dest_buf, columns, a0, a1);
443e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                }
444e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                int run_len2 = 0;
445e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                while (1) {
446e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    int run = _FaxGetRun(a0color ? FaxBlackRunIns : FaxWhiteRunIns, src_buf, bitpos, bitsize);
447e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    run_len2 += run;
448e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    if (run < 64) {
449e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        break;
450e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    }
451e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                }
452e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                a2 = a1 + run_len2;
453e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                if (a0color) {
454e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    _FaxFillBits(dest_buf, columns, a1, a2);
455e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                }
456e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                a0 = a2;
457e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                if (a0 < columns) {
458e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    continue;
459e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                }
460e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                return TRUE;
461e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            } else {
462e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                if (bitpos >= bitsize) {
463e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    return FALSE;
464e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                }
465e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                bit = NEXTBIT;
466e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                if (bit) {
467e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    if (!a0color) {
468e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        _FaxFillBits(dest_buf, columns, a0, b2);
469e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    }
470e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    if (b2 >= columns) {
471e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        return TRUE;
472e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    }
473e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    a0 = b2;
474e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    continue;
475e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                } else {
476e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    if (bitpos >= bitsize) {
477e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        return FALSE;
478e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    }
479e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    FX_BOOL bit1 = NEXTBIT;
480e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    if (bitpos >= bitsize) {
481e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        return FALSE;
482e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    }
483e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    FX_BOOL bit2 = NEXTBIT;
484e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    if (bit1 && bit2) {
485e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        v_delta = 2;
486e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    } else if (bit1) {
487e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        v_delta = -2;
488e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    } else if (bit2) {
489e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        if (bitpos >= bitsize) {
490e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                            return FALSE;
491e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        }
492e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        bit = NEXTBIT;
493e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        if (bit) {
494e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                            v_delta = 3;
495e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        } else {
496e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                            v_delta = -3;
497e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        }
498e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    } else {
499e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        if (bitpos >= bitsize) {
500e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                            return FALSE;
501e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        }
502e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        bit = NEXTBIT;
503e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        if (bit) {
504e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                            bitpos += 3;
505e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                            continue;
506e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        } else {
507e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                            bitpos += 5;
508e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                            return TRUE;
509e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        }
510e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    }
511e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                }
512e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
513e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
514e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        a1 = b1 + v_delta;
515e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (!a0color) {
516e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            _FaxFillBits(dest_buf, columns, a0, a1);
517e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
518e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (a1 >= columns) {
519e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return TRUE;
520e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
521e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        a0 = a1;
522e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        a0color = !a0color;
523e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
524e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
525e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL _FaxSkipEOL(const FX_BYTE* src_buf, int bitsize, int& bitpos)
526e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
527e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int startbit = bitpos;
528e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    while (bitpos < bitsize) {
529e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int bit = NEXTBIT;
530e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (bit) {
531e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (bitpos - startbit <= 11) {
532e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                bitpos = startbit;
533e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
534e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return TRUE;
535e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
536e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
537e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return FALSE;
538e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
539e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL _FaxGet1DLine(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, int columns)
540e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
541e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int color = TRUE;
542e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int startpos = 0;
543e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    while (1) {
544e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (bitpos >= bitsize) {
545e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return FALSE;
546e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
547e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int run_len = 0;
548e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        while (1) {
549e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            int run = _FaxGetRun(color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf, bitpos, bitsize);
550e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (run < 0) {
551e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                while (bitpos < bitsize) {
552e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    int bit = NEXTBIT;
553e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    if (bit) {
554e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                        return TRUE;
555e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    }
556e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                }
557e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                return FALSE;
558e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
559e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            run_len += run;
560e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (run < 64) {
561e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                break;
562e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
563e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
564e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (!color) {
565e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            _FaxFillBits(dest_buf, columns, startpos, startpos + run_len);
566e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
567e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        startpos += run_len;
568e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (startpos >= columns) {
569e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            break;
570e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
571e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        color = !color;
572e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
573e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return TRUE;
574e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
575e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovclass CCodec_FaxDecoder : public CCodec_ScanlineDecoder
576e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
577e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovpublic:
578e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CCodec_FaxDecoder();
579e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    virtual ~CCodec_FaxDecoder();
580e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_BOOL				Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
581e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                               int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows);
582e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    virtual void		v_DownScale(int dest_width, int dest_height) {}
583e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    virtual FX_BOOL		v_Rewind();
584e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    virtual FX_LPBYTE	v_GetNextLine();
585e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    virtual FX_DWORD	GetSrcOffset();
586e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int			m_Encoding, m_bEndOfLine, m_bByteAlign, m_bBlack;
587e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int			bitpos;
588e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_LPCBYTE	m_pSrcBuf;
589e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_DWORD	m_SrcSize;
590e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_LPBYTE	m_pScanlineBuf, m_pRefBuf;
591e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
592e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCCodec_FaxDecoder::CCodec_FaxDecoder()
593e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
594e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pScanlineBuf = NULL;
595e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pRefBuf = NULL;
596e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
597e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCCodec_FaxDecoder::~CCodec_FaxDecoder()
598e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
599e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_pScanlineBuf) {
600e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_Free(m_pScanlineBuf);
601e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
602e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_pRefBuf) {
603e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_Free(m_pRefBuf);
604e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
605e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
606e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CCodec_FaxDecoder::Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
607e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                                  int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows)
608e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
609e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_Encoding = K;
610e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_bEndOfLine = EndOfLine;
611e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_bByteAlign = EncodedByteAlign;
612e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_bBlack = BlackIs1;
613e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_OrigWidth = Columns;
614e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_OrigHeight = Rows;
615e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_OrigWidth == 0) {
616e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_OrigWidth = width;
617e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
618e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_OrigHeight == 0) {
619e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_OrigHeight = height;
620e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
621e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_Pitch = (m_OrigWidth + 31) / 32 * 4;
622e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_OutputWidth = m_OrigWidth;
623e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_OutputHeight = m_OrigHeight;
624e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pScanlineBuf = FX_Alloc(FX_BYTE, m_Pitch);
625e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pRefBuf = FX_Alloc(FX_BYTE, m_Pitch);
626e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pSrcBuf = src_buf;
627e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_SrcSize = src_size;
628e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_nComps = 1;
629e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_bpc = 1;
630e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_bColorTransformed = FALSE;
631e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return TRUE;
632e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
633e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CCodec_FaxDecoder::v_Rewind()
634e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
635e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch);
636e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    bitpos = 0;
637e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return TRUE;
638e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
639e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_LPBYTE CCodec_FaxDecoder::v_GetNextLine()
640e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
641e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int bitsize = m_SrcSize * 8;
642e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    _FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
643e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (bitpos >= bitsize) {
644e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
645e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
646e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch);
647e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_Encoding < 0) {
648e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        _FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_OrigWidth);
649e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch);
650e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else if (m_Encoding == 0) {
651e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        _FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
652e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else {
653e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_BOOL bNext1D = m_pSrcBuf[bitpos / 8] & (1 << (7 - bitpos % 8));
654e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        bitpos ++;
655e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (bNext1D) {
656e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            _FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth);
657e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
658e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            _FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_OrigWidth);
659e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
660e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch);
661e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
662e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_bEndOfLine) {
663e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        _FaxSkipEOL(m_pSrcBuf, bitsize, bitpos);
664e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
665e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_bByteAlign && bitpos < bitsize) {
666e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int bitpos0 = bitpos;
667e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int bitpos1 = (bitpos + 7) / 8 * 8;
668e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        while (m_bByteAlign && bitpos0 < bitpos1) {
669e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8));
670e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (bit != 0) {
671e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                m_bByteAlign = FALSE;
672e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            } else {
673e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                bitpos0 ++;
674e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
675e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
676e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (m_bByteAlign) {
677e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            bitpos = bitpos1;
678e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
679e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
680e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_bBlack) {
681e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (int i = 0; i < m_Pitch; i ++) {
682e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            m_pScanlineBuf[i] = ~m_pScanlineBuf[i];
683e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
684e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
685e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return m_pScanlineBuf;
686e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
687e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_DWORD CCodec_FaxDecoder::GetSrcOffset()
688e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
689e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_DWORD ret = (bitpos + 7) / 8;
690e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (ret > m_SrcSize) {
691e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        ret = m_SrcSize;
692e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
693e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return ret;
694e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
695e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovextern "C" {
696e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    void _FaxG4Decode(void*, FX_LPCBYTE src_buf, FX_DWORD src_size, int* pbitpos, FX_LPBYTE dest_buf, int width, int height, int pitch)
697e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    {
698e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (pitch == 0) {
699e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pitch = (width + 7) / 8;
700e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
701e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_LPBYTE ref_buf = FX_Alloc(FX_BYTE, pitch);
702e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FXSYS_memset8(ref_buf, 0xff, pitch);
703e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int bitpos = *pbitpos;
704e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (int iRow = 0; iRow < height; iRow ++) {
705e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            FX_LPBYTE line_buf = dest_buf + iRow * pitch;
706e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            FXSYS_memset8(line_buf, 0xff, pitch);
707e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            _FaxG4GetRow(src_buf, src_size << 3, bitpos, line_buf, ref_buf, width);
708e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            FXSYS_memcpy32(ref_buf, line_buf, pitch);
709e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
710e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_Free(ref_buf);
711e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        *pbitpos = bitpos;
712e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
713e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
714e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE BlackRunTerminator[128] = {
715e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x37, 10, 0x02, 3, 0x03, 2, 0x02, 2, 0x03, 3, 0x03, 4, 0x02, 4, 0x03, 5,
716e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x05, 6, 0x04, 6, 0x04, 7, 0x05, 7, 0x07, 7, 0x04, 8, 0x07, 8, 0x18, 9,
717e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11, 0x6c, 11, 0x37, 11, 0x28, 11,
718e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12, 0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12,
719e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6a, 12, 0x6b, 12, 0xd2, 12, 0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12,
720e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6c, 12, 0x6d, 12, 0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12,
721e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x64, 12, 0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12,
722e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12, 0x67, 12,
723e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
724e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE BlackRunMarkup[80] = {
725e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12, 0x6c, 13,
726e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13, 0x73, 13, 0x74, 13,
727e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13, 0x54, 13, 0x55, 13, 0x5a, 13,
728e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11, 0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12,
729e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x14, 12, 0x15, 12, 0x16, 12, 0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
730e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
731e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE WhiteRunTerminator[128] = {
732e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x35, 8,
733e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x07, 6,
734e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x07, 4,
735e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 4,
736e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0B, 4,
737e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0C, 4,
738e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0E, 4,
739e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0F, 4,
740e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x13, 5,
741e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x14, 5,
742e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x07, 5,
743e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 5,
744e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 6,
745e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 6,
746e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x34, 6,
747e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x35, 6,
748e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2a, 6,
749e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2B, 6,
750e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x27, 7,
751e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0c, 7,
752e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 7,
753e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 7,
754e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 7,
755e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x04, 7,
756e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x28, 7,
757e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2B, 7,
758e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x13, 7,
759e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x24, 7,
760e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x18, 7,
761e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x02, 8,
762e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x03, 8,
763e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1a, 8,
764e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1b, 8,
765e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x12, 8,
766e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x13, 8,
767e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x14, 8,
768e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x15, 8,
769e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x16, 8,
770e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 8,
771e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x28, 8,
772e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x29, 8,
773e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2a, 8,
774e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2b, 8,
775e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2c, 8,
776e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x2d, 8,
777e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x04, 8,
778e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x05, 8,
779e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0a, 8,
780e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0b, 8,
781e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x52, 8,
782e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x53, 8,
783e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x54, 8,
784e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x55, 8,
785e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x24, 8,
786e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x25, 8,
787e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x58, 8,
788e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x59, 8,
789e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x5a, 8,
790e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x5b, 8,
791e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x4a, 8,
792e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x4b, 8,
793e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x32, 8,
794e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x33, 8,
795e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x34, 8,
796e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
797e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE WhiteRunMarkup[80] = {
798e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1b, 5,
799e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x12, 5,
800e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 6,
801e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x37, 7,
802e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x36, 8,
803e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x37, 8,
804e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x64, 8,
805e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x65, 8,
806e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x68, 8,
807e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x67, 8,
808e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xcc, 9,
809e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xcd, 9,
810e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd2, 9,
811e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd3, 9,
812e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd4, 9,
813e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd5, 9,
814e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd6, 9,
815e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd7, 9,
816e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd8, 9,
817e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xd9, 9,
818e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xda, 9,
819e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0xdb, 9,
820e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x98, 9,
821e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x99, 9,
822e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x9a, 9,
823e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x18, 6,
824e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x9b, 9,
825e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x08, 11,
826e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0c, 11,
827e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x0d, 11,
828e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x12, 12,
829e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x13, 12,
830e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x14, 12,
831e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x15, 12,
832e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x16, 12,
833e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x17, 12,
834e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1c, 12,
835e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1d, 12,
836e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1e, 12,
837e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0x1f, 12,
838e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
839e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic void _AddBitStream(FX_LPBYTE dest_buf, int& dest_bitpos, int data, int bitlen)
840e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
841e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    for (int i = bitlen - 1; i >= 0; i --) {
842e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (data & (1 << i)) {
843e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
844e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
845e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        dest_bitpos ++;
846e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
847e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
848e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic void _FaxEncodeRun(FX_LPBYTE dest_buf, int& dest_bitpos, int run, FX_BOOL bWhite)
849e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
850e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    while (run >= 2560) {
851e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        _AddBitStream(dest_buf, dest_bitpos, 0x1f, 12);
852e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        run -= 2560;
853e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
854e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (run >= 64) {
855e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int markup = run - run % 64;
856e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_LPCBYTE p = bWhite ? WhiteRunMarkup : BlackRunMarkup;
857e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        p += (markup / 64 - 1) * 2;
858e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        _AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
859e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
860e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    run %= 64;
861e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_LPCBYTE p = bWhite ? WhiteRunTerminator : BlackRunTerminator;
862e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    p += run * 2;
863e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    _AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
864e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
865e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic void _FaxEncode2DLine(FX_LPBYTE dest_buf, int& dest_bitpos, FX_LPCBYTE src_buf, FX_LPCBYTE ref_buf, int cols)
866e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
867e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int a0 = -1, a0color = 1;
868e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    while (1) {
869e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int a1 = _FindBit(src_buf, cols, a0 + 1, 1 - a0color);
870e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int b1, b2;
871e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        _FaxG4FindB1B2(ref_buf, cols, a0, a0color, b1, b2);
872e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (b2 < a1) {
873e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_bitpos += 3;
874e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
875e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_bitpos ++;
876e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            a0 = b2;
877e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else if (a1 - b1 <= 3 && b1 - a1 <= 3) {
878e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            int delta = a1 - b1;
879e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            switch (delta) {
880e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                case 0:
881e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
882e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    break;
883e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                case 1:
884e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                case 2:
885e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                case 3:
886e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    dest_bitpos += delta == 1 ? 1 : delta + 2;
887e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
888e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    dest_bitpos ++;
889e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
890e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    break;
891e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                case -1:
892e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                case -2:
893e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                case -3:
894e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    dest_bitpos += delta == -1 ? 1 : -delta + 2;
895e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
896e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    dest_bitpos ++;
897e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                    break;
898e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
899e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_bitpos ++;
900e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            a0 = a1;
901e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            a0color = 1 - a0color;
902e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
903e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            int a2 = _FindBit(src_buf, cols, a1 + 1, a0color);
904e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_bitpos ++;
905e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_bitpos ++;
906e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8);
907e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            dest_bitpos ++;
908e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (a0 < 0) {
909e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                a0 = 0;
910e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
911e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            _FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color);
912e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            _FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, 1 - a0color);
913e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            a0 = a2;
914e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
915e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (a0 >= cols) {
916e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return;
917e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
918e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
919e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
920e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovclass CCodec_FaxEncoder
921e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
922e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovpublic:
923e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CCodec_FaxEncoder(FX_LPCBYTE src_buf, int width, int height, int pitch);
924e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    ~CCodec_FaxEncoder();
925e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    void			Encode(FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
926e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    void			Encode2DLine(FX_LPCBYTE scan_line);
927e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CFX_BinaryBuf	m_DestBuf;
928e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_LPBYTE		m_pRefLine, m_pLineBuf;
929e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int				m_Cols, m_Rows, m_Pitch;
930e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_LPCBYTE		m_pSrcBuf;
931e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
932e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCCodec_FaxEncoder::CCodec_FaxEncoder(FX_LPCBYTE src_buf, int width, int height, int pitch)
933e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
934e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pSrcBuf = src_buf;
935e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_Cols = width;
936e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_Rows = height;
937e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_Pitch = pitch;
938e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pRefLine = FX_Alloc(FX_BYTE, m_Pitch);
939e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FXSYS_memset8(m_pRefLine, 0xff, m_Pitch);
940e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pLineBuf = FX_Alloc2D(FX_BYTE, m_Pitch, 8);
941e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_DestBuf.EstimateSize(0, 10240);
942e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
943e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCCodec_FaxEncoder::~CCodec_FaxEncoder()
944e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
945e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_pRefLine) {
946e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_Free(m_pRefLine);
947e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
948e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_pLineBuf) {
949e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_Free(m_pLineBuf);
950e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
951e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
952e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CCodec_FaxEncoder::Encode(FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
953e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
954e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int dest_bitpos = 0;
955e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_BYTE last_byte = 0;
956e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    for (int i = 0; i < m_Rows; i ++) {
957e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_LPCBYTE scan_line = m_pSrcBuf + i * m_Pitch;
958e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FXSYS_memset32(m_pLineBuf, 0, m_Pitch * 8);
959e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_pLineBuf[0] = last_byte;
960e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        _FaxEncode2DLine(m_pLineBuf, dest_bitpos, scan_line, m_pRefLine, m_Cols);
961e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8);
962e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        last_byte = m_pLineBuf[dest_bitpos / 8];
963e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        dest_bitpos %= 8;
964e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FXSYS_memcpy32(m_pRefLine, scan_line, m_Pitch);
965e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
966e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (dest_bitpos) {
967e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_DestBuf.AppendByte(last_byte);
968e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
969e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    dest_buf = m_DestBuf.GetBuffer();
970e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    dest_size = m_DestBuf.GetSize();
971e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_DestBuf.DetachBuffer();
972e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
973e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL	CCodec_FaxModule::Encode(FX_LPCBYTE src_buf, int width, int height, int pitch, FX_LPBYTE& dest_buf, FX_DWORD& dest_size)
974e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
975e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CCodec_FaxEncoder encoder(src_buf, width, height, pitch);
976e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    encoder.Encode(dest_buf, dest_size);
977e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return TRUE;
978e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
979e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovICodec_ScanlineDecoder*	CCodec_FaxModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
980e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows)
981e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
982e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CCodec_FaxDecoder* pDecoder = new CCodec_FaxDecoder;
983e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    pDecoder->Create(src_buf, src_size, width, height, K, EndOfLine, EncodedByteAlign, BlackIs1, Columns, Rows);
984e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pDecoder;
985e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
986