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
CJBig2_Image(int32_t w,int32_t h)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 }
CJBig2_Image(int32_t w,int32_t h,int32_t stride,uint8_t * pBuf)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 }
CJBig2_Image(const CJBig2_Image & im)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 }
~CJBig2_Image()51 CJBig2_Image::~CJBig2_Image() {
52 if (m_bNeedFree) {
53 FX_Free(m_pData);
54 }
55 }
getPixel(int32_t x,int32_t y)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
setPixel(int32_t x,int32_t y,FX_BOOL v)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 }
copyLine(int32_t hTo,int32_t hFrom)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 }
fill(FX_BOOL v)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 }
composeTo(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op)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 }
composeTo(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op,const FX_RECT * pSrcRect)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
composeFrom(int32_t x,int32_t y,CJBig2_Image * pSrc,JBig2ComposeOp op)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 }
composeFrom(int32_t x,int32_t y,CJBig2_Image * pSrc,JBig2ComposeOp op,const FX_RECT * pSrcRect)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]))
subImage(int32_t x,int32_t y,int32_t w,int32_t h)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 }
expand(int32_t h,FX_BOOL v)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 }
composeTo_opt2(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op)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 }
composeTo_opt2(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op,const FX_RECT * pSrcRect)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