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