1 // Copyright 2014 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_Image.h" 8 9 #include <limits.h> 10 11 #include <algorithm> 12 #include <memory> 13 14 #include "core/fxcrt/fx_coordinates.h" 15 #include "core/fxcrt/fx_memory.h" 16 #include "core/fxcrt/fx_safe_types.h" 17 #include "third_party/base/ptr_util.h" 18 19 namespace { 20 21 const int kMaxImagePixels = INT_MAX - 31; 22 const int kMaxImageBytes = kMaxImagePixels / 8; 23 24 } // namespace 25 26 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h) 27 : m_pData(nullptr), m_nWidth(0), m_nHeight(0), m_nStride(0) { 28 if (w <= 0 || h <= 0 || w > kMaxImagePixels) 29 return; 30 31 int32_t stride_pixels = (w + 31) & ~31; 32 if (h > kMaxImagePixels / stride_pixels) 33 return; 34 35 m_nWidth = w; 36 m_nHeight = h; 37 m_nStride = stride_pixels / 8; 38 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>( 39 FX_Alloc2D(uint8_t, m_nStride, m_nHeight))); 40 } 41 42 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h, int32_t stride, uint8_t* pBuf) 43 : m_pData(nullptr), m_nWidth(0), m_nHeight(0), m_nStride(0) { 44 if (w < 0 || h < 0 || stride < 0 || stride > kMaxImageBytes) 45 return; 46 47 int32_t stride_pixels = 8 * stride; 48 if (stride_pixels < w || h > kMaxImagePixels / stride_pixels) 49 return; 50 51 m_nWidth = w; 52 m_nHeight = h; 53 m_nStride = stride; 54 m_pData.Reset(pBuf); 55 } 56 57 CJBig2_Image::CJBig2_Image(const CJBig2_Image& other) 58 : m_pData(nullptr), 59 m_nWidth(other.m_nWidth), 60 m_nHeight(other.m_nHeight), 61 m_nStride(other.m_nStride) { 62 if (other.m_pData) { 63 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>( 64 FX_Alloc2D(uint8_t, m_nStride, m_nHeight))); 65 JBIG2_memcpy(data(), other.data(), m_nStride * m_nHeight); 66 } 67 } 68 69 CJBig2_Image::~CJBig2_Image() {} 70 71 int CJBig2_Image::getPixel(int32_t x, int32_t y) const { 72 if (!m_pData) 73 return 0; 74 75 if (x < 0 || x >= m_nWidth) 76 return 0; 77 78 if (y < 0 || y >= m_nHeight) 79 return 0; 80 81 int32_t m = y * m_nStride + (x >> 3); 82 int32_t n = x & 7; 83 return ((data()[m] >> (7 - n)) & 1); 84 } 85 86 int32_t CJBig2_Image::setPixel(int32_t x, int32_t y, int v) { 87 if (!m_pData) 88 return 0; 89 90 if (x < 0 || x >= m_nWidth) 91 return 0; 92 93 if (y < 0 || y >= m_nHeight) 94 return 0; 95 96 int32_t m = y * m_nStride + (x >> 3); 97 int32_t n = x & 7; 98 if (v) 99 data()[m] |= 1 << (7 - n); 100 else 101 data()[m] &= ~(1 << (7 - n)); 102 103 return 1; 104 } 105 106 void CJBig2_Image::copyLine(int32_t hTo, int32_t hFrom) { 107 if (!m_pData) 108 return; 109 110 if (hFrom < 0 || hFrom >= m_nHeight) { 111 JBIG2_memset(data() + hTo * m_nStride, 0, m_nStride); 112 } else { 113 JBIG2_memcpy(data() + hTo * m_nStride, data() + hFrom * m_nStride, 114 m_nStride); 115 } 116 } 117 void CJBig2_Image::fill(bool v) { 118 if (!m_pData) 119 return; 120 121 JBIG2_memset(data(), v ? 0xff : 0, m_nStride * m_nHeight); 122 } 123 bool CJBig2_Image::composeTo(CJBig2_Image* pDst, 124 int32_t x, 125 int32_t y, 126 JBig2ComposeOp op) { 127 if (!m_pData) 128 return false; 129 130 return composeTo_opt2(pDst, x, y, op); 131 } 132 bool CJBig2_Image::composeTo(CJBig2_Image* pDst, 133 int32_t x, 134 int32_t y, 135 JBig2ComposeOp op, 136 const FX_RECT* pSrcRect) { 137 if (!m_pData) 138 return false; 139 140 if (!pSrcRect || *pSrcRect == FX_RECT(0, 0, m_nWidth, m_nHeight)) 141 return composeTo_opt2(pDst, x, y, op); 142 143 return composeTo_opt2(pDst, x, y, op, pSrcRect); 144 } 145 146 bool CJBig2_Image::composeFrom(int32_t x, 147 int32_t y, 148 CJBig2_Image* pSrc, 149 JBig2ComposeOp op) { 150 if (!m_pData) 151 return false; 152 153 return pSrc->composeTo(this, x, y, op); 154 } 155 bool CJBig2_Image::composeFrom(int32_t x, 156 int32_t y, 157 CJBig2_Image* pSrc, 158 JBig2ComposeOp op, 159 const FX_RECT* pSrcRect) { 160 return m_pData ? pSrc->composeTo(this, x, y, op, pSrcRect) : false; 161 } 162 163 #define JBIG2_GETDWORD(buf) \ 164 ((uint32_t)(((buf)[0] << 24) | ((buf)[1] << 16) | ((buf)[2] << 8) | (buf)[3])) 165 166 std::unique_ptr<CJBig2_Image> CJBig2_Image::subImage(int32_t x, 167 int32_t y, 168 int32_t w, 169 int32_t h) { 170 int32_t m; 171 int32_t n; 172 int32_t j; 173 uint8_t* pLineSrc; 174 uint8_t* pLineDst; 175 uint32_t wTmp; 176 uint8_t* pSrc; 177 uint8_t* pSrcEnd; 178 uint8_t* pDst; 179 uint8_t* pDstEnd; 180 if (w == 0 || h == 0) 181 return nullptr; 182 183 auto pImage = pdfium::MakeUnique<CJBig2_Image>(w, h); 184 if (!m_pData) { 185 pImage->fill(0); 186 return pImage; 187 } 188 if (!pImage->m_pData) 189 return pImage; 190 191 pLineSrc = data() + m_nStride * y; 192 pLineDst = pImage->data(); 193 m = (x >> 5) << 2; 194 n = x & 31; 195 if (n == 0) { 196 for (j = 0; j < h; j++) { 197 pSrc = pLineSrc + m; 198 pSrcEnd = pLineSrc + m_nStride; 199 pDst = pLineDst; 200 pDstEnd = pLineDst + pImage->m_nStride; 201 for (; pDst < pDstEnd; pSrc += 4, pDst += 4) { 202 *((uint32_t*)pDst) = *((uint32_t*)pSrc); 203 } 204 pLineSrc += m_nStride; 205 pLineDst += pImage->m_nStride; 206 } 207 } else { 208 for (j = 0; j < h; j++) { 209 pSrc = pLineSrc + m; 210 pSrcEnd = pLineSrc + m_nStride; 211 pDst = pLineDst; 212 pDstEnd = pLineDst + pImage->m_nStride; 213 for (; pDst < pDstEnd; pSrc += 4, pDst += 4) { 214 if (pSrc + 4 < pSrcEnd) { 215 wTmp = (JBIG2_GETDWORD(pSrc) << n) | 216 (JBIG2_GETDWORD(pSrc + 4) >> (32 - n)); 217 } else { 218 wTmp = JBIG2_GETDWORD(pSrc) << n; 219 } 220 pDst[0] = (uint8_t)(wTmp >> 24); 221 pDst[1] = (uint8_t)(wTmp >> 16); 222 pDst[2] = (uint8_t)(wTmp >> 8); 223 pDst[3] = (uint8_t)wTmp; 224 } 225 pLineSrc += m_nStride; 226 pLineDst += pImage->m_nStride; 227 } 228 } 229 return pImage; 230 } 231 232 void CJBig2_Image::expand(int32_t h, bool v) { 233 if (!m_pData || h <= m_nHeight || h > kMaxImageBytes / m_nStride) 234 return; 235 236 if (m_pData.IsOwned()) { 237 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>( 238 FX_Realloc(uint8_t, m_pData.Release().release(), h * m_nStride))); 239 } else { 240 uint8_t* pExternalBuffer = data(); 241 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>( 242 FX_Alloc(uint8_t, h * m_nStride))); 243 JBIG2_memcpy(data(), pExternalBuffer, m_nHeight * m_nStride); 244 } 245 JBIG2_memset(data() + m_nHeight * m_nStride, v ? 0xff : 0, 246 (h - m_nHeight) * m_nStride); 247 m_nHeight = h; 248 } 249 250 bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, 251 int32_t x, 252 int32_t y, 253 JBig2ComposeOp op) { 254 if (!m_pData) 255 return false; 256 257 if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) 258 return false; 259 260 int32_t xs0 = x < 0 ? -x : 0; 261 int32_t xs1; 262 FX_SAFE_INT32 iChecked = pDst->m_nWidth; 263 iChecked -= x; 264 if (iChecked.IsValid() && m_nWidth > iChecked.ValueOrDie()) 265 xs1 = iChecked.ValueOrDie(); 266 else 267 xs1 = m_nWidth; 268 269 int32_t ys0 = y < 0 ? -y : 0; 270 int32_t ys1; 271 iChecked = pDst->m_nHeight; 272 iChecked -= y; 273 if (iChecked.IsValid() && m_nHeight > iChecked.ValueOrDie()) 274 ys1 = pDst->m_nHeight - y; 275 else 276 ys1 = m_nHeight; 277 278 if (ys0 >= ys1 || xs0 >= xs1) 279 return false; 280 281 int32_t xd0 = std::max(x, 0); 282 int32_t yd0 = std::max(y, 0); 283 int32_t w = xs1 - xs0; 284 int32_t h = ys1 - ys0; 285 int32_t xd1 = xd0 + w; 286 int32_t yd1 = yd0 + h; 287 uint32_t d1 = xd0 & 31; 288 uint32_t d2 = xd1 & 31; 289 uint32_t s1 = xs0 & 31; 290 uint32_t maskL = 0xffffffff >> d1; 291 uint32_t maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32); 292 uint32_t maskM = maskL & maskR; 293 uint8_t* lineSrc = data() + ys0 * m_nStride + ((xs0 >> 5) << 2); 294 int32_t lineLeft = m_nStride - ((xs0 >> 5) << 2); 295 uint8_t* lineDst = pDst->data() + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2); 296 if ((xd0 & ~31) == ((xd1 - 1) & ~31)) { 297 if ((xs0 & ~31) == ((xs1 - 1) & ~31)) { 298 if (s1 > d1) { 299 uint32_t shift = s1 - d1; 300 for (int32_t yy = yd0; yy < yd1; yy++) { 301 uint32_t tmp1 = JBIG2_GETDWORD(lineSrc) << shift; 302 uint32_t tmp2 = JBIG2_GETDWORD(lineDst); 303 uint32_t tmp = 0; 304 switch (op) { 305 case JBIG2_COMPOSE_OR: 306 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM); 307 break; 308 case JBIG2_COMPOSE_AND: 309 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM); 310 break; 311 case JBIG2_COMPOSE_XOR: 312 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM); 313 break; 314 case JBIG2_COMPOSE_XNOR: 315 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM); 316 break; 317 case JBIG2_COMPOSE_REPLACE: 318 tmp = (tmp2 & ~maskM) | (tmp1 & maskM); 319 break; 320 } 321 lineDst[0] = (uint8_t)(tmp >> 24); 322 lineDst[1] = (uint8_t)(tmp >> 16); 323 lineDst[2] = (uint8_t)(tmp >> 8); 324 lineDst[3] = (uint8_t)tmp; 325 lineSrc += m_nStride; 326 lineDst += pDst->m_nStride; 327 } 328 } else { 329 uint32_t shift = d1 - s1; 330 for (int32_t yy = yd0; yy < yd1; yy++) { 331 uint32_t tmp1 = JBIG2_GETDWORD(lineSrc) >> shift; 332 uint32_t tmp2 = JBIG2_GETDWORD(lineDst); 333 uint32_t tmp = 0; 334 switch (op) { 335 case JBIG2_COMPOSE_OR: 336 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM); 337 break; 338 case JBIG2_COMPOSE_AND: 339 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM); 340 break; 341 case JBIG2_COMPOSE_XOR: 342 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM); 343 break; 344 case JBIG2_COMPOSE_XNOR: 345 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM); 346 break; 347 case JBIG2_COMPOSE_REPLACE: 348 tmp = (tmp2 & ~maskM) | (tmp1 & maskM); 349 break; 350 } 351 lineDst[0] = (uint8_t)(tmp >> 24); 352 lineDst[1] = (uint8_t)(tmp >> 16); 353 lineDst[2] = (uint8_t)(tmp >> 8); 354 lineDst[3] = (uint8_t)tmp; 355 lineSrc += m_nStride; 356 lineDst += pDst->m_nStride; 357 } 358 } 359 } else { 360 uint32_t shift1 = s1 - d1; 361 uint32_t shift2 = 32 - shift1; 362 for (int32_t yy = yd0; yy < yd1; yy++) { 363 uint32_t tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) | 364 (JBIG2_GETDWORD(lineSrc + 4) >> shift2); 365 uint32_t tmp2 = JBIG2_GETDWORD(lineDst); 366 uint32_t tmp = 0; 367 switch (op) { 368 case JBIG2_COMPOSE_OR: 369 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM); 370 break; 371 case JBIG2_COMPOSE_AND: 372 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM); 373 break; 374 case JBIG2_COMPOSE_XOR: 375 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM); 376 break; 377 case JBIG2_COMPOSE_XNOR: 378 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM); 379 break; 380 case JBIG2_COMPOSE_REPLACE: 381 tmp = (tmp2 & ~maskM) | (tmp1 & maskM); 382 break; 383 } 384 lineDst[0] = (uint8_t)(tmp >> 24); 385 lineDst[1] = (uint8_t)(tmp >> 16); 386 lineDst[2] = (uint8_t)(tmp >> 8); 387 lineDst[3] = (uint8_t)tmp; 388 lineSrc += m_nStride; 389 lineDst += pDst->m_nStride; 390 } 391 } 392 } else { 393 uint8_t* sp = nullptr; 394 uint8_t* dp = nullptr; 395 396 if (s1 > d1) { 397 uint32_t shift1 = s1 - d1; 398 uint32_t shift2 = 32 - shift1; 399 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); 400 for (int32_t yy = yd0; yy < yd1; yy++) { 401 sp = lineSrc; 402 dp = lineDst; 403 if (d1 != 0) { 404 uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift1) | 405 (JBIG2_GETDWORD(sp + 4) >> shift2); 406 uint32_t tmp2 = JBIG2_GETDWORD(dp); 407 uint32_t tmp = 0; 408 switch (op) { 409 case JBIG2_COMPOSE_OR: 410 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL); 411 break; 412 case JBIG2_COMPOSE_AND: 413 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL); 414 break; 415 case JBIG2_COMPOSE_XOR: 416 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL); 417 break; 418 case JBIG2_COMPOSE_XNOR: 419 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL); 420 break; 421 case JBIG2_COMPOSE_REPLACE: 422 tmp = (tmp2 & ~maskL) | (tmp1 & maskL); 423 break; 424 } 425 dp[0] = (uint8_t)(tmp >> 24); 426 dp[1] = (uint8_t)(tmp >> 16); 427 dp[2] = (uint8_t)(tmp >> 8); 428 dp[3] = (uint8_t)tmp; 429 sp += 4; 430 dp += 4; 431 } 432 for (int32_t xx = 0; xx < middleDwords; xx++) { 433 uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift1) | 434 (JBIG2_GETDWORD(sp + 4) >> shift2); 435 uint32_t tmp2 = JBIG2_GETDWORD(dp); 436 uint32_t tmp = 0; 437 switch (op) { 438 case JBIG2_COMPOSE_OR: 439 tmp = tmp1 | tmp2; 440 break; 441 case JBIG2_COMPOSE_AND: 442 tmp = tmp1 & tmp2; 443 break; 444 case JBIG2_COMPOSE_XOR: 445 tmp = tmp1 ^ tmp2; 446 break; 447 case JBIG2_COMPOSE_XNOR: 448 tmp = ~(tmp1 ^ tmp2); 449 break; 450 case JBIG2_COMPOSE_REPLACE: 451 tmp = tmp1; 452 break; 453 } 454 dp[0] = (uint8_t)(tmp >> 24); 455 dp[1] = (uint8_t)(tmp >> 16); 456 dp[2] = (uint8_t)(tmp >> 8); 457 dp[3] = (uint8_t)tmp; 458 sp += 4; 459 dp += 4; 460 } 461 if (d2 != 0) { 462 uint32_t tmp1 = 463 (JBIG2_GETDWORD(sp) << shift1) | 464 (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> 465 shift2); 466 uint32_t tmp2 = JBIG2_GETDWORD(dp); 467 uint32_t tmp = 0; 468 switch (op) { 469 case JBIG2_COMPOSE_OR: 470 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR); 471 break; 472 case JBIG2_COMPOSE_AND: 473 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR); 474 break; 475 case JBIG2_COMPOSE_XOR: 476 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR); 477 break; 478 case JBIG2_COMPOSE_XNOR: 479 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR); 480 break; 481 case JBIG2_COMPOSE_REPLACE: 482 tmp = (tmp2 & ~maskR) | (tmp1 & maskR); 483 break; 484 } 485 dp[0] = (uint8_t)(tmp >> 24); 486 dp[1] = (uint8_t)(tmp >> 16); 487 dp[2] = (uint8_t)(tmp >> 8); 488 dp[3] = (uint8_t)tmp; 489 } 490 lineSrc += m_nStride; 491 lineDst += pDst->m_nStride; 492 } 493 } else if (s1 == d1) { 494 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); 495 for (int32_t yy = yd0; yy < yd1; yy++) { 496 sp = lineSrc; 497 dp = lineDst; 498 if (d1 != 0) { 499 uint32_t tmp1 = JBIG2_GETDWORD(sp); 500 uint32_t tmp2 = JBIG2_GETDWORD(dp); 501 uint32_t tmp = 0; 502 switch (op) { 503 case JBIG2_COMPOSE_OR: 504 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL); 505 break; 506 case JBIG2_COMPOSE_AND: 507 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL); 508 break; 509 case JBIG2_COMPOSE_XOR: 510 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL); 511 break; 512 case JBIG2_COMPOSE_XNOR: 513 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL); 514 break; 515 case JBIG2_COMPOSE_REPLACE: 516 tmp = (tmp2 & ~maskL) | (tmp1 & maskL); 517 break; 518 } 519 dp[0] = (uint8_t)(tmp >> 24); 520 dp[1] = (uint8_t)(tmp >> 16); 521 dp[2] = (uint8_t)(tmp >> 8); 522 dp[3] = (uint8_t)tmp; 523 sp += 4; 524 dp += 4; 525 } 526 for (int32_t xx = 0; xx < middleDwords; xx++) { 527 uint32_t tmp1 = JBIG2_GETDWORD(sp); 528 uint32_t tmp2 = JBIG2_GETDWORD(dp); 529 uint32_t tmp = 0; 530 switch (op) { 531 case JBIG2_COMPOSE_OR: 532 tmp = tmp1 | tmp2; 533 break; 534 case JBIG2_COMPOSE_AND: 535 tmp = tmp1 & tmp2; 536 break; 537 case JBIG2_COMPOSE_XOR: 538 tmp = tmp1 ^ tmp2; 539 break; 540 case JBIG2_COMPOSE_XNOR: 541 tmp = ~(tmp1 ^ tmp2); 542 break; 543 case JBIG2_COMPOSE_REPLACE: 544 tmp = tmp1; 545 break; 546 } 547 dp[0] = (uint8_t)(tmp >> 24); 548 dp[1] = (uint8_t)(tmp >> 16); 549 dp[2] = (uint8_t)(tmp >> 8); 550 dp[3] = (uint8_t)tmp; 551 sp += 4; 552 dp += 4; 553 } 554 if (d2 != 0) { 555 uint32_t tmp1 = JBIG2_GETDWORD(sp); 556 uint32_t tmp2 = JBIG2_GETDWORD(dp); 557 uint32_t tmp = 0; 558 switch (op) { 559 case JBIG2_COMPOSE_OR: 560 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR); 561 break; 562 case JBIG2_COMPOSE_AND: 563 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR); 564 break; 565 case JBIG2_COMPOSE_XOR: 566 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR); 567 break; 568 case JBIG2_COMPOSE_XNOR: 569 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR); 570 break; 571 case JBIG2_COMPOSE_REPLACE: 572 tmp = (tmp2 & ~maskR) | (tmp1 & maskR); 573 break; 574 } 575 dp[0] = (uint8_t)(tmp >> 24); 576 dp[1] = (uint8_t)(tmp >> 16); 577 dp[2] = (uint8_t)(tmp >> 8); 578 dp[3] = (uint8_t)tmp; 579 } 580 lineSrc += m_nStride; 581 lineDst += pDst->m_nStride; 582 } 583 } else { 584 uint32_t shift1 = d1 - s1; 585 uint32_t shift2 = 32 - shift1; 586 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); 587 for (int32_t yy = yd0; yy < yd1; yy++) { 588 sp = lineSrc; 589 dp = lineDst; 590 if (d1 != 0) { 591 uint32_t tmp1 = JBIG2_GETDWORD(sp) >> shift1; 592 uint32_t tmp2 = JBIG2_GETDWORD(dp); 593 uint32_t tmp = 0; 594 switch (op) { 595 case JBIG2_COMPOSE_OR: 596 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL); 597 break; 598 case JBIG2_COMPOSE_AND: 599 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL); 600 break; 601 case JBIG2_COMPOSE_XOR: 602 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL); 603 break; 604 case JBIG2_COMPOSE_XNOR: 605 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL); 606 break; 607 case JBIG2_COMPOSE_REPLACE: 608 tmp = (tmp2 & ~maskL) | (tmp1 & maskL); 609 break; 610 } 611 dp[0] = (uint8_t)(tmp >> 24); 612 dp[1] = (uint8_t)(tmp >> 16); 613 dp[2] = (uint8_t)(tmp >> 8); 614 dp[3] = (uint8_t)tmp; 615 dp += 4; 616 } 617 for (int32_t xx = 0; xx < middleDwords; xx++) { 618 uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift2) | 619 ((JBIG2_GETDWORD(sp + 4)) >> shift1); 620 uint32_t tmp2 = JBIG2_GETDWORD(dp); 621 uint32_t tmp = 0; 622 switch (op) { 623 case JBIG2_COMPOSE_OR: 624 tmp = tmp1 | tmp2; 625 break; 626 case JBIG2_COMPOSE_AND: 627 tmp = tmp1 & tmp2; 628 break; 629 case JBIG2_COMPOSE_XOR: 630 tmp = tmp1 ^ tmp2; 631 break; 632 case JBIG2_COMPOSE_XNOR: 633 tmp = ~(tmp1 ^ tmp2); 634 break; 635 case JBIG2_COMPOSE_REPLACE: 636 tmp = tmp1; 637 break; 638 } 639 dp[0] = (uint8_t)(tmp >> 24); 640 dp[1] = (uint8_t)(tmp >> 16); 641 dp[2] = (uint8_t)(tmp >> 8); 642 dp[3] = (uint8_t)tmp; 643 sp += 4; 644 dp += 4; 645 } 646 if (d2 != 0) { 647 uint32_t tmp1 = 648 (JBIG2_GETDWORD(sp) << shift2) | 649 (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> 650 shift1); 651 uint32_t tmp2 = JBIG2_GETDWORD(dp); 652 uint32_t tmp = 0; 653 switch (op) { 654 case JBIG2_COMPOSE_OR: 655 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR); 656 break; 657 case JBIG2_COMPOSE_AND: 658 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR); 659 break; 660 case JBIG2_COMPOSE_XOR: 661 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR); 662 break; 663 case JBIG2_COMPOSE_XNOR: 664 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR); 665 break; 666 case JBIG2_COMPOSE_REPLACE: 667 tmp = (tmp2 & ~maskR) | (tmp1 & maskR); 668 break; 669 } 670 dp[0] = (uint8_t)(tmp >> 24); 671 dp[1] = (uint8_t)(tmp >> 16); 672 dp[2] = (uint8_t)(tmp >> 8); 673 dp[3] = (uint8_t)tmp; 674 } 675 lineSrc += m_nStride; 676 lineDst += pDst->m_nStride; 677 } 678 } 679 } 680 return true; 681 } 682 683 bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, 684 int32_t x, 685 int32_t y, 686 JBig2ComposeOp op, 687 const FX_RECT* pSrcRect) { 688 if (!m_pData) 689 return false; 690 691 // TODO(weili): Check whether the range check is correct. Should x>=1048576? 692 if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) { 693 return false; 694 } 695 int32_t sw = pSrcRect->Width(); 696 int32_t sh = pSrcRect->Height(); 697 int32_t ys0 = y < 0 ? -y : 0; 698 int32_t ys1 = y + sh > pDst->m_nHeight ? pDst->m_nHeight - y : sh; 699 int32_t xs0 = x < 0 ? -x : 0; 700 int32_t xs1 = x + sw > pDst->m_nWidth ? pDst->m_nWidth - x : sw; 701 if ((ys0 >= ys1) || (xs0 >= xs1)) { 702 return 0; 703 } 704 int32_t w = xs1 - xs0; 705 int32_t h = ys1 - ys0; 706 int32_t yd0 = y < 0 ? 0 : y; 707 int32_t xd0 = x < 0 ? 0 : x; 708 int32_t xd1 = xd0 + w; 709 int32_t yd1 = yd0 + h; 710 int32_t d1 = xd0 & 31; 711 int32_t d2 = xd1 & 31; 712 int32_t s1 = xs0 & 31; 713 int32_t maskL = 0xffffffff >> d1; 714 int32_t maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32); 715 int32_t maskM = maskL & maskR; 716 uint8_t* lineSrc = data() + (pSrcRect->top + ys0) * m_nStride + 717 (((xs0 + pSrcRect->left) >> 5) << 2); 718 int32_t lineLeft = m_nStride - ((xs0 >> 5) << 2); 719 uint8_t* lineDst = pDst->data() + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2); 720 if ((xd0 & ~31) == ((xd1 - 1) & ~31)) { 721 if ((xs0 & ~31) == ((xs1 - 1) & ~31)) { 722 if (s1 > d1) { 723 uint32_t shift = s1 - d1; 724 for (int32_t yy = yd0; yy < yd1; yy++) { 725 uint32_t tmp1 = JBIG2_GETDWORD(lineSrc) << shift; 726 uint32_t tmp2 = JBIG2_GETDWORD(lineDst); 727 uint32_t tmp = 0; 728 switch (op) { 729 case JBIG2_COMPOSE_OR: 730 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM); 731 break; 732 case JBIG2_COMPOSE_AND: 733 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM); 734 break; 735 case JBIG2_COMPOSE_XOR: 736 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM); 737 break; 738 case JBIG2_COMPOSE_XNOR: 739 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM); 740 break; 741 case JBIG2_COMPOSE_REPLACE: 742 tmp = (tmp2 & ~maskM) | (tmp1 & maskM); 743 break; 744 } 745 lineDst[0] = (uint8_t)(tmp >> 24); 746 lineDst[1] = (uint8_t)(tmp >> 16); 747 lineDst[2] = (uint8_t)(tmp >> 8); 748 lineDst[3] = (uint8_t)tmp; 749 lineSrc += m_nStride; 750 lineDst += pDst->m_nStride; 751 } 752 } else { 753 uint32_t shift = d1 - s1; 754 for (int32_t yy = yd0; yy < yd1; yy++) { 755 uint32_t tmp1 = JBIG2_GETDWORD(lineSrc) >> shift; 756 uint32_t tmp2 = JBIG2_GETDWORD(lineDst); 757 uint32_t tmp = 0; 758 switch (op) { 759 case JBIG2_COMPOSE_OR: 760 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM); 761 break; 762 case JBIG2_COMPOSE_AND: 763 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM); 764 break; 765 case JBIG2_COMPOSE_XOR: 766 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM); 767 break; 768 case JBIG2_COMPOSE_XNOR: 769 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM); 770 break; 771 case JBIG2_COMPOSE_REPLACE: 772 tmp = (tmp2 & ~maskM) | (tmp1 & maskM); 773 break; 774 } 775 lineDst[0] = (uint8_t)(tmp >> 24); 776 lineDst[1] = (uint8_t)(tmp >> 16); 777 lineDst[2] = (uint8_t)(tmp >> 8); 778 lineDst[3] = (uint8_t)tmp; 779 lineSrc += m_nStride; 780 lineDst += pDst->m_nStride; 781 } 782 } 783 } else { 784 uint32_t shift1 = s1 - d1; 785 uint32_t shift2 = 32 - shift1; 786 for (int32_t yy = yd0; yy < yd1; yy++) { 787 uint32_t tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) | 788 (JBIG2_GETDWORD(lineSrc + 4) >> shift2); 789 uint32_t tmp2 = JBIG2_GETDWORD(lineDst); 790 uint32_t tmp = 0; 791 switch (op) { 792 case JBIG2_COMPOSE_OR: 793 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM); 794 break; 795 case JBIG2_COMPOSE_AND: 796 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM); 797 break; 798 case JBIG2_COMPOSE_XOR: 799 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM); 800 break; 801 case JBIG2_COMPOSE_XNOR: 802 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM); 803 break; 804 case JBIG2_COMPOSE_REPLACE: 805 tmp = (tmp2 & ~maskM) | (tmp1 & maskM); 806 break; 807 } 808 lineDst[0] = (uint8_t)(tmp >> 24); 809 lineDst[1] = (uint8_t)(tmp >> 16); 810 lineDst[2] = (uint8_t)(tmp >> 8); 811 lineDst[3] = (uint8_t)tmp; 812 lineSrc += m_nStride; 813 lineDst += pDst->m_nStride; 814 } 815 } 816 } else { 817 if (s1 > d1) { 818 uint32_t shift1 = s1 - d1; 819 uint32_t shift2 = 32 - shift1; 820 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); 821 for (int32_t yy = yd0; yy < yd1; yy++) { 822 uint8_t* sp = lineSrc; 823 uint8_t* dp = lineDst; 824 if (d1 != 0) { 825 uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift1) | 826 (JBIG2_GETDWORD(sp + 4) >> shift2); 827 uint32_t tmp2 = JBIG2_GETDWORD(dp); 828 uint32_t tmp = 0; 829 switch (op) { 830 case JBIG2_COMPOSE_OR: 831 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL); 832 break; 833 case JBIG2_COMPOSE_AND: 834 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL); 835 break; 836 case JBIG2_COMPOSE_XOR: 837 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL); 838 break; 839 case JBIG2_COMPOSE_XNOR: 840 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL); 841 break; 842 case JBIG2_COMPOSE_REPLACE: 843 tmp = (tmp2 & ~maskL) | (tmp1 & maskL); 844 break; 845 } 846 dp[0] = (uint8_t)(tmp >> 24); 847 dp[1] = (uint8_t)(tmp >> 16); 848 dp[2] = (uint8_t)(tmp >> 8); 849 dp[3] = (uint8_t)tmp; 850 sp += 4; 851 dp += 4; 852 } 853 for (int32_t xx = 0; xx < middleDwords; xx++) { 854 uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift1) | 855 (JBIG2_GETDWORD(sp + 4) >> shift2); 856 uint32_t tmp2 = JBIG2_GETDWORD(dp); 857 uint32_t tmp = 0; 858 switch (op) { 859 case JBIG2_COMPOSE_OR: 860 tmp = tmp1 | tmp2; 861 break; 862 case JBIG2_COMPOSE_AND: 863 tmp = tmp1 & tmp2; 864 break; 865 case JBIG2_COMPOSE_XOR: 866 tmp = tmp1 ^ tmp2; 867 break; 868 case JBIG2_COMPOSE_XNOR: 869 tmp = ~(tmp1 ^ tmp2); 870 break; 871 case JBIG2_COMPOSE_REPLACE: 872 tmp = tmp1; 873 break; 874 } 875 dp[0] = (uint8_t)(tmp >> 24); 876 dp[1] = (uint8_t)(tmp >> 16); 877 dp[2] = (uint8_t)(tmp >> 8); 878 dp[3] = (uint8_t)tmp; 879 sp += 4; 880 dp += 4; 881 } 882 if (d2 != 0) { 883 uint32_t tmp1 = 884 (JBIG2_GETDWORD(sp) << shift1) | 885 (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> 886 shift2); 887 uint32_t tmp2 = JBIG2_GETDWORD(dp); 888 uint32_t tmp = 0; 889 switch (op) { 890 case JBIG2_COMPOSE_OR: 891 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR); 892 break; 893 case JBIG2_COMPOSE_AND: 894 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR); 895 break; 896 case JBIG2_COMPOSE_XOR: 897 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR); 898 break; 899 case JBIG2_COMPOSE_XNOR: 900 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR); 901 break; 902 case JBIG2_COMPOSE_REPLACE: 903 tmp = (tmp2 & ~maskR) | (tmp1 & maskR); 904 break; 905 } 906 dp[0] = (uint8_t)(tmp >> 24); 907 dp[1] = (uint8_t)(tmp >> 16); 908 dp[2] = (uint8_t)(tmp >> 8); 909 dp[3] = (uint8_t)tmp; 910 } 911 lineSrc += m_nStride; 912 lineDst += pDst->m_nStride; 913 } 914 } else if (s1 == d1) { 915 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); 916 for (int32_t yy = yd0; yy < yd1; yy++) { 917 uint8_t* sp = lineSrc; 918 uint8_t* dp = lineDst; 919 if (d1 != 0) { 920 uint32_t tmp1 = JBIG2_GETDWORD(sp); 921 uint32_t tmp2 = JBIG2_GETDWORD(dp); 922 uint32_t tmp = 0; 923 switch (op) { 924 case JBIG2_COMPOSE_OR: 925 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL); 926 break; 927 case JBIG2_COMPOSE_AND: 928 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL); 929 break; 930 case JBIG2_COMPOSE_XOR: 931 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL); 932 break; 933 case JBIG2_COMPOSE_XNOR: 934 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL); 935 break; 936 case JBIG2_COMPOSE_REPLACE: 937 tmp = (tmp2 & ~maskL) | (tmp1 & maskL); 938 break; 939 } 940 dp[0] = (uint8_t)(tmp >> 24); 941 dp[1] = (uint8_t)(tmp >> 16); 942 dp[2] = (uint8_t)(tmp >> 8); 943 dp[3] = (uint8_t)tmp; 944 sp += 4; 945 dp += 4; 946 } 947 for (int32_t xx = 0; xx < middleDwords; xx++) { 948 uint32_t tmp1 = JBIG2_GETDWORD(sp); 949 uint32_t tmp2 = JBIG2_GETDWORD(dp); 950 uint32_t tmp = 0; 951 switch (op) { 952 case JBIG2_COMPOSE_OR: 953 tmp = tmp1 | tmp2; 954 break; 955 case JBIG2_COMPOSE_AND: 956 tmp = tmp1 & tmp2; 957 break; 958 case JBIG2_COMPOSE_XOR: 959 tmp = tmp1 ^ tmp2; 960 break; 961 case JBIG2_COMPOSE_XNOR: 962 tmp = ~(tmp1 ^ tmp2); 963 break; 964 case JBIG2_COMPOSE_REPLACE: 965 tmp = tmp1; 966 break; 967 } 968 dp[0] = (uint8_t)(tmp >> 24); 969 dp[1] = (uint8_t)(tmp >> 16); 970 dp[2] = (uint8_t)(tmp >> 8); 971 dp[3] = (uint8_t)tmp; 972 sp += 4; 973 dp += 4; 974 } 975 if (d2 != 0) { 976 uint32_t tmp1 = JBIG2_GETDWORD(sp); 977 uint32_t tmp2 = JBIG2_GETDWORD(dp); 978 uint32_t tmp = 0; 979 switch (op) { 980 case JBIG2_COMPOSE_OR: 981 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR); 982 break; 983 case JBIG2_COMPOSE_AND: 984 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR); 985 break; 986 case JBIG2_COMPOSE_XOR: 987 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR); 988 break; 989 case JBIG2_COMPOSE_XNOR: 990 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR); 991 break; 992 case JBIG2_COMPOSE_REPLACE: 993 tmp = (tmp2 & ~maskR) | (tmp1 & maskR); 994 break; 995 } 996 dp[0] = (uint8_t)(tmp >> 24); 997 dp[1] = (uint8_t)(tmp >> 16); 998 dp[2] = (uint8_t)(tmp >> 8); 999 dp[3] = (uint8_t)tmp; 1000 } 1001 lineSrc += m_nStride; 1002 lineDst += pDst->m_nStride; 1003 } 1004 } else { 1005 uint32_t shift1 = d1 - s1; 1006 uint32_t shift2 = 32 - shift1; 1007 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5); 1008 for (int32_t yy = yd0; yy < yd1; yy++) { 1009 uint8_t* sp = lineSrc; 1010 uint8_t* dp = lineDst; 1011 if (d1 != 0) { 1012 uint32_t tmp1 = JBIG2_GETDWORD(sp) >> shift1; 1013 uint32_t tmp2 = JBIG2_GETDWORD(dp); 1014 uint32_t tmp = 0; 1015 switch (op) { 1016 case JBIG2_COMPOSE_OR: 1017 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL); 1018 break; 1019 case JBIG2_COMPOSE_AND: 1020 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL); 1021 break; 1022 case JBIG2_COMPOSE_XOR: 1023 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL); 1024 break; 1025 case JBIG2_COMPOSE_XNOR: 1026 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL); 1027 break; 1028 case JBIG2_COMPOSE_REPLACE: 1029 tmp = (tmp2 & ~maskL) | (tmp1 & maskL); 1030 break; 1031 } 1032 dp[0] = (uint8_t)(tmp >> 24); 1033 dp[1] = (uint8_t)(tmp >> 16); 1034 dp[2] = (uint8_t)(tmp >> 8); 1035 dp[3] = (uint8_t)tmp; 1036 dp += 4; 1037 } 1038 for (int32_t xx = 0; xx < middleDwords; xx++) { 1039 uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift2) | 1040 ((JBIG2_GETDWORD(sp + 4)) >> shift1); 1041 uint32_t tmp2 = JBIG2_GETDWORD(dp); 1042 uint32_t tmp = 0; 1043 switch (op) { 1044 case JBIG2_COMPOSE_OR: 1045 tmp = tmp1 | tmp2; 1046 break; 1047 case JBIG2_COMPOSE_AND: 1048 tmp = tmp1 & tmp2; 1049 break; 1050 case JBIG2_COMPOSE_XOR: 1051 tmp = tmp1 ^ tmp2; 1052 break; 1053 case JBIG2_COMPOSE_XNOR: 1054 tmp = ~(tmp1 ^ tmp2); 1055 break; 1056 case JBIG2_COMPOSE_REPLACE: 1057 tmp = tmp1; 1058 break; 1059 } 1060 dp[0] = (uint8_t)(tmp >> 24); 1061 dp[1] = (uint8_t)(tmp >> 16); 1062 dp[2] = (uint8_t)(tmp >> 8); 1063 dp[3] = (uint8_t)tmp; 1064 sp += 4; 1065 dp += 4; 1066 } 1067 if (d2 != 0) { 1068 uint32_t tmp1 = 1069 (JBIG2_GETDWORD(sp) << shift2) | 1070 (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> 1071 shift1); 1072 uint32_t tmp2 = JBIG2_GETDWORD(dp); 1073 uint32_t tmp = 0; 1074 switch (op) { 1075 case JBIG2_COMPOSE_OR: 1076 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR); 1077 break; 1078 case JBIG2_COMPOSE_AND: 1079 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR); 1080 break; 1081 case JBIG2_COMPOSE_XOR: 1082 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR); 1083 break; 1084 case JBIG2_COMPOSE_XNOR: 1085 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR); 1086 break; 1087 case JBIG2_COMPOSE_REPLACE: 1088 tmp = (tmp2 & ~maskR) | (tmp1 & maskR); 1089 break; 1090 } 1091 dp[0] = (uint8_t)(tmp >> 24); 1092 dp[1] = (uint8_t)(tmp >> 16); 1093 dp[2] = (uint8_t)(tmp >> 8); 1094 dp[3] = (uint8_t)tmp; 1095 } 1096 lineSrc += m_nStride; 1097 lineDst += pDst->m_nStride; 1098 } 1099 } 1100 } 1101 return 1; 1102 } 1103