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