Split up JBig2_GeneralDecoder.cpp.
[pdfium.git] / core / src / fxcodec / jbig2 / JBig2_GrdProc.cpp
1 // Copyright 2015 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 "JBig2_GrdProc.h"
8
9 #include "../../../../third_party/base/nonstd_unique_ptr.h"
10 #include "JBig2_ArithDecoder.h"
11 #include "JBig2_BitStream.h"
12 #include "JBig2_Image.h"
13
14 CJBig2_GRDProc::CJBig2_GRDProc()
15     : m_loopIndex(0),
16       m_pLine(nullptr),
17       m_pPause(nullptr),
18       m_DecodeType(0),
19       LTP(0) {
20   m_ReplaceRect.left = 0;
21   m_ReplaceRect.bottom = 0;
22   m_ReplaceRect.top = 0;
23   m_ReplaceRect.right = 0;
24 }
25
26 bool CJBig2_GRDProc::UseTemplate0Opt3() const {
27   return (GBAT[0] == 3) && (GBAT[1] == -1) && (GBAT[2] == -3) &&
28          (GBAT[3] == -1) && (GBAT[4] == 2) && (GBAT[5] == -2) &&
29          (GBAT[6] == -2) && (GBAT[7] == -2);
30 }
31
32 bool CJBig2_GRDProc::UseTemplate1Opt3() const {
33   return (GBAT[0] == 3) && (GBAT[1] == -1);
34 }
35
36 bool CJBig2_GRDProc::UseTemplate23Opt3() const {
37   return (GBAT[0] == 2) && (GBAT[1] == -1);
38 }
39
40 CJBig2_Image* CJBig2_GRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
41                                            JBig2ArithCtx* gbContext) {
42   if (GBW == 0 || GBH == 0)
43     return new CJBig2_Image(GBW, GBH);
44
45   if (GBTEMPLATE == 0) {
46     if (UseTemplate0Opt3())
47       return decode_Arith_Template0_opt3(pArithDecoder, gbContext);
48     return decode_Arith_Template0_unopt(pArithDecoder, gbContext);
49   } else if (GBTEMPLATE == 1) {
50     if (UseTemplate1Opt3())
51       return decode_Arith_Template1_opt3(pArithDecoder, gbContext);
52     return decode_Arith_Template1_unopt(pArithDecoder, gbContext);
53   } else if (GBTEMPLATE == 2) {
54     if (UseTemplate23Opt3())
55       return decode_Arith_Template2_opt3(pArithDecoder, gbContext);
56     return decode_Arith_Template2_unopt(pArithDecoder, gbContext);
57   } else {
58     if (UseTemplate23Opt3())
59       return decode_Arith_Template3_opt3(pArithDecoder, gbContext);
60     return decode_Arith_Template3_unopt(pArithDecoder, gbContext);
61   }
62 }
63 CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_opt3(
64     CJBig2_ArithDecoder* pArithDecoder,
65     JBig2ArithCtx* gbContext) {
66   FX_BOOL LTP, SLTP, bVal;
67   FX_DWORD CONTEXT;
68   FX_DWORD line1, line2;
69   uint8_t* pLine, *pLine1, *pLine2, cVal;
70   int32_t nStride, nStride2, k;
71   int32_t nLineBytes, nBitsLeft, cc;
72   LTP = 0;
73   nonstd::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
74   if (!GBREG->m_pData)
75     return nullptr;
76
77   pLine = GBREG->m_pData;
78   nStride = GBREG->m_nStride;
79   nStride2 = nStride << 1;
80   nLineBytes = ((GBW + 7) >> 3) - 1;
81   nBitsLeft = GBW - (nLineBytes << 3);
82   FX_DWORD height = GBH & 0x7fffffff;
83   for (FX_DWORD h = 0; h < height; h++) {
84     if (TPGDON) {
85       SLTP = pArithDecoder->DECODE(&gbContext[0x9b25]);
86       LTP = LTP ^ SLTP;
87     }
88     if (LTP == 1) {
89       GBREG->copyLine(h, h - 1);
90     } else {
91       if (h > 1) {
92         pLine1 = pLine - nStride2;
93         pLine2 = pLine - nStride;
94         line1 = (*pLine1++) << 6;
95         line2 = *pLine2++;
96         CONTEXT = ((line1 & 0xf800) | (line2 & 0x07f0));
97         for (cc = 0; cc < nLineBytes; cc++) {
98           line1 = (line1 << 8) | ((*pLine1++) << 6);
99           line2 = (line2 << 8) | (*pLine2++);
100           cVal = 0;
101           for (k = 7; k >= 0; k--) {
102             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
103             cVal |= bVal << k;
104             CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
105                        ((line1 >> k) & 0x0800) | ((line2 >> k) & 0x0010));
106           }
107           pLine[cc] = cVal;
108         }
109         line1 <<= 8;
110         line2 <<= 8;
111         cVal = 0;
112         for (k = 0; k < nBitsLeft; k++) {
113           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
114           cVal |= bVal << (7 - k);
115           CONTEXT =
116               (((CONTEXT & 0x7bf7) << 1) | bVal |
117                ((line1 >> (7 - k)) & 0x0800) | ((line2 >> (7 - k)) & 0x0010));
118         }
119         pLine[nLineBytes] = cVal;
120       } else {
121         pLine2 = pLine - nStride;
122         line2 = (h & 1) ? (*pLine2++) : 0;
123         CONTEXT = (line2 & 0x07f0);
124         for (cc = 0; cc < nLineBytes; cc++) {
125           if (h & 1) {
126             line2 = (line2 << 8) | (*pLine2++);
127           }
128           cVal = 0;
129           for (k = 7; k >= 0; k--) {
130             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
131             cVal |= bVal << k;
132             CONTEXT =
133                 (((CONTEXT & 0x7bf7) << 1) | bVal | ((line2 >> k) & 0x0010));
134           }
135           pLine[cc] = cVal;
136         }
137         line2 <<= 8;
138         cVal = 0;
139         for (k = 0; k < nBitsLeft; k++) {
140           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
141           cVal |= bVal << (7 - k);
142           CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
143                      (((line2 >> (7 - k))) & 0x0010));
144         }
145         pLine[nLineBytes] = cVal;
146       }
147     }
148     pLine += nStride;
149   }
150   return GBREG.release();
151 }
152
153 CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_unopt(
154     CJBig2_ArithDecoder* pArithDecoder,
155     JBig2ArithCtx* gbContext) {
156   FX_BOOL LTP, SLTP, bVal;
157   FX_DWORD CONTEXT;
158   FX_DWORD line1, line2, line3;
159   LTP = 0;
160   nonstd::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
161   GBREG->fill(0);
162   for (FX_DWORD h = 0; h < GBH; h++) {
163     if (TPGDON) {
164       SLTP = pArithDecoder->DECODE(&gbContext[0x9b25]);
165       LTP = LTP ^ SLTP;
166     }
167     if (LTP == 1) {
168       GBREG->copyLine(h, h - 1);
169     } else {
170       line1 = GBREG->getPixel(1, h - 2);
171       line1 |= GBREG->getPixel(0, h - 2) << 1;
172       line2 = GBREG->getPixel(2, h - 1);
173       line2 |= GBREG->getPixel(1, h - 1) << 1;
174       line2 |= GBREG->getPixel(0, h - 1) << 2;
175       line3 = 0;
176       for (FX_DWORD w = 0; w < GBW; w++) {
177         if (USESKIP && SKIP->getPixel(w, h)) {
178           bVal = 0;
179         } else {
180           CONTEXT = line3;
181           CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 4;
182           CONTEXT |= line2 << 5;
183           CONTEXT |= GBREG->getPixel(w + GBAT[2], h + GBAT[3]) << 10;
184           CONTEXT |= GBREG->getPixel(w + GBAT[4], h + GBAT[5]) << 11;
185           CONTEXT |= line1 << 12;
186           CONTEXT |= GBREG->getPixel(w + GBAT[6], h + GBAT[7]) << 15;
187           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
188         }
189         if (bVal) {
190           GBREG->setPixel(w, h, bVal);
191         }
192         line1 = ((line1 << 1) | GBREG->getPixel(w + 2, h - 2)) & 0x07;
193         line2 = ((line2 << 1) | GBREG->getPixel(w + 3, h - 1)) & 0x1f;
194         line3 = ((line3 << 1) | bVal) & 0x0f;
195       }
196     }
197   }
198   return GBREG.release();
199 }
200
201 CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_opt3(
202     CJBig2_ArithDecoder* pArithDecoder,
203     JBig2ArithCtx* gbContext) {
204   FX_BOOL LTP, SLTP, bVal;
205   FX_DWORD CONTEXT;
206   FX_DWORD line1, line2;
207   uint8_t* pLine, *pLine1, *pLine2, cVal;
208   int32_t nStride, nStride2, k;
209   int32_t nLineBytes, nBitsLeft, cc;
210   LTP = 0;
211   nonstd::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
212   if (!GBREG->m_pData)
213     return nullptr;
214
215   pLine = GBREG->m_pData;
216   nStride = GBREG->m_nStride;
217   nStride2 = nStride << 1;
218   nLineBytes = ((GBW + 7) >> 3) - 1;
219   nBitsLeft = GBW - (nLineBytes << 3);
220   for (FX_DWORD h = 0; h < GBH; h++) {
221     if (TPGDON) {
222       SLTP = pArithDecoder->DECODE(&gbContext[0x0795]);
223       LTP = LTP ^ SLTP;
224     }
225     if (LTP == 1) {
226       GBREG->copyLine(h, h - 1);
227     } else {
228       if (h > 1) {
229         pLine1 = pLine - nStride2;
230         pLine2 = pLine - nStride;
231         line1 = (*pLine1++) << 4;
232         line2 = *pLine2++;
233         CONTEXT = (line1 & 0x1e00) | ((line2 >> 1) & 0x01f8);
234         for (cc = 0; cc < nLineBytes; cc++) {
235           line1 = (line1 << 8) | ((*pLine1++) << 4);
236           line2 = (line2 << 8) | (*pLine2++);
237           cVal = 0;
238           for (k = 7; k >= 0; k--) {
239             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
240             cVal |= bVal << k;
241             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
242                       ((line1 >> k) & 0x0200) | ((line2 >> (k + 1)) & 0x0008);
243           }
244           pLine[cc] = cVal;
245         }
246         line1 <<= 8;
247         line2 <<= 8;
248         cVal = 0;
249         for (k = 0; k < nBitsLeft; k++) {
250           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
251           cVal |= bVal << (7 - k);
252           CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
253                     ((line1 >> (7 - k)) & 0x0200) |
254                     ((line2 >> (8 - k)) & 0x0008);
255         }
256         pLine[nLineBytes] = cVal;
257       } else {
258         pLine2 = pLine - nStride;
259         line2 = (h & 1) ? (*pLine2++) : 0;
260         CONTEXT = (line2 >> 1) & 0x01f8;
261         for (cc = 0; cc < nLineBytes; cc++) {
262           if (h & 1) {
263             line2 = (line2 << 8) | (*pLine2++);
264           }
265           cVal = 0;
266           for (k = 7; k >= 0; k--) {
267             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
268             cVal |= bVal << k;
269             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
270                       ((line2 >> (k + 1)) & 0x0008);
271           }
272           pLine[cc] = cVal;
273         }
274         line2 <<= 8;
275         cVal = 0;
276         for (k = 0; k < nBitsLeft; k++) {
277           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
278           cVal |= bVal << (7 - k);
279           CONTEXT =
280               ((CONTEXT & 0x0efb) << 1) | bVal | ((line2 >> (8 - k)) & 0x0008);
281         }
282         pLine[nLineBytes] = cVal;
283       }
284     }
285     pLine += nStride;
286   }
287   return GBREG.release();
288 }
289
290 CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_unopt(
291     CJBig2_ArithDecoder* pArithDecoder,
292     JBig2ArithCtx* gbContext) {
293   FX_BOOL LTP, SLTP, bVal;
294   FX_DWORD CONTEXT;
295   FX_DWORD line1, line2, line3;
296   LTP = 0;
297   nonstd::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
298   GBREG->fill(0);
299   for (FX_DWORD h = 0; h < GBH; h++) {
300     if (TPGDON) {
301       SLTP = pArithDecoder->DECODE(&gbContext[0x0795]);
302       LTP = LTP ^ SLTP;
303     }
304     if (LTP == 1) {
305       GBREG->copyLine(h, h - 1);
306     } else {
307       line1 = GBREG->getPixel(2, h - 2);
308       line1 |= GBREG->getPixel(1, h - 2) << 1;
309       line1 |= GBREG->getPixel(0, h - 2) << 2;
310       line2 = GBREG->getPixel(2, h - 1);
311       line2 |= GBREG->getPixel(1, h - 1) << 1;
312       line2 |= GBREG->getPixel(0, h - 1) << 2;
313       line3 = 0;
314       for (FX_DWORD w = 0; w < GBW; w++) {
315         if (USESKIP && SKIP->getPixel(w, h)) {
316           bVal = 0;
317         } else {
318           CONTEXT = line3;
319           CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 3;
320           CONTEXT |= line2 << 4;
321           CONTEXT |= line1 << 9;
322           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
323         }
324         if (bVal) {
325           GBREG->setPixel(w, h, bVal);
326         }
327         line1 = ((line1 << 1) | GBREG->getPixel(w + 3, h - 2)) & 0x0f;
328         line2 = ((line2 << 1) | GBREG->getPixel(w + 3, h - 1)) & 0x1f;
329         line3 = ((line3 << 1) | bVal) & 0x07;
330       }
331     }
332   }
333   return GBREG.release();
334 }
335 CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_opt3(
336     CJBig2_ArithDecoder* pArithDecoder,
337     JBig2ArithCtx* gbContext) {
338   FX_BOOL LTP, SLTP, bVal;
339   FX_DWORD CONTEXT;
340   FX_DWORD line1, line2;
341   uint8_t* pLine, *pLine1, *pLine2, cVal;
342   int32_t nStride, nStride2, k;
343   int32_t nLineBytes, nBitsLeft, cc;
344   LTP = 0;
345   nonstd::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
346   if (!GBREG->m_pData)
347     return nullptr;
348
349   pLine = GBREG->m_pData;
350   nStride = GBREG->m_nStride;
351   nStride2 = nStride << 1;
352   nLineBytes = ((GBW + 7) >> 3) - 1;
353   nBitsLeft = GBW - (nLineBytes << 3);
354   for (FX_DWORD h = 0; h < GBH; h++) {
355     if (TPGDON) {
356       SLTP = pArithDecoder->DECODE(&gbContext[0x00e5]);
357       LTP = LTP ^ SLTP;
358     }
359     if (LTP == 1) {
360       GBREG->copyLine(h, h - 1);
361     } else {
362       if (h > 1) {
363         pLine1 = pLine - nStride2;
364         pLine2 = pLine - nStride;
365         line1 = (*pLine1++) << 1;
366         line2 = *pLine2++;
367         CONTEXT = (line1 & 0x0380) | ((line2 >> 3) & 0x007c);
368         for (cc = 0; cc < nLineBytes; cc++) {
369           line1 = (line1 << 8) | ((*pLine1++) << 1);
370           line2 = (line2 << 8) | (*pLine2++);
371           cVal = 0;
372           for (k = 7; k >= 0; k--) {
373             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
374             cVal |= bVal << k;
375             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
376                       ((line1 >> k) & 0x0080) | ((line2 >> (k + 3)) & 0x0004);
377           }
378           pLine[cc] = cVal;
379         }
380         line1 <<= 8;
381         line2 <<= 8;
382         cVal = 0;
383         for (k = 0; k < nBitsLeft; k++) {
384           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
385           cVal |= bVal << (7 - k);
386           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
387                     ((line1 >> (7 - k)) & 0x0080) |
388                     ((line2 >> (10 - k)) & 0x0004);
389         }
390         pLine[nLineBytes] = cVal;
391       } else {
392         pLine2 = pLine - nStride;
393         line2 = (h & 1) ? (*pLine2++) : 0;
394         CONTEXT = (line2 >> 3) & 0x007c;
395         for (cc = 0; cc < nLineBytes; cc++) {
396           if (h & 1) {
397             line2 = (line2 << 8) | (*pLine2++);
398           }
399           cVal = 0;
400           for (k = 7; k >= 0; k--) {
401             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
402             cVal |= bVal << k;
403             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
404                       ((line2 >> (k + 3)) & 0x0004);
405           }
406           pLine[cc] = cVal;
407         }
408         line2 <<= 8;
409         cVal = 0;
410         for (k = 0; k < nBitsLeft; k++) {
411           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
412           cVal |= bVal << (7 - k);
413           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
414                     (((line2 >> (10 - k))) & 0x0004);
415         }
416         pLine[nLineBytes] = cVal;
417       }
418     }
419     pLine += nStride;
420   }
421   return GBREG.release();
422 }
423
424 CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_unopt(
425     CJBig2_ArithDecoder* pArithDecoder,
426     JBig2ArithCtx* gbContext) {
427   FX_BOOL LTP, SLTP, bVal;
428   FX_DWORD CONTEXT;
429   FX_DWORD line1, line2, line3;
430   LTP = 0;
431   nonstd::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
432   GBREG->fill(0);
433   for (FX_DWORD h = 0; h < GBH; h++) {
434     if (TPGDON) {
435       SLTP = pArithDecoder->DECODE(&gbContext[0x00e5]);
436       LTP = LTP ^ SLTP;
437     }
438     if (LTP == 1) {
439       GBREG->copyLine(h, h - 1);
440     } else {
441       line1 = GBREG->getPixel(1, h - 2);
442       line1 |= GBREG->getPixel(0, h - 2) << 1;
443       line2 = GBREG->getPixel(1, h - 1);
444       line2 |= GBREG->getPixel(0, h - 1) << 1;
445       line3 = 0;
446       for (FX_DWORD w = 0; w < GBW; w++) {
447         if (USESKIP && SKIP->getPixel(w, h)) {
448           bVal = 0;
449         } else {
450           CONTEXT = line3;
451           CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 2;
452           CONTEXT |= line2 << 3;
453           CONTEXT |= line1 << 7;
454           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
455         }
456         if (bVal) {
457           GBREG->setPixel(w, h, bVal);
458         }
459         line1 = ((line1 << 1) | GBREG->getPixel(w + 2, h - 2)) & 0x07;
460         line2 = ((line2 << 1) | GBREG->getPixel(w + 2, h - 1)) & 0x0f;
461         line3 = ((line3 << 1) | bVal) & 0x03;
462       }
463     }
464   }
465   return GBREG.release();
466 }
467
468 CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_opt3(
469     CJBig2_ArithDecoder* pArithDecoder,
470     JBig2ArithCtx* gbContext) {
471   FX_BOOL LTP, SLTP, bVal;
472   FX_DWORD CONTEXT;
473   FX_DWORD line1;
474   uint8_t* pLine, *pLine1, cVal;
475   int32_t nStride, k;
476   int32_t nLineBytes, nBitsLeft, cc;
477   LTP = 0;
478   nonstd::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
479   if (!GBREG->m_pData)
480     return nullptr;
481
482   pLine = GBREG->m_pData;
483   nStride = GBREG->m_nStride;
484   nLineBytes = ((GBW + 7) >> 3) - 1;
485   nBitsLeft = GBW - (nLineBytes << 3);
486   for (FX_DWORD h = 0; h < GBH; h++) {
487     if (TPGDON) {
488       SLTP = pArithDecoder->DECODE(&gbContext[0x0195]);
489       LTP = LTP ^ SLTP;
490     }
491     if (LTP == 1) {
492       GBREG->copyLine(h, h - 1);
493     } else {
494       if (h > 0) {
495         pLine1 = pLine - nStride;
496         line1 = *pLine1++;
497         CONTEXT = (line1 >> 1) & 0x03f0;
498         for (cc = 0; cc < nLineBytes; cc++) {
499           line1 = (line1 << 8) | (*pLine1++);
500           cVal = 0;
501           for (k = 7; k >= 0; k--) {
502             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
503             cVal |= bVal << k;
504             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal |
505                       ((line1 >> (k + 1)) & 0x0010);
506           }
507           pLine[cc] = cVal;
508         }
509         line1 <<= 8;
510         cVal = 0;
511         for (k = 0; k < nBitsLeft; k++) {
512           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
513           cVal |= bVal << (7 - k);
514           CONTEXT =
515               ((CONTEXT & 0x01f7) << 1) | bVal | ((line1 >> (8 - k)) & 0x0010);
516         }
517         pLine[nLineBytes] = cVal;
518       } else {
519         CONTEXT = 0;
520         for (cc = 0; cc < nLineBytes; cc++) {
521           cVal = 0;
522           for (k = 7; k >= 0; k--) {
523             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
524             cVal |= bVal << k;
525             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
526           }
527           pLine[cc] = cVal;
528         }
529         cVal = 0;
530         for (k = 0; k < nBitsLeft; k++) {
531           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
532           cVal |= bVal << (7 - k);
533           CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
534         }
535         pLine[nLineBytes] = cVal;
536       }
537     }
538     pLine += nStride;
539   }
540   return GBREG.release();
541 }
542
543 CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_unopt(
544     CJBig2_ArithDecoder* pArithDecoder,
545     JBig2ArithCtx* gbContext) {
546   FX_BOOL LTP, SLTP, bVal;
547   FX_DWORD CONTEXT;
548   FX_DWORD line1, line2;
549   LTP = 0;
550   nonstd::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
551   GBREG->fill(0);
552   for (FX_DWORD h = 0; h < GBH; h++) {
553     if (TPGDON) {
554       SLTP = pArithDecoder->DECODE(&gbContext[0x0195]);
555       LTP = LTP ^ SLTP;
556     }
557     if (LTP == 1) {
558       GBREG->copyLine(h, h - 1);
559     } else {
560       line1 = GBREG->getPixel(1, h - 1);
561       line1 |= GBREG->getPixel(0, h - 1) << 1;
562       line2 = 0;
563       for (FX_DWORD w = 0; w < GBW; w++) {
564         if (USESKIP && SKIP->getPixel(w, h)) {
565           bVal = 0;
566         } else {
567           CONTEXT = line2;
568           CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 4;
569           CONTEXT |= line1 << 5;
570           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
571         }
572         if (bVal) {
573           GBREG->setPixel(w, h, bVal);
574         }
575         line1 = ((line1 << 1) | GBREG->getPixel(w + 2, h - 1)) & 0x1f;
576         line2 = ((line2 << 1) | bVal) & 0x0f;
577       }
578     }
579   }
580   return GBREG.release();
581 }
582
583 FXCODEC_STATUS CJBig2_GRDProc::Start_decode_Arith(
584     CJBig2_Image** pImage,
585     CJBig2_ArithDecoder* pArithDecoder,
586     JBig2ArithCtx* gbContext,
587     IFX_Pause* pPause) {
588   if (GBW == 0 || GBH == 0) {
589     m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
590     return FXCODEC_STATUS_DECODE_FINISH;
591   }
592   m_ProssiveStatus = FXCODEC_STATUS_DECODE_READY;
593   m_pPause = pPause;
594   if (!*pImage)
595     *pImage = new CJBig2_Image(GBW, GBH);
596   if (!(*pImage)->m_pData) {
597     delete *pImage;
598     *pImage = nullptr;
599     m_ProssiveStatus = FXCODEC_STATUS_ERROR;
600     return FXCODEC_STATUS_ERROR;
601   }
602   m_DecodeType = 1;
603   m_pImage = pImage;
604   (*m_pImage)->fill(0);
605   m_pArithDecoder = pArithDecoder;
606   m_gbContext = gbContext;
607   LTP = 0;
608   m_pLine = nullptr;
609   m_loopIndex = 0;
610   return decode_Arith(pPause);
611 }
612
613 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith(IFX_Pause* pPause) {
614   int iline = m_loopIndex;
615   CJBig2_Image* pImage = *m_pImage;
616   if (GBTEMPLATE == 0) {
617     if (UseTemplate0Opt3()) {
618       m_ProssiveStatus = decode_Arith_Template0_opt3(pImage, m_pArithDecoder,
619                                                      m_gbContext, pPause);
620     } else {
621       m_ProssiveStatus = decode_Arith_Template0_unopt(pImage, m_pArithDecoder,
622                                                       m_gbContext, pPause);
623     }
624   } else if (GBTEMPLATE == 1) {
625     if (UseTemplate1Opt3()) {
626       m_ProssiveStatus = decode_Arith_Template1_opt3(pImage, m_pArithDecoder,
627                                                      m_gbContext, pPause);
628     } else {
629       m_ProssiveStatus = decode_Arith_Template1_unopt(pImage, m_pArithDecoder,
630                                                       m_gbContext, pPause);
631     }
632   } else if (GBTEMPLATE == 2) {
633     if (UseTemplate23Opt3()) {
634       m_ProssiveStatus = decode_Arith_Template2_opt3(pImage, m_pArithDecoder,
635                                                      m_gbContext, pPause);
636     } else {
637       m_ProssiveStatus = decode_Arith_Template2_unopt(pImage, m_pArithDecoder,
638                                                       m_gbContext, pPause);
639     }
640   } else {
641     if (UseTemplate23Opt3()) {
642       m_ProssiveStatus = decode_Arith_Template3_opt3(pImage, m_pArithDecoder,
643                                                      m_gbContext, pPause);
644     } else {
645       m_ProssiveStatus = decode_Arith_Template3_unopt(pImage, m_pArithDecoder,
646                                                       m_gbContext, pPause);
647     }
648   }
649   m_ReplaceRect.left = 0;
650   m_ReplaceRect.right = pImage->m_nWidth;
651   m_ReplaceRect.top = iline;
652   m_ReplaceRect.bottom = m_loopIndex;
653   if (m_ProssiveStatus == FXCODEC_STATUS_DECODE_FINISH) {
654     m_loopIndex = 0;
655   }
656   return m_ProssiveStatus;
657 }
658
659 FXCODEC_STATUS CJBig2_GRDProc::Start_decode_MMR(CJBig2_Image** pImage,
660                                                 CJBig2_BitStream* pStream,
661                                                 IFX_Pause* pPause) {
662   int bitpos, i;
663   *pImage = new CJBig2_Image(GBW, GBH);
664   if (!(*pImage)->m_pData) {
665     delete (*pImage);
666     (*pImage) = nullptr;
667     m_ProssiveStatus = FXCODEC_STATUS_ERROR;
668     return m_ProssiveStatus;
669   }
670   bitpos = (int)pStream->getBitPos();
671   _FaxG4Decode(pStream->getBuf(), pStream->getLength(), &bitpos,
672                (*pImage)->m_pData, GBW, GBH, (*pImage)->m_nStride);
673   pStream->setBitPos(bitpos);
674   for (i = 0; (FX_DWORD)i < (*pImage)->m_nStride * GBH; i++) {
675     (*pImage)->m_pData[i] = ~(*pImage)->m_pData[i];
676   }
677   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
678   return m_ProssiveStatus;
679 }
680
681 FXCODEC_STATUS CJBig2_GRDProc::Continue_decode(IFX_Pause* pPause) {
682   if (m_ProssiveStatus != FXCODEC_STATUS_DECODE_TOBECONTINUE)
683     return m_ProssiveStatus;
684
685   if (m_DecodeType != 1) {
686     m_ProssiveStatus = FXCODEC_STATUS_ERROR;
687     return m_ProssiveStatus;
688   }
689
690   return decode_Arith(pPause);
691 }
692
693 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_opt3(
694     CJBig2_Image* pImage,
695     CJBig2_ArithDecoder* pArithDecoder,
696     JBig2ArithCtx* gbContext,
697     IFX_Pause* pPause) {
698   FX_BOOL SLTP, bVal;
699   FX_DWORD CONTEXT;
700   FX_DWORD line1, line2;
701   uint8_t* pLine1, *pLine2, cVal;
702   int32_t nStride, nStride2, k;
703   int32_t nLineBytes, nBitsLeft, cc;
704   if (!m_pLine) {
705     m_pLine = pImage->m_pData;
706   }
707   nStride = pImage->m_nStride;
708   nStride2 = nStride << 1;
709   nLineBytes = ((GBW + 7) >> 3) - 1;
710   nBitsLeft = GBW - (nLineBytes << 3);
711   FX_DWORD height = GBH & 0x7fffffff;
712   for (; m_loopIndex < height; m_loopIndex++) {
713     if (TPGDON) {
714       SLTP = pArithDecoder->DECODE(&gbContext[0x9b25]);
715       LTP = LTP ^ SLTP;
716     }
717     if (LTP == 1) {
718       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
719     } else {
720       if (m_loopIndex > 1) {
721         pLine1 = m_pLine - nStride2;
722         pLine2 = m_pLine - nStride;
723         line1 = (*pLine1++) << 6;
724         line2 = *pLine2++;
725         CONTEXT = ((line1 & 0xf800) | (line2 & 0x07f0));
726         for (cc = 0; cc < nLineBytes; cc++) {
727           line1 = (line1 << 8) | ((*pLine1++) << 6);
728           line2 = (line2 << 8) | (*pLine2++);
729           cVal = 0;
730           for (k = 7; k >= 0; k--) {
731             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
732             cVal |= bVal << k;
733             CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
734                        ((line1 >> k) & 0x0800) | ((line2 >> k) & 0x0010));
735           }
736           m_pLine[cc] = cVal;
737         }
738         line1 <<= 8;
739         line2 <<= 8;
740         cVal = 0;
741         for (k = 0; k < nBitsLeft; k++) {
742           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
743           cVal |= bVal << (7 - k);
744           CONTEXT =
745               (((CONTEXT & 0x7bf7) << 1) | bVal |
746                ((line1 >> (7 - k)) & 0x0800) | ((line2 >> (7 - k)) & 0x0010));
747         }
748         m_pLine[nLineBytes] = cVal;
749       } else {
750         pLine2 = m_pLine - nStride;
751         line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
752         CONTEXT = (line2 & 0x07f0);
753         for (cc = 0; cc < nLineBytes; cc++) {
754           if (m_loopIndex & 1) {
755             line2 = (line2 << 8) | (*pLine2++);
756           }
757           cVal = 0;
758           for (k = 7; k >= 0; k--) {
759             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
760             cVal |= bVal << k;
761             CONTEXT =
762                 (((CONTEXT & 0x7bf7) << 1) | bVal | ((line2 >> k) & 0x0010));
763           }
764           m_pLine[cc] = cVal;
765         }
766         line2 <<= 8;
767         cVal = 0;
768         for (k = 0; k < nBitsLeft; k++) {
769           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
770           cVal |= bVal << (7 - k);
771           CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
772                      ((line2 >> (7 - k)) & 0x0010));
773         }
774         m_pLine[nLineBytes] = cVal;
775       }
776     }
777     m_pLine += nStride;
778     if (pPause && pPause->NeedToPauseNow()) {
779       m_loopIndex++;
780       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
781       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
782     }
783   }
784   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
785   return FXCODEC_STATUS_DECODE_FINISH;
786 }
787
788 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_unopt(
789     CJBig2_Image* pImage,
790     CJBig2_ArithDecoder* pArithDecoder,
791     JBig2ArithCtx* gbContext,
792     IFX_Pause* pPause) {
793   FX_BOOL SLTP, bVal;
794   FX_DWORD CONTEXT;
795   FX_DWORD line1, line2, line3;
796   for (; m_loopIndex < GBH; m_loopIndex++) {
797     if (TPGDON) {
798       SLTP = pArithDecoder->DECODE(&gbContext[0x9b25]);
799       LTP = LTP ^ SLTP;
800     }
801     if (LTP == 1) {
802       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
803     } else {
804       line1 = pImage->getPixel(1, m_loopIndex - 2);
805       line1 |= pImage->getPixel(0, m_loopIndex - 2) << 1;
806       line2 = pImage->getPixel(2, m_loopIndex - 1);
807       line2 |= pImage->getPixel(1, m_loopIndex - 1) << 1;
808       line2 |= pImage->getPixel(0, m_loopIndex - 1) << 2;
809       line3 = 0;
810       for (FX_DWORD w = 0; w < GBW; w++) {
811         if (USESKIP && SKIP->getPixel(w, m_loopIndex)) {
812           bVal = 0;
813         } else {
814           CONTEXT = line3;
815           CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 4;
816           CONTEXT |= line2 << 5;
817           CONTEXT |= pImage->getPixel(w + GBAT[2], m_loopIndex + GBAT[3]) << 10;
818           CONTEXT |= pImage->getPixel(w + GBAT[4], m_loopIndex + GBAT[5]) << 11;
819           CONTEXT |= line1 << 12;
820           CONTEXT |= pImage->getPixel(w + GBAT[6], m_loopIndex + GBAT[7]) << 15;
821           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
822         }
823         if (bVal) {
824           pImage->setPixel(w, m_loopIndex, bVal);
825         }
826         line1 =
827             ((line1 << 1) | pImage->getPixel(w + 2, m_loopIndex - 2)) & 0x07;
828         line2 =
829             ((line2 << 1) | pImage->getPixel(w + 3, m_loopIndex - 1)) & 0x1f;
830         line3 = ((line3 << 1) | bVal) & 0x0f;
831       }
832     }
833     if (pPause && pPause->NeedToPauseNow()) {
834       m_loopIndex++;
835       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
836       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
837     }
838   }
839   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
840   return FXCODEC_STATUS_DECODE_FINISH;
841 }
842
843 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_opt3(
844     CJBig2_Image* pImage,
845     CJBig2_ArithDecoder* pArithDecoder,
846     JBig2ArithCtx* gbContext,
847     IFX_Pause* pPause) {
848   FX_BOOL SLTP, bVal;
849   FX_DWORD CONTEXT;
850   FX_DWORD line1, line2;
851   uint8_t* pLine1, *pLine2, cVal;
852   int32_t nStride, nStride2, k;
853   int32_t nLineBytes, nBitsLeft, cc;
854   if (!m_pLine) {
855     m_pLine = pImage->m_pData;
856   }
857   nStride = pImage->m_nStride;
858   nStride2 = nStride << 1;
859   nLineBytes = ((GBW + 7) >> 3) - 1;
860   nBitsLeft = GBW - (nLineBytes << 3);
861   for (; m_loopIndex < GBH; m_loopIndex++) {
862     if (TPGDON) {
863       SLTP = pArithDecoder->DECODE(&gbContext[0x0795]);
864       LTP = LTP ^ SLTP;
865     }
866     if (LTP == 1) {
867       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
868     } else {
869       if (m_loopIndex > 1) {
870         pLine1 = m_pLine - nStride2;
871         pLine2 = m_pLine - nStride;
872         line1 = (*pLine1++) << 4;
873         line2 = *pLine2++;
874         CONTEXT = (line1 & 0x1e00) | ((line2 >> 1) & 0x01f8);
875         for (cc = 0; cc < nLineBytes; cc++) {
876           line1 = (line1 << 8) | ((*pLine1++) << 4);
877           line2 = (line2 << 8) | (*pLine2++);
878           cVal = 0;
879           for (k = 7; k >= 0; k--) {
880             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
881             cVal |= bVal << k;
882             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
883                       ((line1 >> k) & 0x0200) | ((line2 >> (k + 1)) & 0x0008);
884           }
885           m_pLine[cc] = cVal;
886         }
887         line1 <<= 8;
888         line2 <<= 8;
889         cVal = 0;
890         for (k = 0; k < nBitsLeft; k++) {
891           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
892           cVal |= bVal << (7 - k);
893           CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
894                     ((line1 >> (7 - k)) & 0x0200) |
895                     ((line2 >> (8 - k)) & 0x0008);
896         }
897         m_pLine[nLineBytes] = cVal;
898       } else {
899         pLine2 = m_pLine - nStride;
900         line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
901         CONTEXT = (line2 >> 1) & 0x01f8;
902         for (cc = 0; cc < nLineBytes; cc++) {
903           if (m_loopIndex & 1) {
904             line2 = (line2 << 8) | (*pLine2++);
905           }
906           cVal = 0;
907           for (k = 7; k >= 0; k--) {
908             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
909             cVal |= bVal << k;
910             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
911                       ((line2 >> (k + 1)) & 0x0008);
912           }
913           m_pLine[cc] = cVal;
914         }
915         line2 <<= 8;
916         cVal = 0;
917         for (k = 0; k < nBitsLeft; k++) {
918           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
919           cVal |= bVal << (7 - k);
920           CONTEXT =
921               ((CONTEXT & 0x0efb) << 1) | bVal | ((line2 >> (8 - k)) & 0x0008);
922         }
923         m_pLine[nLineBytes] = cVal;
924       }
925     }
926     m_pLine += nStride;
927     if (pPause && pPause->NeedToPauseNow()) {
928       m_loopIndex++;
929       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
930       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
931     }
932   }
933   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
934   return FXCODEC_STATUS_DECODE_FINISH;
935 }
936
937 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_unopt(
938     CJBig2_Image* pImage,
939     CJBig2_ArithDecoder* pArithDecoder,
940     JBig2ArithCtx* gbContext,
941     IFX_Pause* pPause) {
942   FX_BOOL SLTP, bVal;
943   FX_DWORD CONTEXT;
944   FX_DWORD line1, line2, line3;
945   for (FX_DWORD h = 0; h < GBH; h++) {
946     if (TPGDON) {
947       SLTP = pArithDecoder->DECODE(&gbContext[0x0795]);
948       LTP = LTP ^ SLTP;
949     }
950     if (LTP == 1) {
951       pImage->copyLine(h, h - 1);
952     } else {
953       line1 = pImage->getPixel(2, h - 2);
954       line1 |= pImage->getPixel(1, h - 2) << 1;
955       line1 |= pImage->getPixel(0, h - 2) << 2;
956       line2 = pImage->getPixel(2, h - 1);
957       line2 |= pImage->getPixel(1, h - 1) << 1;
958       line2 |= pImage->getPixel(0, h - 1) << 2;
959       line3 = 0;
960       for (FX_DWORD w = 0; w < GBW; w++) {
961         if (USESKIP && SKIP->getPixel(w, h)) {
962           bVal = 0;
963         } else {
964           CONTEXT = line3;
965           CONTEXT |= pImage->getPixel(w + GBAT[0], h + GBAT[1]) << 3;
966           CONTEXT |= line2 << 4;
967           CONTEXT |= line1 << 9;
968           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
969         }
970         if (bVal) {
971           pImage->setPixel(w, h, bVal);
972         }
973         line1 = ((line1 << 1) | pImage->getPixel(w + 3, h - 2)) & 0x0f;
974         line2 = ((line2 << 1) | pImage->getPixel(w + 3, h - 1)) & 0x1f;
975         line3 = ((line3 << 1) | bVal) & 0x07;
976       }
977     }
978     if (pPause && pPause->NeedToPauseNow()) {
979       m_loopIndex++;
980       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
981       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
982     }
983   }
984   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
985   return FXCODEC_STATUS_DECODE_FINISH;
986 }
987
988 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_opt3(
989     CJBig2_Image* pImage,
990     CJBig2_ArithDecoder* pArithDecoder,
991     JBig2ArithCtx* gbContext,
992     IFX_Pause* pPause) {
993   FX_BOOL SLTP, bVal;
994   FX_DWORD CONTEXT;
995   FX_DWORD line1, line2;
996   uint8_t* pLine1, *pLine2, cVal;
997   int32_t nStride, nStride2, k;
998   int32_t nLineBytes, nBitsLeft, cc;
999   if (!m_pLine) {
1000     m_pLine = pImage->m_pData;
1001   }
1002   nStride = pImage->m_nStride;
1003   nStride2 = nStride << 1;
1004   nLineBytes = ((GBW + 7) >> 3) - 1;
1005   nBitsLeft = GBW - (nLineBytes << 3);
1006   for (; m_loopIndex < GBH; m_loopIndex++) {
1007     if (TPGDON) {
1008       SLTP = pArithDecoder->DECODE(&gbContext[0x00e5]);
1009       LTP = LTP ^ SLTP;
1010     }
1011     if (LTP == 1) {
1012       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
1013     } else {
1014       if (m_loopIndex > 1) {
1015         pLine1 = m_pLine - nStride2;
1016         pLine2 = m_pLine - nStride;
1017         line1 = (*pLine1++) << 1;
1018         line2 = *pLine2++;
1019         CONTEXT = (line1 & 0x0380) | ((line2 >> 3) & 0x007c);
1020         for (cc = 0; cc < nLineBytes; cc++) {
1021           line1 = (line1 << 8) | ((*pLine1++) << 1);
1022           line2 = (line2 << 8) | (*pLine2++);
1023           cVal = 0;
1024           for (k = 7; k >= 0; k--) {
1025             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1026             cVal |= bVal << k;
1027             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
1028                       ((line1 >> k) & 0x0080) | ((line2 >> (k + 3)) & 0x0004);
1029           }
1030           m_pLine[cc] = cVal;
1031         }
1032         line1 <<= 8;
1033         line2 <<= 8;
1034         cVal = 0;
1035         for (k = 0; k < nBitsLeft; k++) {
1036           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1037           cVal |= bVal << (7 - k);
1038           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
1039                     ((line1 >> (7 - k)) & 0x0080) |
1040                     ((line2 >> (10 - k)) & 0x0004);
1041         }
1042         m_pLine[nLineBytes] = cVal;
1043       } else {
1044         pLine2 = m_pLine - nStride;
1045         line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
1046         CONTEXT = (line2 >> 3) & 0x007c;
1047         for (cc = 0; cc < nLineBytes; cc++) {
1048           if (m_loopIndex & 1) {
1049             line2 = (line2 << 8) | (*pLine2++);
1050           }
1051           cVal = 0;
1052           for (k = 7; k >= 0; k--) {
1053             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1054             cVal |= bVal << k;
1055             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
1056                       ((line2 >> (k + 3)) & 0x0004);
1057           }
1058           m_pLine[cc] = cVal;
1059         }
1060         line2 <<= 8;
1061         cVal = 0;
1062         for (k = 0; k < nBitsLeft; k++) {
1063           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1064           cVal |= bVal << (7 - k);
1065           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
1066                     (((line2 >> (10 - k))) & 0x0004);
1067         }
1068         m_pLine[nLineBytes] = cVal;
1069       }
1070     }
1071     m_pLine += nStride;
1072     if (pPause && m_loopIndex % 50 == 0 && pPause->NeedToPauseNow()) {
1073       m_loopIndex++;
1074       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1075       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
1076     }
1077   }
1078   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
1079   return FXCODEC_STATUS_DECODE_FINISH;
1080 }
1081
1082 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_unopt(
1083     CJBig2_Image* pImage,
1084     CJBig2_ArithDecoder* pArithDecoder,
1085     JBig2ArithCtx* gbContext,
1086     IFX_Pause* pPause) {
1087   FX_BOOL SLTP, bVal;
1088   FX_DWORD CONTEXT;
1089   FX_DWORD line1, line2, line3;
1090   for (; m_loopIndex < GBH; m_loopIndex++) {
1091     if (TPGDON) {
1092       SLTP = pArithDecoder->DECODE(&gbContext[0x00e5]);
1093       LTP = LTP ^ SLTP;
1094     }
1095     if (LTP == 1) {
1096       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
1097     } else {
1098       line1 = pImage->getPixel(1, m_loopIndex - 2);
1099       line1 |= pImage->getPixel(0, m_loopIndex - 2) << 1;
1100       line2 = pImage->getPixel(1, m_loopIndex - 1);
1101       line2 |= pImage->getPixel(0, m_loopIndex - 1) << 1;
1102       line3 = 0;
1103       for (FX_DWORD w = 0; w < GBW; w++) {
1104         if (USESKIP && SKIP->getPixel(w, m_loopIndex)) {
1105           bVal = 0;
1106         } else {
1107           CONTEXT = line3;
1108           CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 2;
1109           CONTEXT |= line2 << 3;
1110           CONTEXT |= line1 << 7;
1111           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1112         }
1113         if (bVal) {
1114           pImage->setPixel(w, m_loopIndex, bVal);
1115         }
1116         line1 =
1117             ((line1 << 1) | pImage->getPixel(w + 2, m_loopIndex - 2)) & 0x07;
1118         line2 =
1119             ((line2 << 1) | pImage->getPixel(w + 2, m_loopIndex - 1)) & 0x0f;
1120         line3 = ((line3 << 1) | bVal) & 0x03;
1121       }
1122     }
1123     if (pPause && pPause->NeedToPauseNow()) {
1124       m_loopIndex++;
1125       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1126       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
1127     }
1128   }
1129   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
1130   return FXCODEC_STATUS_DECODE_FINISH;
1131 }
1132
1133 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_opt3(
1134     CJBig2_Image* pImage,
1135     CJBig2_ArithDecoder* pArithDecoder,
1136     JBig2ArithCtx* gbContext,
1137     IFX_Pause* pPause) {
1138   FX_BOOL SLTP, bVal;
1139   FX_DWORD CONTEXT;
1140   FX_DWORD line1;
1141   uint8_t* pLine1, cVal;
1142   int32_t nStride, k;
1143   int32_t nLineBytes, nBitsLeft, cc;
1144   if (!m_pLine) {
1145     m_pLine = pImage->m_pData;
1146   }
1147   nStride = pImage->m_nStride;
1148   nLineBytes = ((GBW + 7) >> 3) - 1;
1149   nBitsLeft = GBW - (nLineBytes << 3);
1150   for (; m_loopIndex < GBH; m_loopIndex++) {
1151     if (TPGDON) {
1152       SLTP = pArithDecoder->DECODE(&gbContext[0x0195]);
1153       LTP = LTP ^ SLTP;
1154     }
1155     if (LTP == 1) {
1156       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
1157     } else {
1158       if (m_loopIndex > 0) {
1159         pLine1 = m_pLine - nStride;
1160         line1 = *pLine1++;
1161         CONTEXT = (line1 >> 1) & 0x03f0;
1162         for (cc = 0; cc < nLineBytes; cc++) {
1163           line1 = (line1 << 8) | (*pLine1++);
1164           cVal = 0;
1165           for (k = 7; k >= 0; k--) {
1166             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1167             cVal |= bVal << k;
1168             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal |
1169                       ((line1 >> (k + 1)) & 0x0010);
1170           }
1171           m_pLine[cc] = cVal;
1172         }
1173         line1 <<= 8;
1174         cVal = 0;
1175         for (k = 0; k < nBitsLeft; k++) {
1176           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1177           cVal |= bVal << (7 - k);
1178           CONTEXT =
1179               ((CONTEXT & 0x01f7) << 1) | bVal | ((line1 >> (8 - k)) & 0x0010);
1180         }
1181         m_pLine[nLineBytes] = cVal;
1182       } else {
1183         CONTEXT = 0;
1184         for (cc = 0; cc < nLineBytes; cc++) {
1185           cVal = 0;
1186           for (k = 7; k >= 0; k--) {
1187             bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1188             cVal |= bVal << k;
1189             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
1190           }
1191           m_pLine[cc] = cVal;
1192         }
1193         cVal = 0;
1194         for (k = 0; k < nBitsLeft; k++) {
1195           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1196           cVal |= bVal << (7 - k);
1197           CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
1198         }
1199         m_pLine[nLineBytes] = cVal;
1200       }
1201     }
1202     m_pLine += nStride;
1203     if (pPause && pPause->NeedToPauseNow()) {
1204       m_loopIndex++;
1205       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1206       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
1207     }
1208   }
1209   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
1210   return FXCODEC_STATUS_DECODE_FINISH;
1211 }
1212
1213 FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_unopt(
1214     CJBig2_Image* pImage,
1215     CJBig2_ArithDecoder* pArithDecoder,
1216     JBig2ArithCtx* gbContext,
1217     IFX_Pause* pPause) {
1218   FX_BOOL SLTP, bVal;
1219   FX_DWORD CONTEXT;
1220   FX_DWORD line1, line2;
1221   for (; m_loopIndex < GBH; m_loopIndex++) {
1222     if (TPGDON) {
1223       SLTP = pArithDecoder->DECODE(&gbContext[0x0195]);
1224       LTP = LTP ^ SLTP;
1225     }
1226     if (LTP == 1) {
1227       pImage->copyLine(m_loopIndex, m_loopIndex - 1);
1228     } else {
1229       line1 = pImage->getPixel(1, m_loopIndex - 1);
1230       line1 |= pImage->getPixel(0, m_loopIndex - 1) << 1;
1231       line2 = 0;
1232       for (FX_DWORD w = 0; w < GBW; w++) {
1233         if (USESKIP && SKIP->getPixel(w, m_loopIndex)) {
1234           bVal = 0;
1235         } else {
1236           CONTEXT = line2;
1237           CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 4;
1238           CONTEXT |= line1 << 5;
1239           bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
1240         }
1241         if (bVal) {
1242           pImage->setPixel(w, m_loopIndex, bVal);
1243         }
1244         line1 =
1245             ((line1 << 1) | pImage->getPixel(w + 2, m_loopIndex - 1)) & 0x1f;
1246         line2 = ((line2 << 1) | bVal) & 0x0f;
1247       }
1248     }
1249     if (pPause && pPause->NeedToPauseNow()) {
1250       m_loopIndex++;
1251       m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1252       return FXCODEC_STATUS_DECODE_TOBECONTINUE;
1253     }
1254   }
1255   m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
1256   return FXCODEC_STATUS_DECODE_FINISH;
1257 }