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