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
CJBig2_Image(int32_t w,int32_t h)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
CJBig2_Image(int32_t w,int32_t h,int32_t stride,uint8_t * pBuf)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
CJBig2_Image(const CJBig2_Image & other)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
~CJBig2_Image()69 CJBig2_Image::~CJBig2_Image() {}
70
getPixel(int32_t x,int32_t y) const71 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
setPixel(int32_t x,int32_t y,int v)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
copyLine(int32_t hTo,int32_t hFrom)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 }
fill(bool v)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 }
composeTo(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op)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 }
composeTo(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op,const FX_RECT * pSrcRect)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
composeFrom(int32_t x,int32_t y,CJBig2_Image * pSrc,JBig2ComposeOp op)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 }
composeFrom(int32_t x,int32_t y,CJBig2_Image * pSrc,JBig2ComposeOp op,const FX_RECT * pSrcRect)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
subImage(int32_t x,int32_t y,int32_t w,int32_t h)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
expand(int32_t h,bool v)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
composeTo_opt2(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op)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
composeTo_opt2(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op,const FX_RECT * pSrcRect)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