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_TrdProc.h"
8
9#include <memory>
10
11#include "JBig2_ArithDecoder.h"
12#include "JBig2_ArithIntDecoder.h"
13#include "JBig2_GrrdProc.h"
14#include "JBig2_HuffmanDecoder.h"
15
16CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream,
17                                             JBig2ArithCtx* grContext) {
18  int32_t STRIPT, FIRSTS;
19  FX_DWORD NINSTANCES;
20  int32_t DT, DFS, CURS;
21  int32_t SI, TI;
22  CJBig2_Image* IBI;
23  FX_DWORD WI, HI;
24  int32_t IDS;
25  FX_BOOL RI;
26  int32_t RDWI, RDHI, RDXI, RDYI;
27  CJBig2_Image* IBOI;
28  FX_DWORD WOI, HOI;
29  FX_BOOL bFirst;
30  FX_DWORD nTmp;
31  int32_t nVal, nBits;
32  std::unique_ptr<CJBig2_HuffmanDecoder> pHuffmanDecoder(
33      new CJBig2_HuffmanDecoder(pStream));
34  std::unique_ptr<CJBig2_Image> SBREG(new CJBig2_Image(SBW, SBH));
35  SBREG->fill(SBDEFPIXEL);
36  if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &STRIPT) != 0)
37    return nullptr;
38
39  STRIPT *= SBSTRIPS;
40  STRIPT = -STRIPT;
41  FIRSTS = 0;
42  NINSTANCES = 0;
43  while (NINSTANCES < SBNUMINSTANCES) {
44    if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &DT) != 0)
45      return nullptr;
46
47    DT *= SBSTRIPS;
48    STRIPT = STRIPT + DT;
49    bFirst = TRUE;
50    for (;;) {
51      if (bFirst) {
52        if (pHuffmanDecoder->decodeAValue(SBHUFFFS, &DFS) != 0)
53          return nullptr;
54
55        FIRSTS = FIRSTS + DFS;
56        CURS = FIRSTS;
57        bFirst = FALSE;
58      } else {
59        nVal = pHuffmanDecoder->decodeAValue(SBHUFFDS, &IDS);
60        if (nVal == JBIG2_OOB) {
61          break;
62        } else if (nVal != 0) {
63          return nullptr;
64        } else {
65          CURS = CURS + IDS + SBDSOFFSET;
66        }
67      }
68      uint8_t CURT = 0;
69      if (SBSTRIPS != 1) {
70        nTmp = 1;
71        while ((FX_DWORD)(1 << nTmp) < SBSTRIPS) {
72          nTmp++;
73        }
74        if (pStream->readNBits(nTmp, &nVal) != 0)
75          return nullptr;
76
77        CURT = nVal;
78      }
79      TI = STRIPT + CURT;
80      nVal = 0;
81      nBits = 0;
82      FX_DWORD IDI;
83      for (;;) {
84        if (pStream->read1Bit(&nTmp) != 0)
85          return nullptr;
86
87        nVal = (nVal << 1) | nTmp;
88        nBits++;
89        for (IDI = 0; IDI < SBNUMSYMS; IDI++) {
90          if ((nBits == SBSYMCODES[IDI].codelen) &&
91              (nVal == SBSYMCODES[IDI].code)) {
92            break;
93          }
94        }
95        if (IDI < SBNUMSYMS) {
96          break;
97        }
98      }
99      if (SBREFINE == 0) {
100        RI = 0;
101      } else {
102        if (pStream->read1Bit(&RI) != 0) {
103          return nullptr;
104        }
105      }
106      if (RI == 0) {
107        IBI = SBSYMS[IDI];
108      } else {
109        if ((pHuffmanDecoder->decodeAValue(SBHUFFRDW, &RDWI) != 0) ||
110            (pHuffmanDecoder->decodeAValue(SBHUFFRDH, &RDHI) != 0) ||
111            (pHuffmanDecoder->decodeAValue(SBHUFFRDX, &RDXI) != 0) ||
112            (pHuffmanDecoder->decodeAValue(SBHUFFRDY, &RDYI) != 0) ||
113            (pHuffmanDecoder->decodeAValue(SBHUFFRSIZE, &nVal) != 0)) {
114          return nullptr;
115        }
116        pStream->alignByte();
117        nTmp = pStream->getOffset();
118        IBOI = SBSYMS[IDI];
119        if (!IBOI)
120          return nullptr;
121
122        WOI = IBOI->m_nWidth;
123        HOI = IBOI->m_nHeight;
124        if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0)
125          return nullptr;
126
127        std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
128        pGRRD->GRW = WOI + RDWI;
129        pGRRD->GRH = HOI + RDHI;
130        pGRRD->GRTEMPLATE = SBRTEMPLATE;
131        pGRRD->GRREFERENCE = IBOI;
132        pGRRD->GRREFERENCEDX = (RDWI >> 2) + RDXI;
133        pGRRD->GRREFERENCEDY = (RDHI >> 2) + RDYI;
134        pGRRD->TPGRON = 0;
135        pGRRD->GRAT[0] = SBRAT[0];
136        pGRRD->GRAT[1] = SBRAT[1];
137        pGRRD->GRAT[2] = SBRAT[2];
138        pGRRD->GRAT[3] = SBRAT[3];
139
140        {
141          std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
142              new CJBig2_ArithDecoder(pStream));
143          IBI = pGRRD->decode(pArithDecoder.get(), grContext);
144          if (!IBI)
145            return nullptr;
146        }
147
148        pStream->alignByte();
149        pStream->offset(2);
150        if ((FX_DWORD)nVal != (pStream->getOffset() - nTmp)) {
151          delete IBI;
152          return nullptr;
153        }
154      }
155      if (!IBI) {
156        continue;
157      }
158      WI = IBI->m_nWidth;
159      HI = IBI->m_nHeight;
160      if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
161                              (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
162        CURS = CURS + WI - 1;
163      } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
164                                     (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
165        CURS = CURS + HI - 1;
166      }
167      SI = CURS;
168      if (TRANSPOSED == 0) {
169        switch (REFCORNER) {
170          case JBIG2_CORNER_TOPLEFT:
171            SBREG->composeFrom(SI, TI, IBI, SBCOMBOP);
172            break;
173          case JBIG2_CORNER_TOPRIGHT:
174            SBREG->composeFrom(SI - WI + 1, TI, IBI, SBCOMBOP);
175            break;
176          case JBIG2_CORNER_BOTTOMLEFT:
177            SBREG->composeFrom(SI, TI - HI + 1, IBI, SBCOMBOP);
178            break;
179          case JBIG2_CORNER_BOTTOMRIGHT:
180            SBREG->composeFrom(SI - WI + 1, TI - HI + 1, IBI, SBCOMBOP);
181            break;
182        }
183      } else {
184        switch (REFCORNER) {
185          case JBIG2_CORNER_TOPLEFT:
186            SBREG->composeFrom(TI, SI, IBI, SBCOMBOP);
187            break;
188          case JBIG2_CORNER_TOPRIGHT:
189            SBREG->composeFrom(TI - WI + 1, SI, IBI, SBCOMBOP);
190            break;
191          case JBIG2_CORNER_BOTTOMLEFT:
192            SBREG->composeFrom(TI, SI - HI + 1, IBI, SBCOMBOP);
193            break;
194          case JBIG2_CORNER_BOTTOMRIGHT:
195            SBREG->composeFrom(TI - WI + 1, SI - HI + 1, IBI, SBCOMBOP);
196            break;
197        }
198      }
199      if (RI != 0) {
200        delete IBI;
201      }
202      if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
203                              (REFCORNER == JBIG2_CORNER_BOTTOMLEFT))) {
204        CURS = CURS + WI - 1;
205      } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
206                                     (REFCORNER == JBIG2_CORNER_TOPRIGHT))) {
207        CURS = CURS + HI - 1;
208      }
209      NINSTANCES = NINSTANCES + 1;
210    }
211  }
212  return SBREG.release();
213}
214
215CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
216                                           JBig2ArithCtx* grContext,
217                                           JBig2IntDecoderState* pIDS) {
218  int32_t STRIPT, FIRSTS;
219  FX_DWORD NINSTANCES;
220  int32_t DT, DFS, CURS;
221  int32_t SI, TI;
222  CJBig2_Image* IBI;
223  FX_DWORD WI, HI;
224  int32_t IDS;
225  int RI;
226  int32_t RDWI, RDHI, RDXI, RDYI;
227  CJBig2_Image* IBOI;
228  FX_DWORD WOI, HOI;
229  FX_BOOL bFirst;
230  int32_t bRetained;
231  CJBig2_ArithIntDecoder* IADT, *IAFS, *IADS, *IAIT, *IARI, *IARDW, *IARDH,
232      *IARDX, *IARDY;
233  CJBig2_ArithIaidDecoder* IAID;
234  if (pIDS) {
235    IADT = pIDS->IADT;
236    IAFS = pIDS->IAFS;
237    IADS = pIDS->IADS;
238    IAIT = pIDS->IAIT;
239    IARI = pIDS->IARI;
240    IARDW = pIDS->IARDW;
241    IARDH = pIDS->IARDH;
242    IARDX = pIDS->IARDX;
243    IARDY = pIDS->IARDY;
244    IAID = pIDS->IAID;
245    bRetained = TRUE;
246  } else {
247    IADT = new CJBig2_ArithIntDecoder();
248    IAFS = new CJBig2_ArithIntDecoder();
249    IADS = new CJBig2_ArithIntDecoder();
250    IAIT = new CJBig2_ArithIntDecoder();
251    IARI = new CJBig2_ArithIntDecoder();
252    IARDW = new CJBig2_ArithIntDecoder();
253    IARDH = new CJBig2_ArithIntDecoder();
254    IARDX = new CJBig2_ArithIntDecoder();
255    IARDY = new CJBig2_ArithIntDecoder();
256    IAID = new CJBig2_ArithIaidDecoder(SBSYMCODELEN);
257    bRetained = FALSE;
258  }
259  std::unique_ptr<CJBig2_Image> SBREG(new CJBig2_Image(SBW, SBH));
260  SBREG->fill(SBDEFPIXEL);
261  IADT->decode(pArithDecoder, &STRIPT);
262  STRIPT *= SBSTRIPS;
263  STRIPT = -STRIPT;
264  FIRSTS = 0;
265  NINSTANCES = 0;
266  while (NINSTANCES < SBNUMINSTANCES) {
267    IADT->decode(pArithDecoder, &DT);
268    DT *= SBSTRIPS;
269    STRIPT = STRIPT + DT;
270    bFirst = TRUE;
271    for (;;) {
272      if (bFirst) {
273        IAFS->decode(pArithDecoder, &DFS);
274        FIRSTS = FIRSTS + DFS;
275        CURS = FIRSTS;
276        bFirst = FALSE;
277      } else {
278        if (!IADS->decode(pArithDecoder, &IDS))
279          break;
280        CURS = CURS + IDS + SBDSOFFSET;
281      }
282      if (NINSTANCES >= SBNUMINSTANCES) {
283        break;
284      }
285      int CURT = 0;
286      if (SBSTRIPS != 1)
287        IAIT->decode(pArithDecoder, &CURT);
288
289      TI = STRIPT + CURT;
290      FX_DWORD IDI;
291      IAID->decode(pArithDecoder, &IDI);
292      if (IDI >= SBNUMSYMS)
293        goto failed;
294
295      if (SBREFINE == 0)
296        RI = 0;
297      else
298        IARI->decode(pArithDecoder, &RI);
299
300      if (!SBSYMS[IDI])
301        goto failed;
302
303      if (RI == 0) {
304        IBI = SBSYMS[IDI];
305      } else {
306        IARDW->decode(pArithDecoder, &RDWI);
307        IARDH->decode(pArithDecoder, &RDHI);
308        IARDX->decode(pArithDecoder, &RDXI);
309        IARDY->decode(pArithDecoder, &RDYI);
310        IBOI = SBSYMS[IDI];
311        WOI = IBOI->m_nWidth;
312        HOI = IBOI->m_nHeight;
313        if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0) {
314          goto failed;
315        }
316        std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
317        pGRRD->GRW = WOI + RDWI;
318        pGRRD->GRH = HOI + RDHI;
319        pGRRD->GRTEMPLATE = SBRTEMPLATE;
320        pGRRD->GRREFERENCE = IBOI;
321        pGRRD->GRREFERENCEDX = (RDWI >> 1) + RDXI;
322        pGRRD->GRREFERENCEDY = (RDHI >> 1) + RDYI;
323        pGRRD->TPGRON = 0;
324        pGRRD->GRAT[0] = SBRAT[0];
325        pGRRD->GRAT[1] = SBRAT[1];
326        pGRRD->GRAT[2] = SBRAT[2];
327        pGRRD->GRAT[3] = SBRAT[3];
328        IBI = pGRRD->decode(pArithDecoder, grContext);
329        if (!IBI)
330          goto failed;
331      }
332      WI = IBI->m_nWidth;
333      HI = IBI->m_nHeight;
334      if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
335                              (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
336        CURS = CURS + WI - 1;
337      } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
338                                     (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
339        CURS = CURS + HI - 1;
340      }
341      SI = CURS;
342      if (TRANSPOSED == 0) {
343        switch (REFCORNER) {
344          case JBIG2_CORNER_TOPLEFT:
345            SBREG->composeFrom(SI, TI, IBI, SBCOMBOP);
346            break;
347          case JBIG2_CORNER_TOPRIGHT:
348            SBREG->composeFrom(SI - WI + 1, TI, IBI, SBCOMBOP);
349            break;
350          case JBIG2_CORNER_BOTTOMLEFT:
351            SBREG->composeFrom(SI, TI - HI + 1, IBI, SBCOMBOP);
352            break;
353          case JBIG2_CORNER_BOTTOMRIGHT:
354            SBREG->composeFrom(SI - WI + 1, TI - HI + 1, IBI, SBCOMBOP);
355            break;
356        }
357      } else {
358        switch (REFCORNER) {
359          case JBIG2_CORNER_TOPLEFT:
360            SBREG->composeFrom(TI, SI, IBI, SBCOMBOP);
361            break;
362          case JBIG2_CORNER_TOPRIGHT:
363            SBREG->composeFrom(TI - WI + 1, SI, IBI, SBCOMBOP);
364            break;
365          case JBIG2_CORNER_BOTTOMLEFT:
366            SBREG->composeFrom(TI, SI - HI + 1, IBI, SBCOMBOP);
367            break;
368          case JBIG2_CORNER_BOTTOMRIGHT:
369            SBREG->composeFrom(TI - WI + 1, SI - HI + 1, IBI, SBCOMBOP);
370            break;
371        }
372      }
373      if (RI != 0) {
374        delete IBI;
375      }
376      if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
377                              (REFCORNER == JBIG2_CORNER_BOTTOMLEFT))) {
378        CURS = CURS + WI - 1;
379      } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
380                                     (REFCORNER == JBIG2_CORNER_TOPRIGHT))) {
381        CURS = CURS + HI - 1;
382      }
383      NINSTANCES = NINSTANCES + 1;
384    }
385  }
386  if (bRetained == FALSE) {
387    delete IADT;
388    delete IAFS;
389    delete IADS;
390    delete IAIT;
391    delete IARI;
392    delete IARDW;
393    delete IARDH;
394    delete IARDX;
395    delete IARDY;
396    delete IAID;
397  }
398  return SBREG.release();
399failed:
400  if (bRetained == FALSE) {
401    delete IADT;
402    delete IAFS;
403    delete IADS;
404    delete IAIT;
405    delete IARI;
406    delete IARDW;
407    delete IARDH;
408    delete IARDX;
409    delete IARDY;
410    delete IAID;
411  }
412  return nullptr;
413}
414