Home | History | Annotate | Download | only in codec
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    629 CCodec_FaxDecoder::CCodec_FaxDecoder() {
    630   m_pScanlineBuf = NULL;
    631   m_pRefBuf = NULL;
    632 }
    633 CCodec_FaxDecoder::~CCodec_FaxDecoder() {
    634   FX_Free(m_pScanlineBuf);
    635   FX_Free(m_pRefBuf);
    636 }
    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 }
    672 FX_BOOL CCodec_FaxDecoder::v_Rewind() {
    673   FXSYS_memset(m_pRefBuf, 0xff, m_Pitch);
    674   bitpos = 0;
    675   return TRUE;
    676 }
    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 }
    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 
    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 };
    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 }
    782 CCodec_FaxEncoder::~CCodec_FaxEncoder() {
    783   FX_Free(m_pRefLine);
    784   FX_Free(m_pLineBuf);
    785 }
    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 }
    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 }
    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