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 18CJBig2_TRDProc::CJBig2_TRDProc() {} 19 20CJBig2_TRDProc::~CJBig2_TRDProc() {} 21 22std::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 223std::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