Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / core / src / fxcodec / jbig2 / JBig2_Image.cpp
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 "../../../include/fxcrt/fx_basic.h"
10 #include "../../../include/fxcrt/fx_coordinates.h"
11 #include "../../../include/fxcrt/fx_safe_types.h"
12 #include "JBig2_Image.h"
13
14 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h)
15 {
16     m_nWidth    = w;
17     m_nHeight   = h;
18     if (m_nWidth <= 0 || m_nHeight <= 0 || m_nWidth > INT_MAX - 31) {
19         m_pData = NULL;
20         m_bNeedFree = FALSE;
21         return;
22     }
23     m_nStride  = ((w + 31) >> 5) << 2;
24     if (m_nStride * m_nHeight > 0 && 104857600 / (int)m_nStride > m_nHeight) {
25         m_pData = (uint8_t *)m_pModule->JBig2_Malloc2(m_nStride, m_nHeight);
26     } else {
27         m_pData = NULL;
28     }
29     m_bNeedFree = TRUE;
30 }
31 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h, int32_t stride, uint8_t*pBuf)
32 {
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(CJBig2_Image &im)
40 {
41     m_pModule = im.m_pModule;
42     m_nWidth    = im.m_nWidth;
43     m_nHeight   = im.m_nHeight;
44     m_nStride   = im.m_nStride;
45     if (im.m_pData) {
46         m_pData = (uint8_t*)m_pModule->JBig2_Malloc2(m_nStride, m_nHeight);
47         JBIG2_memcpy(m_pData, im.m_pData, m_nStride * m_nHeight);
48     } else {
49         m_pData = NULL;
50     }
51     m_bNeedFree = TRUE;
52 }
53 CJBig2_Image::~CJBig2_Image()
54 {
55     if(m_bNeedFree && m_pData) {
56         m_pModule->JBig2_Free(m_pData);
57     }
58 }
59 FX_BOOL CJBig2_Image::getPixel(int32_t x, int32_t y)
60 {
61     if (!m_pData) {
62         return 0;
63     }
64     int32_t m, n;
65     if(x < 0 || x >= m_nWidth) {
66         return 0;
67     }
68     if(y < 0 || y >= m_nHeight) {
69         return 0;
70     }
71     m = y * m_nStride + (x >> 3);
72     n = x & 7;
73     return ((m_pData[m] >> (7 - n)) & 1);
74 }
75
76 int32_t CJBig2_Image::setPixel(int32_t x, int32_t y, FX_BOOL v)
77 {
78     if (!m_pData) {
79         return 0;
80     }
81     int32_t m, n;
82     if(x < 0 || x >= m_nWidth) {
83         return 0;
84     }
85     if(y < 0 || y >= m_nHeight) {
86         return 0;
87     }
88     m = y * m_nStride + (x >> 3);
89     n = x & 7;
90     if(v) {
91         m_pData[m] |= 1 << (7 - n);
92     } else {
93         m_pData[m] &= ~(1 << (7 - n));
94     }
95     return 1;
96 }
97 void CJBig2_Image::copyLine(int32_t hTo, int32_t hFrom)
98 {
99     if (!m_pData) {
100         return;
101     }
102     if(hFrom < 0 || hFrom >= m_nHeight) {
103         JBIG2_memset(m_pData + hTo * m_nStride, 0, m_nStride);
104     } else {
105         JBIG2_memcpy(m_pData + hTo * m_nStride, m_pData + hFrom * m_nStride, m_nStride);
106     }
107 }
108 void CJBig2_Image::fill(FX_BOOL v)
109 {
110     if (!m_pData) {
111         return;
112     }
113     JBIG2_memset(m_pData, v ? 0xff : 0, m_nStride * m_nHeight);
114 }
115 FX_BOOL CJBig2_Image::composeTo(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op)
116 {
117     if (!m_pData) {
118         return FALSE;
119     }
120     return composeTo_opt2(pDst, x, y, op);
121 }
122 FX_BOOL CJBig2_Image::composeTo(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op, const FX_RECT* pSrcRect)
123 {
124     if (!m_pData) {
125         return FALSE;
126     }
127     if (NULL == pSrcRect || *pSrcRect == FX_RECT(0, 0, m_nWidth, m_nHeight)) {
128         return composeTo_opt2(pDst, x, y, op);
129     }
130     return composeTo_opt2(pDst, x, y, op, pSrcRect);
131 }
132 FX_BOOL CJBig2_Image::composeTo_unopt(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op)
133 {
134     int32_t w, h, dx, dy;
135     int32_t i, j;
136     w = m_nWidth;
137     h = m_nHeight;
138     dx = dy = 0;
139     if(x < 0) {
140         dx += -x;
141         w  -= -x;
142         x = 0;
143     }
144     if(y < 0) {
145         dy += -y;
146         h  -= -y;
147         y = 0;
148     }
149     if(x + w > pDst->m_nWidth) {
150         w = pDst->m_nWidth - x;
151     }
152     if(y + h > pDst->m_nHeight) {
153         h = pDst->m_nHeight - y;
154     }
155     switch(op) {
156         case JBIG2_COMPOSE_OR:
157             for(j = 0; j < h; j++) {
158                 for(i = 0; i < w; i++) {
159                     pDst->setPixel(x + i, y + j,
160                                    (getPixel(i + dx, j + dy) | pDst->getPixel(x + i, y + j)) & 1);
161                 }
162             }
163             break;
164         case JBIG2_COMPOSE_AND:
165             for(j = 0; j < h; j++) {
166                 for(i = 0; i < w; i++) {
167                     pDst->setPixel(x + i, y + j,
168                                    (getPixel(i + dx, j + dy) & pDst->getPixel(x + i, y + j)) & 1);
169                 }
170             }
171             break;
172         case JBIG2_COMPOSE_XOR:
173             for(j = 0; j < h; j++) {
174                 for(i = 0; i < w; i++) {
175                     pDst->setPixel(x + i, y + j,
176                                    (getPixel(i + dx, j + dy) ^ pDst->getPixel(x + i, y + j)) & 1);
177                 }
178             }
179             break;
180         case JBIG2_COMPOSE_XNOR:
181             for(j = 0; j < h; j++) {
182                 for(i = 0; i < w; i++) {
183                     pDst->setPixel(x + i, y + j,
184                                    (~(getPixel(i + dx, j + dy) ^ pDst->getPixel(x + i, y + j))) & 1);
185                 }
186             }
187             break;
188         case JBIG2_COMPOSE_REPLACE:
189             for(j = 0; j < h; j++) {
190                 for(i = 0; i < w; i++) {
191                     pDst->setPixel(x + i, y + j, getPixel(i + dx, j + dy));
192                 }
193             }
194             break;
195     }
196     return TRUE;
197 }
198
199 FX_BOOL CJBig2_Image::composeTo_opt(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op)
200 {
201     int32_t x0, x1, y0, y1, xx, yy;
202     uint8_t *pLineSrc, *pLineDst, *srcPtr, *destPtr;
203     FX_DWORD src0, src1, src, dest, s1, s2, m1, m2, m3;
204     FX_BOOL oneByte;
205     if (!m_pData) {
206         return FALSE;
207     }
208     if (y < 0) {
209         y0 = -y;
210     } else {
211         y0 = 0;
212     }
213     if (y + m_nHeight > pDst->m_nHeight) {
214         y1 = pDst->m_nHeight - y;
215     } else {
216         y1 = m_nHeight;
217     }
218     if (y0 >= y1) {
219         return FALSE;
220     }
221     if (x >= 0) {
222         x0 = x & ~7;
223     } else {
224         x0 = 0;
225     }
226     x1 = x + m_nWidth;
227     if (x1 > pDst->m_nWidth) {
228         x1 = pDst->m_nWidth;
229     }
230     if (x0 >= x1) {
231         return FALSE;
232     }
233     s1 = x & 7;
234     s2 = 8 - s1;
235     m1 = 0xff >> (x1 & 7);
236     m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7));
237     m3 = (0xff >> s1) & m2;
238     oneByte = x0 == ((x1 - 1) & ~7);
239     pLineDst = pDst->m_pData + y * pDst->m_nStride;
240     pLineSrc = m_pData + y0 * m_nStride;
241     if(oneByte) {
242         if(x >= 0) {
243             switch(op) {
244                 case JBIG2_COMPOSE_OR: {
245                         for (yy = y0; yy < y1; ++yy) {
246                             destPtr = pLineDst + (x >> 3);
247                             srcPtr = pLineSrc;
248                             dest = *destPtr;
249                             dest |= (*srcPtr >> s1) & m2;
250                             *destPtr = (uint8_t)dest;
251                             pLineDst += pDst->m_nStride;
252                             pLineSrc += m_nStride;
253                         }
254                     }
255                     break;
256                 case JBIG2_COMPOSE_AND: {
257                         for (yy = y0; yy < y1; ++yy) {
258                             destPtr = pLineDst + (x >> 3);
259                             srcPtr = pLineSrc;
260                             dest = *destPtr;
261                             dest &= ((0xff00 | *srcPtr) >> s1) | m1;
262                             *destPtr = (uint8_t)dest;
263                             pLineDst += pDst->m_nStride;
264                             pLineSrc += m_nStride;
265                         }
266                     }
267                     break;
268                 case JBIG2_COMPOSE_XOR: {
269                         for (yy = y0; yy < y1; ++yy) {
270                             destPtr = pLineDst + (x >> 3);
271                             srcPtr = pLineSrc;
272                             dest = *destPtr;
273                             dest ^= (*srcPtr >> s1) & m2;
274                             *destPtr = (uint8_t)dest;
275                             pLineDst += pDst->m_nStride;
276                             pLineSrc += m_nStride;
277                         }
278                     }
279                     break;
280                 case JBIG2_COMPOSE_XNOR: {
281                         for (yy = y0; yy < y1; ++yy) {
282                             destPtr = pLineDst + (x >> 3);
283                             srcPtr = pLineSrc;
284                             dest = *destPtr;
285                             dest ^= ((*srcPtr ^ 0xff) >> s1) & m2;
286                             *destPtr = (uint8_t)dest;
287                             pLineDst += pDst->m_nStride;
288                             pLineSrc += m_nStride;
289                         }
290                     }
291                     break;
292                 case JBIG2_COMPOSE_REPLACE: {
293                         for (yy = y0; yy < y1; ++yy) {
294                             destPtr = pLineDst + (x >> 3);
295                             srcPtr = pLineSrc;
296                             dest = *destPtr;
297                             dest = (dest & ~m3) | ((*srcPtr >> s1) & m3);
298                             *destPtr = (uint8_t)dest;
299                             pLineDst += pDst->m_nStride;
300                             pLineSrc += m_nStride;
301                         }
302                     }
303                     break;
304             }
305         } else {
306             switch(op) {
307                 case JBIG2_COMPOSE_OR: {
308                         for(yy = y0; yy < y1; ++yy) {
309                             destPtr = pLineDst;
310                             srcPtr = pLineSrc + (-x >> 3);
311                             dest = *destPtr;
312                             dest |= *srcPtr & m2;
313                             *destPtr = (uint8_t)dest;
314                             pLineDst += pDst->m_nStride;
315                             pLineSrc += m_nStride;
316                         }
317                     }
318                     break;
319                 case JBIG2_COMPOSE_AND: {
320                         for(yy = y0; yy < y1; ++yy) {
321                             destPtr = pLineDst;
322                             srcPtr = pLineSrc + (-x >> 3);
323                             dest = *destPtr;
324                             dest &= *srcPtr | m1;
325                             *destPtr = (uint8_t)dest;
326                             pLineDst += pDst->m_nStride;
327                             pLineSrc += m_nStride;
328                         }
329                     }
330                     break;
331                 case JBIG2_COMPOSE_XOR: {
332                         for(yy = y0; yy < y1; ++yy) {
333                             destPtr = pLineDst;
334                             srcPtr = pLineSrc + (-x >> 3);
335                             dest = *destPtr;
336                             dest ^= *srcPtr & m2;
337                             *destPtr = (uint8_t)dest;
338                             pLineDst += pDst->m_nStride;
339                             pLineSrc += m_nStride;
340                         }
341                     }
342                     break;
343                 case JBIG2_COMPOSE_XNOR: {
344                         for(yy = y0; yy < y1; ++yy) {
345                             destPtr = pLineDst;
346                             srcPtr = pLineSrc + (-x >> 3);
347                             dest = *destPtr;
348                             dest ^= (*srcPtr ^ 0xff) & m2;
349                             *destPtr = (uint8_t)dest;
350                             pLineDst += pDst->m_nStride;
351                             pLineSrc += m_nStride;
352                         }
353                     }
354                     break;
355                 case JBIG2_COMPOSE_REPLACE: {
356                         for(yy = y0; yy < y1; ++yy) {
357                             destPtr = pLineDst;
358                             srcPtr = pLineSrc + (-x >> 3);
359                             dest = *destPtr;
360                             dest = (*srcPtr & m2) | (dest & m1);
361                             *destPtr = (uint8_t)dest;
362                             pLineDst += pDst->m_nStride;
363                             pLineSrc += m_nStride;
364                         }
365                     }
366                     break;
367             }
368         }
369     } else {
370         if(x >= 0) {
371             switch(op) {
372                 case JBIG2_COMPOSE_OR: {
373                         for(yy = y0; yy < y1; ++yy) {
374                             destPtr = pLineDst + (x >> 3);
375                             srcPtr = pLineSrc;
376                             src1 = *srcPtr++;
377                             dest = *destPtr;
378                             dest |= src1 >> s1;
379                             *destPtr++ = (uint8_t)dest;
380                             xx = x0 + 8;
381                             for (; xx < x1 - 8; xx += 8) {
382                                 dest = *destPtr;
383                                 src0 = src1;
384                                 src1 = *srcPtr++;
385                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
386                                 dest |= src;
387                                 *destPtr++ = (uint8_t)dest;
388                             }
389                             dest = *destPtr;
390                             src0 = src1;
391                             if(srcPtr - pLineSrc < m_nStride) {
392                                 src1 = *srcPtr++;
393                             } else {
394                                 src1 = 0;
395                             }
396                             src = (((src0 << 8) | src1) >> s1) & 0xff;
397                             dest |= src & m2;
398                             *destPtr = (uint8_t)dest;
399                             pLineDst += pDst->m_nStride;
400                             pLineSrc += m_nStride;
401                         }
402                     }
403                     break;
404                 case JBIG2_COMPOSE_AND: {
405                         for(yy = y0; yy < y1; ++yy) {
406                             destPtr = pLineDst + (x >> 3);
407                             srcPtr = pLineSrc;
408                             src1 = *srcPtr++;
409                             dest = *destPtr;
410                             dest &= (0xff00 | src1) >> s1;
411                             *destPtr++ = (uint8_t)dest;
412                             xx = x0 + 8;
413                             for (; xx < x1 - 8; xx += 8) {
414                                 dest = *destPtr;
415                                 src0 = src1;
416                                 src1 = *srcPtr++;
417                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
418                                 dest &= src;
419                                 *destPtr++ = (uint8_t)dest;
420                             }
421                             dest = *destPtr;
422                             src0 = src1;
423                             if(srcPtr - pLineSrc < m_nStride) {
424                                 src1 = *srcPtr++;
425                             } else {
426                                 src1 = 0;
427                             }
428                             src = (((src0 << 8) | src1) >> s1) & 0xff;
429                             dest &= src | m1;
430                             *destPtr = (uint8_t)dest;
431                             pLineDst += pDst->m_nStride;
432                             pLineSrc += m_nStride;
433                         }
434                     }
435                     break;
436                 case JBIG2_COMPOSE_XOR: {
437                         for(yy = y0; yy < y1; ++yy) {
438                             destPtr = pLineDst + (x >> 3);
439                             srcPtr = pLineSrc;
440                             src1 = *srcPtr++;
441                             dest = *destPtr;
442                             dest ^= src1 >> s1;
443                             *destPtr++ = (uint8_t)dest;
444                             xx = x0 + 8;
445                             for (; xx < x1 - 8; xx += 8) {
446                                 dest = *destPtr;
447                                 src0 = src1;
448                                 src1 = *srcPtr++;
449                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
450                                 dest ^= src;
451                                 *destPtr++ = (uint8_t)dest;
452                             }
453                             dest = *destPtr;
454                             src0 = src1;
455                             if(srcPtr - pLineSrc < m_nStride) {
456                                 src1 = *srcPtr++;
457                             } else {
458                                 src1 = 0;
459                             }
460                             src = (((src0 << 8) | src1) >> s1) & 0xff;
461                             dest ^= src & m2;
462                             *destPtr = (uint8_t)dest;
463                             pLineDst += pDst->m_nStride;
464                             pLineSrc += m_nStride;
465                         }
466                     }
467                     break;
468                 case JBIG2_COMPOSE_XNOR: {
469                         for(yy = y0; yy < y1; ++yy) {
470                             destPtr = pLineDst + (x >> 3);
471                             srcPtr = pLineSrc;
472                             src1 = *srcPtr++;
473                             dest = *destPtr;
474                             dest ^= (src1 ^ 0xff) >> s1;
475                             *destPtr++ = (uint8_t)dest;
476                             xx = x0 + 8;
477                             for (; xx < x1 - 8; xx += 8) {
478                                 dest = *destPtr;
479                                 src0 = src1;
480                                 src1 = *srcPtr++;
481                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
482                                 dest ^= src ^ 0xff;
483                                 *destPtr++ = (uint8_t)dest;
484                             }
485                             dest = *destPtr;
486                             src0 = src1;
487                             if(srcPtr - pLineSrc < m_nStride) {
488                                 src1 = *srcPtr++;
489                             } else {
490                                 src1 = 0;
491                             }
492                             src = (((src0 << 8) | src1) >> s1) & 0xff;
493                             dest ^= (src ^ 0xff) & m2;
494                             *destPtr = (uint8_t)dest;
495                             pLineDst += pDst->m_nStride;
496                             pLineSrc += m_nStride;
497                         }
498                     }
499                     break;
500                 case JBIG2_COMPOSE_REPLACE: {
501                         for(yy = y0; yy < y1; ++yy) {
502                             destPtr = pLineDst + (x >> 3);
503                             srcPtr = pLineSrc;
504                             src1 = *srcPtr++;
505                             dest = *destPtr;
506                             dest = (dest & (0xff << s2)) | (src1 >> s1);
507                             *destPtr++ = (uint8_t)dest;
508                             xx = x0 + 8;
509                             for (; xx < x1 - 8; xx += 8) {
510                                 dest = *destPtr;
511                                 src0 = src1;
512                                 src1 = *srcPtr++;
513                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
514                                 dest = src;
515                                 *destPtr++ = (uint8_t)dest;
516                             }
517                             dest = *destPtr;
518                             src0 = src1;
519                             if(srcPtr - pLineSrc < m_nStride) {
520                                 src1 = *srcPtr++;
521                             } else {
522                                 src1 = 0;
523                             }
524                             src = (((src0 << 8) | src1) >> s1) & 0xff;
525                             dest = (src & m2) | (dest & m1);
526                             *destPtr = (uint8_t)dest;
527                             pLineDst += pDst->m_nStride;
528                             pLineSrc += m_nStride;
529                         }
530                     }
531                     break;
532             }
533         } else {
534             switch(op) {
535                 case JBIG2_COMPOSE_OR: {
536                         for(yy = y0; yy < y1; ++yy) {
537                             destPtr = pLineDst;
538                             srcPtr = pLineSrc + (-x >> 3);
539                             src1 = *srcPtr++;
540                             xx = x0;
541                             for (; xx < x1 - 8; xx += 8) {
542                                 dest = *destPtr;
543                                 src0 = src1;
544                                 src1 = *srcPtr++;
545                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
546                                 dest |= src;
547                                 *destPtr++ = (uint8_t)dest;
548                             }
549                             dest = *destPtr;
550                             src0 = src1;
551                             if(srcPtr - pLineSrc < m_nStride) {
552                                 src1 = *srcPtr++;
553                             } else {
554                                 src1 = 0;
555                             }
556                             src = (((src0 << 8) | src1) >> s1) & 0xff;
557                             dest |= src & m2;
558                             *destPtr = (uint8_t)dest;
559                             pLineDst += pDst->m_nStride;
560                             pLineSrc += m_nStride;
561                         }
562                     }
563                     break;
564                 case JBIG2_COMPOSE_AND: {
565                         for(yy = y0; yy < y1; ++yy) {
566                             destPtr = pLineDst;
567                             srcPtr = pLineSrc + (-x >> 3);
568                             src1 = *srcPtr++;
569                             xx = x0;
570                             for (; xx < x1 - 8; xx += 8) {
571                                 dest = *destPtr;
572                                 src0 = src1;
573                                 src1 = *srcPtr++;
574                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
575                                 dest &= src;
576                                 *destPtr++ = (uint8_t)dest;
577                             }
578                             dest = *destPtr;
579                             src0 = src1;
580                             if(srcPtr - pLineSrc < m_nStride) {
581                                 src1 = *srcPtr++;
582                             } else {
583                                 src1 = 0;
584                             }
585                             src = (((src0 << 8) | src1) >> s1) & 0xff;
586                             dest &= src | m1;
587                             *destPtr = (uint8_t)dest;
588                             pLineDst += pDst->m_nStride;
589                             pLineSrc += m_nStride;
590                         }
591                     }
592                     break;
593                 case JBIG2_COMPOSE_XOR: {
594                         for(yy = y0; yy < y1; ++yy) {
595                             destPtr = pLineDst;
596                             srcPtr = pLineSrc + (-x >> 3);
597                             src1 = *srcPtr++;
598                             xx = x0;
599                             for (; xx < x1 - 8; xx += 8) {
600                                 dest = *destPtr;
601                                 src0 = src1;
602                                 src1 = *srcPtr++;
603                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
604                                 dest ^= src;
605                                 *destPtr++ = (uint8_t)dest;
606                             }
607                             dest = *destPtr;
608                             src0 = src1;
609                             if(srcPtr - pLineSrc < m_nStride) {
610                                 src1 = *srcPtr++;
611                             } else {
612                                 src1 = 0;
613                             }
614                             src = (((src0 << 8) | src1) >> s1) & 0xff;
615                             dest ^= src & m2;
616                             *destPtr = (uint8_t)dest;
617                             pLineDst += pDst->m_nStride;
618                             pLineSrc += m_nStride;
619                         }
620                     }
621                     break;
622                 case JBIG2_COMPOSE_XNOR: {
623                         for(yy = y0; yy < y1; ++yy) {
624                             destPtr = pLineDst;
625                             srcPtr = pLineSrc + (-x >> 3);
626                             src1 = *srcPtr++;
627                             xx = x0;
628                             for (; xx < x1 - 8; xx += 8) {
629                                 dest = *destPtr;
630                                 src0 = src1;
631                                 src1 = *srcPtr++;
632                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
633                                 dest ^= src ^ 0xff;
634                                 *destPtr++ = (uint8_t)dest;
635                             }
636                             dest = *destPtr;
637                             src0 = src1;
638                             if(srcPtr - pLineSrc < m_nStride) {
639                                 src1 = *srcPtr++;
640                             } else {
641                                 src1 = 0;
642                             }
643                             src = (((src0 << 8) | src1) >> s1) & 0xff;
644                             dest ^= (src ^ 0xff) & m2;
645                             *destPtr = (uint8_t)dest;
646                             pLineDst += pDst->m_nStride;
647                             pLineSrc += m_nStride;
648                         }
649                     }
650                     break;
651                 case JBIG2_COMPOSE_REPLACE: {
652                         for(yy = y0; yy < y1; ++yy) {
653                             destPtr = pLineDst;
654                             srcPtr = pLineSrc + (-x >> 3);
655                             src1 = *srcPtr++;
656                             xx = x0;
657                             for (; xx < x1 - 8; xx += 8) {
658                                 dest = *destPtr;
659                                 src0 = src1;
660                                 src1 = *srcPtr++;
661                                 src = (((src0 << 8) | src1) >> s1) & 0xff;
662                                 dest = src;
663                                 *destPtr++ = (uint8_t)dest;
664                             }
665                             dest = *destPtr;
666                             src0 = src1;
667                             if(srcPtr - pLineSrc < m_nStride) {
668                                 src1 = *srcPtr++;
669                             } else {
670                                 src1 = 0;
671                             }
672                             src = (((src0 << 8) | src1) >> s1) & 0xff;
673                             dest = (src & m2) | (dest & m1);
674                             *destPtr = (uint8_t)dest;
675                             pLineDst += pDst->m_nStride;
676                             pLineSrc += m_nStride;
677                         }
678                     }
679                     break;
680             }
681         }
682     }
683     return TRUE;
684 }
685 FX_BOOL CJBig2_Image::composeFrom(int32_t x, int32_t y, CJBig2_Image *pSrc, JBig2ComposeOp op)
686 {
687     if (!m_pData) {
688         return FALSE;
689     }
690     return pSrc->composeTo(this, x, y, op);
691 }
692 FX_BOOL CJBig2_Image::composeFrom(int32_t x, int32_t y, CJBig2_Image *pSrc, JBig2ComposeOp op, const FX_RECT* pSrcRect)
693 {
694     if (!m_pData) {
695         return FALSE;
696     }
697     return pSrc->composeTo(this, x, y, op, pSrcRect);
698 }
699 CJBig2_Image *CJBig2_Image::subImage_unopt(int32_t x, int32_t y, int32_t w, int32_t h)
700 {
701     CJBig2_Image *pImage;
702     int32_t i, j;
703     JBIG2_ALLOC(pImage, CJBig2_Image(w, h));
704     for(j = 0; j < h; j++) {
705         for(i = 0; i < w; i++) {
706             pImage->setPixel(i, j, getPixel(x + i, y + j));
707         }
708     }
709     return pImage;
710 }
711 #define JBIG2_GETDWORD(buf)     ((FX_DWORD)(((buf)[0] << 24) | ((buf)[1] << 16) | ((buf)[2] << 8) | (buf)[3]))
712 CJBig2_Image *CJBig2_Image::subImage(int32_t x, int32_t y, int32_t w, int32_t h)
713 {
714     CJBig2_Image *pImage;
715     int32_t m, n, j;
716     uint8_t *pLineSrc, *pLineDst;
717     FX_DWORD wTmp;
718     uint8_t *pSrc, *pSrcEnd, *pDst, *pDstEnd;
719     if (w == 0 || h == 0) {
720         return NULL;
721     }
722     JBIG2_ALLOC(pImage, CJBig2_Image(w, h));
723     if (!m_pData) {
724         pImage->fill(0);
725         return pImage;
726     }
727     if (!pImage->m_pData) {
728         return pImage;
729     }
730     pLineSrc = m_pData + m_nStride * y;
731     pLineDst = pImage->m_pData;
732     m = (x >> 5) << 2;
733     n = x & 31;
734     if(n == 0) {
735         for(j = 0; j < h; j++) {
736             pSrc = pLineSrc + m;
737             pSrcEnd = pLineSrc + m_nStride;
738             pDst = pLineDst;
739             pDstEnd = pLineDst + pImage->m_nStride;
740             for(; pDst < pDstEnd; pSrc += 4, pDst += 4) {
741                 *((FX_DWORD *)pDst) = *((FX_DWORD *)pSrc);
742             }
743             pLineSrc += m_nStride;
744             pLineDst += pImage->m_nStride;
745         }
746     } else {
747         for(j = 0; j < h; j++) {
748             pSrc = pLineSrc + m;
749             pSrcEnd = pLineSrc + m_nStride;
750             pDst = pLineDst;
751             pDstEnd = pLineDst + pImage->m_nStride;
752             for(; pDst < pDstEnd; pSrc += 4, pDst += 4) {
753                 if(pSrc + 4 < pSrcEnd) {
754                     wTmp = (JBIG2_GETDWORD(pSrc) << n) | (JBIG2_GETDWORD(pSrc + 4) >> (32 - n));
755                 } else {
756                     wTmp = JBIG2_GETDWORD(pSrc) << n;
757                 }
758                 pDst[0] = (uint8_t)(wTmp >> 24);
759                 pDst[1] = (uint8_t)(wTmp >> 16);
760                 pDst[2] = (uint8_t)(wTmp >> 8);
761                 pDst[3] = (uint8_t)wTmp;
762             }
763             pLineSrc += m_nStride;
764             pLineDst += pImage->m_nStride;
765         }
766     }
767     return pImage;
768 }
769 void CJBig2_Image::expand(int32_t h, FX_BOOL v)
770 {
771     if (!m_pData || h <= m_nHeight) {
772         return;
773     }
774     FX_DWORD dwH = pdfium::base::checked_cast<FX_DWORD>(h);
775     FX_DWORD dwStride = pdfium::base::checked_cast<FX_DWORD>(m_nStride);
776     FX_DWORD dwHeight = pdfium::base::checked_cast<FX_DWORD>(m_nHeight);
777     FX_SAFE_DWORD safeMemSize = dwH; 
778     safeMemSize *= dwStride;
779     if (!safeMemSize.IsValid()) {
780         return;
781     }
782     //The guaranteed reallocated memory is to be < 4GB (unsigned int). 
783     m_pData = (uint8_t*)m_pModule->JBig2_Realloc(m_pData, safeMemSize.ValueOrDie());
784     //The result of dwHeight * dwStride doesn't overflow after the 
785     //checking of safeMemSize.
786     //The same as the result of (dwH - dwHeight) * dwStride) because
787     //dwH - dwHeight is always less than dwH(h) which is checked in
788     //the calculation of dwH * dwStride. 
789     JBIG2_memset(m_pData + dwHeight * dwStride, v ? 0xff : 0, (dwH - dwHeight) * dwStride);
790     m_nHeight = h;
791 }
792 FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op)
793 {
794     int32_t xs0 = 0, ys0  = 0, xs1  = 0, ys1   = 0, xd0    = 0, yd0          = 0, xd1      = 0, 
795              yd1 = 0, xx   = 0, yy   = 0, w     = 0, h      = 0, middleDwords = 0, lineLeft = 0;
796
797     FX_DWORD s1  = 0, d1   = 0, d2   = 0, shift = 0, shift1 = 0, shift2       = 0, 
798              tmp = 0, tmp1 = 0, tmp2 = 0, maskL = 0, maskR  = 0, maskM        = 0;
799
800     uint8_t *lineSrc = NULL, *lineDst = NULL, *sp = NULL, *dp = NULL;
801
802     if (!m_pData) {
803         return FALSE;
804     }
805     if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
806         return FALSE;
807     }
808     if(y < 0) {
809         ys0 = -y;
810     }
811     if(y + m_nHeight > pDst->m_nHeight) {
812         ys1 = pDst->m_nHeight - y;
813     } else {
814         ys1 = m_nHeight;
815     }
816     if(x < 0) {
817         xs0 = -x;
818     }
819     if(x + m_nWidth > pDst->m_nWidth) {
820         xs1 = pDst->m_nWidth - x;
821     } else {
822         xs1 = m_nWidth;
823     }
824     if((ys0 >= ys1) || (xs0 >= xs1)) {
825         return 0;
826     }
827     w = xs1 - xs0;
828     h = ys1 - ys0;
829     if(y >= 0) {
830         yd0 = y;
831     } 
832     if(x >= 0) {
833         xd0 = x;
834     }
835     xd1 = xd0 + w;
836     yd1 = yd0 + h;
837     d1 = xd0 & 31;
838     d2 = xd1 & 31;
839     s1 = xs0 & 31;
840     maskL = 0xffffffff >> d1;
841     maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
842     maskM = maskL & maskR;
843     lineSrc = m_pData + ys0 * m_nStride + ((xs0 >> 5) << 2);
844     lineLeft = m_nStride - ((xs0 >> 5) << 2);
845     lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
846     if((xd0 & ~31) == ((xd1 - 1) & ~31)) {
847         if((xs0 & ~31) == ((xs1 - 1) & ~31)) {
848             if(s1 > d1) {
849                 shift = s1 - d1;
850                 for(yy = yd0; yy < yd1; yy++) {
851                     tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
852                     tmp2 = JBIG2_GETDWORD(lineDst);
853                     switch(op) {
854                         case JBIG2_COMPOSE_OR:
855                             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
856                             break;
857                         case JBIG2_COMPOSE_AND:
858                             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
859                             break;
860                         case JBIG2_COMPOSE_XOR:
861                             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
862                             break;
863                         case JBIG2_COMPOSE_XNOR:
864                             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
865                             break;
866                         case JBIG2_COMPOSE_REPLACE:
867                             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
868                             break;
869                     }
870                     lineDst[0] = (uint8_t)(tmp >> 24);
871                     lineDst[1] = (uint8_t)(tmp >> 16);
872                     lineDst[2] = (uint8_t)(tmp >> 8);
873                     lineDst[3] = (uint8_t)tmp;
874                     lineSrc += m_nStride;
875                     lineDst += pDst->m_nStride;
876                 }
877             } else {
878                 shift = d1 - s1;
879                 for(yy = yd0; yy < yd1; yy++) {
880                     tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
881                     tmp2 = JBIG2_GETDWORD(lineDst);
882                     switch(op) {
883                         case JBIG2_COMPOSE_OR:
884                             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
885                             break;
886                         case JBIG2_COMPOSE_AND:
887                             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
888                             break;
889                         case JBIG2_COMPOSE_XOR:
890                             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
891                             break;
892                         case JBIG2_COMPOSE_XNOR:
893                             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
894                             break;
895                         case JBIG2_COMPOSE_REPLACE:
896                             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
897                             break;
898                     }
899                     lineDst[0] = (uint8_t)(tmp >> 24);
900                     lineDst[1] = (uint8_t)(tmp >> 16);
901                     lineDst[2] = (uint8_t)(tmp >> 8);
902                     lineDst[3] = (uint8_t)tmp;
903                     lineSrc += m_nStride;
904                     lineDst += pDst->m_nStride;
905                 }
906             }
907         } else {
908             shift1 = s1 - d1;
909             shift2 = 32 - shift1;
910             for(yy = yd0; yy < yd1; yy++) {
911                 tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) | (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
912                 tmp2 = JBIG2_GETDWORD(lineDst);
913                 switch(op) {
914                     case JBIG2_COMPOSE_OR:
915                         tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
916                         break;
917                     case JBIG2_COMPOSE_AND:
918                         tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
919                         break;
920                     case JBIG2_COMPOSE_XOR:
921                         tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
922                         break;
923                     case JBIG2_COMPOSE_XNOR:
924                         tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
925                         break;
926                     case JBIG2_COMPOSE_REPLACE:
927                         tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
928                         break;
929                 }
930                 lineDst[0] = (uint8_t)(tmp >> 24);
931                 lineDst[1] = (uint8_t)(tmp >> 16);
932                 lineDst[2] = (uint8_t)(tmp >> 8);
933                 lineDst[3] = (uint8_t)tmp;
934                 lineSrc += m_nStride;
935                 lineDst += pDst->m_nStride;
936             }
937         }
938     } else {
939         if(s1 > d1) {
940             shift1 = s1 - d1;
941             shift2 = 32 - shift1;
942             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
943             for(yy = yd0; yy < yd1; yy++) {
944                 sp = lineSrc;
945                 dp = lineDst;
946                 if(d1 != 0) {
947                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (JBIG2_GETDWORD(sp + 4) >> shift2);
948                     tmp2 = JBIG2_GETDWORD(dp);
949                     switch(op) {
950                         case JBIG2_COMPOSE_OR:
951                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
952                             break;
953                         case JBIG2_COMPOSE_AND:
954                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
955                             break;
956                         case JBIG2_COMPOSE_XOR:
957                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
958                             break;
959                         case JBIG2_COMPOSE_XNOR:
960                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
961                             break;
962                         case JBIG2_COMPOSE_REPLACE:
963                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
964                             break;
965                     }
966                     dp[0] = (uint8_t)(tmp >> 24);
967                     dp[1] = (uint8_t)(tmp >> 16);
968                     dp[2] = (uint8_t)(tmp >> 8);
969                     dp[3] = (uint8_t)tmp;
970                     sp += 4;
971                     dp += 4;
972                 }
973                 for(xx = 0; xx < middleDwords; xx++) {
974                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (JBIG2_GETDWORD(sp + 4) >> shift2);
975                     tmp2 = JBIG2_GETDWORD(dp);
976                     switch(op) {
977                         case JBIG2_COMPOSE_OR:
978                             tmp = tmp1 | tmp2;
979                             break;
980                         case JBIG2_COMPOSE_AND:
981                             tmp = tmp1 & tmp2;
982                             break;
983                         case JBIG2_COMPOSE_XOR:
984                             tmp = tmp1 ^ tmp2;
985                             break;
986                         case JBIG2_COMPOSE_XNOR:
987                             tmp = ~(tmp1 ^ tmp2);
988                             break;
989                         case JBIG2_COMPOSE_REPLACE:
990                             tmp = tmp1;
991                             break;
992                     }
993                     dp[0] = (uint8_t)(tmp >> 24);
994                     dp[1] = (uint8_t)(tmp >> 16);
995                     dp[2] = (uint8_t)(tmp >> 8);
996                     dp[3] = (uint8_t)tmp;
997                     sp += 4;
998                     dp += 4;
999                 }
1000                 if(d2 != 0) {
1001                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (
1002                                ((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift2);
1003                     tmp2 = JBIG2_GETDWORD(dp);
1004                     switch(op) {
1005                         case JBIG2_COMPOSE_OR:
1006                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1007                             break;
1008                         case JBIG2_COMPOSE_AND:
1009                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1010                             break;
1011                         case JBIG2_COMPOSE_XOR:
1012                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1013                             break;
1014                         case JBIG2_COMPOSE_XNOR:
1015                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1016                             break;
1017                         case JBIG2_COMPOSE_REPLACE:
1018                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1019                             break;
1020                     }
1021                     dp[0] = (uint8_t)(tmp >> 24);
1022                     dp[1] = (uint8_t)(tmp >> 16);
1023                     dp[2] = (uint8_t)(tmp >> 8);
1024                     dp[3] = (uint8_t)tmp;
1025                 }
1026                 lineSrc += m_nStride;
1027                 lineDst += pDst->m_nStride;
1028             }
1029         } else if(s1 == d1) {
1030             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1031             for(yy = yd0; yy < yd1; yy++) {
1032                 sp = lineSrc;
1033                 dp = lineDst;
1034                 if(d1 != 0) {
1035                     tmp1 = JBIG2_GETDWORD(sp);
1036                     tmp2 = JBIG2_GETDWORD(dp);
1037                     switch(op) {
1038                         case JBIG2_COMPOSE_OR:
1039                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1040                             break;
1041                         case JBIG2_COMPOSE_AND:
1042                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1043                             break;
1044                         case JBIG2_COMPOSE_XOR:
1045                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1046                             break;
1047                         case JBIG2_COMPOSE_XNOR:
1048                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1049                             break;
1050                         case JBIG2_COMPOSE_REPLACE:
1051                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1052                             break;
1053                     }
1054                     dp[0] = (uint8_t)(tmp >> 24);
1055                     dp[1] = (uint8_t)(tmp >> 16);
1056                     dp[2] = (uint8_t)(tmp >> 8);
1057                     dp[3] = (uint8_t)tmp;
1058                     sp += 4;
1059                     dp += 4;
1060                 }
1061                 for(xx = 0; xx < middleDwords; xx++) {
1062                     tmp1 = JBIG2_GETDWORD(sp);
1063                     tmp2 = JBIG2_GETDWORD(dp);
1064                     switch(op) {
1065                         case JBIG2_COMPOSE_OR:
1066                             tmp = tmp1 | tmp2;
1067                             break;
1068                         case JBIG2_COMPOSE_AND:
1069                             tmp = tmp1 & tmp2;
1070                             break;
1071                         case JBIG2_COMPOSE_XOR:
1072                             tmp = tmp1 ^ tmp2;
1073                             break;
1074                         case JBIG2_COMPOSE_XNOR:
1075                             tmp = ~(tmp1 ^ tmp2);
1076                             break;
1077                         case JBIG2_COMPOSE_REPLACE:
1078                             tmp = tmp1;
1079                             break;
1080                     }
1081                     dp[0] = (uint8_t)(tmp >> 24);
1082                     dp[1] = (uint8_t)(tmp >> 16);
1083                     dp[2] = (uint8_t)(tmp >> 8);
1084                     dp[3] = (uint8_t)tmp;
1085                     sp += 4;
1086                     dp += 4;
1087                 }
1088                 if(d2 != 0) {
1089                     tmp1 = JBIG2_GETDWORD(sp);
1090                     tmp2 = JBIG2_GETDWORD(dp);
1091                     switch(op) {
1092                         case JBIG2_COMPOSE_OR:
1093                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1094                             break;
1095                         case JBIG2_COMPOSE_AND:
1096                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1097                             break;
1098                         case JBIG2_COMPOSE_XOR:
1099                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1100                             break;
1101                         case JBIG2_COMPOSE_XNOR:
1102                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1103                             break;
1104                         case JBIG2_COMPOSE_REPLACE:
1105                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1106                             break;
1107                     }
1108                     dp[0] = (uint8_t)(tmp >> 24);
1109                     dp[1] = (uint8_t)(tmp >> 16);
1110                     dp[2] = (uint8_t)(tmp >> 8);
1111                     dp[3] = (uint8_t)tmp;
1112                 }
1113                 lineSrc += m_nStride;
1114                 lineDst += pDst->m_nStride;
1115             }
1116         } else {
1117             shift1 = d1 - s1;
1118             shift2 = 32 - shift1;
1119             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1120             for(yy = yd0; yy < yd1; yy++) {
1121                 sp = lineSrc;
1122                 dp = lineDst;
1123                 if(d1 != 0) {
1124                     tmp1 = JBIG2_GETDWORD(sp) >> shift1;
1125                     tmp2 = JBIG2_GETDWORD(dp);
1126                     switch(op) {
1127                         case JBIG2_COMPOSE_OR:
1128                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1129                             break;
1130                         case JBIG2_COMPOSE_AND:
1131                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1132                             break;
1133                         case JBIG2_COMPOSE_XOR:
1134                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1135                             break;
1136                         case JBIG2_COMPOSE_XNOR:
1137                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1138                             break;
1139                         case JBIG2_COMPOSE_REPLACE:
1140                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1141                             break;
1142                     }
1143                     dp[0] = (uint8_t)(tmp >> 24);
1144                     dp[1] = (uint8_t)(tmp >> 16);
1145                     dp[2] = (uint8_t)(tmp >> 8);
1146                     dp[3] = (uint8_t)tmp;
1147                     dp += 4;
1148                 }
1149                 for(xx = 0; xx < middleDwords; xx++) {
1150                     tmp1 = (JBIG2_GETDWORD(sp) << shift2) | ((JBIG2_GETDWORD(sp + 4)) >> shift1);
1151                     tmp2 = JBIG2_GETDWORD(dp);
1152                     switch(op) {
1153                         case JBIG2_COMPOSE_OR:
1154                             tmp = tmp1 | tmp2;
1155                             break;
1156                         case JBIG2_COMPOSE_AND:
1157                             tmp = tmp1 & tmp2;
1158                             break;
1159                         case JBIG2_COMPOSE_XOR:
1160                             tmp = tmp1 ^ tmp2;
1161                             break;
1162                         case JBIG2_COMPOSE_XNOR:
1163                             tmp = ~(tmp1 ^ tmp2);
1164                             break;
1165                         case JBIG2_COMPOSE_REPLACE:
1166                             tmp = tmp1;
1167                             break;
1168                     }
1169                     dp[0] = (uint8_t)(tmp >> 24);
1170                     dp[1] = (uint8_t)(tmp >> 16);
1171                     dp[2] = (uint8_t)(tmp >> 8);
1172                     dp[3] = (uint8_t)tmp;
1173                     sp += 4;
1174                     dp += 4;
1175                 }
1176                 if(d2 != 0) {
1177                     tmp1 = (JBIG2_GETDWORD(sp) << shift2) | (
1178                                ((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift1);
1179                     tmp2 = JBIG2_GETDWORD(dp);
1180                     switch(op) {
1181                         case JBIG2_COMPOSE_OR:
1182                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1183                             break;
1184                         case JBIG2_COMPOSE_AND:
1185                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1186                             break;
1187                         case JBIG2_COMPOSE_XOR:
1188                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1189                             break;
1190                         case JBIG2_COMPOSE_XNOR:
1191                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1192                             break;
1193                         case JBIG2_COMPOSE_REPLACE:
1194                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1195                             break;
1196                     }
1197                     dp[0] = (uint8_t)(tmp >> 24);
1198                     dp[1] = (uint8_t)(tmp >> 16);
1199                     dp[2] = (uint8_t)(tmp >> 8);
1200                     dp[3] = (uint8_t)tmp;
1201                 }
1202                 lineSrc += m_nStride;
1203                 lineDst += pDst->m_nStride;
1204             }
1205         }
1206     }
1207     return 1;
1208 }
1209 FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op, const FX_RECT* pSrcRect)
1210 {
1211     int32_t xs0, ys0, xs1, ys1, xd0, yd0, xd1, yd1, xx, yy, w, h, middleDwords, lineLeft;
1212     FX_DWORD s1, d1, d2, shift, shift1, shift2, tmp, tmp1, tmp2, maskL, maskR, maskM;
1213     uint8_t *lineSrc, *lineDst, *sp, *dp;
1214     int32_t sw, sh;
1215     if (!m_pData) {
1216         return FALSE;
1217     }
1218     if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
1219         return FALSE;
1220     }
1221     sw = pSrcRect->Width();
1222     sh = pSrcRect->Height();
1223     if(y < 0) {
1224         ys0 = -y;
1225     } else {
1226         ys0 = 0;
1227     }
1228     if(y + sh > pDst->m_nHeight) {
1229         ys1 = pDst->m_nHeight - y;
1230     } else {
1231         ys1 = sh;
1232     }
1233     if(x < 0) {
1234         xs0 = -x;
1235     } else {
1236         xs0 = 0;
1237     }
1238     if(x + sw > pDst->m_nWidth) {
1239         xs1 = pDst->m_nWidth - x;
1240     } else {
1241         xs1 = sw;
1242     }
1243     if((ys0 >= ys1) || (xs0 >= xs1)) {
1244         return 0;
1245     }
1246     w = xs1 - xs0;
1247     h = ys1 - ys0;
1248     if(y < 0) {
1249         yd0 = 0;
1250     } else {
1251         yd0 = y;
1252     }
1253     if(x < 0) {
1254         xd0 = 0;
1255     } else {
1256         xd0 = x;
1257     }
1258     xd1 = xd0 + w;
1259     yd1 = yd0 + h;
1260     d1 = xd0 & 31;
1261     d2 = xd1 & 31;
1262     s1 = xs0 & 31;
1263     maskL = 0xffffffff >> d1;
1264     maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
1265     maskM = maskL & maskR;
1266     lineSrc = m_pData + (pSrcRect->top + ys0) * m_nStride + (((xs0 + pSrcRect->left) >> 5) << 2);
1267     lineLeft = m_nStride - ((xs0 >> 5) << 2);
1268     lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
1269     if((xd0 & ~31) == ((xd1 - 1) & ~31)) {
1270         if((xs0 & ~31) == ((xs1 - 1) & ~31)) {
1271             if(s1 > d1) {
1272                 shift = s1 - d1;
1273                 for(yy = yd0; yy < yd1; yy++) {
1274                     tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
1275                     tmp2 = JBIG2_GETDWORD(lineDst);
1276                     switch(op) {
1277                         case JBIG2_COMPOSE_OR:
1278                             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
1279                             break;
1280                         case JBIG2_COMPOSE_AND:
1281                             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
1282                             break;
1283                         case JBIG2_COMPOSE_XOR:
1284                             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
1285                             break;
1286                         case JBIG2_COMPOSE_XNOR:
1287                             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
1288                             break;
1289                         case JBIG2_COMPOSE_REPLACE:
1290                             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
1291                             break;
1292                     }
1293                     lineDst[0] = (uint8_t)(tmp >> 24);
1294                     lineDst[1] = (uint8_t)(tmp >> 16);
1295                     lineDst[2] = (uint8_t)(tmp >> 8);
1296                     lineDst[3] = (uint8_t)tmp;
1297                     lineSrc += m_nStride;
1298                     lineDst += pDst->m_nStride;
1299                 }
1300             } else {
1301                 shift = d1 - s1;
1302                 for(yy = yd0; yy < yd1; yy++) {
1303                     tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
1304                     tmp2 = JBIG2_GETDWORD(lineDst);
1305                     switch(op) {
1306                         case JBIG2_COMPOSE_OR:
1307                             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
1308                             break;
1309                         case JBIG2_COMPOSE_AND:
1310                             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
1311                             break;
1312                         case JBIG2_COMPOSE_XOR:
1313                             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
1314                             break;
1315                         case JBIG2_COMPOSE_XNOR:
1316                             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
1317                             break;
1318                         case JBIG2_COMPOSE_REPLACE:
1319                             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
1320                             break;
1321                     }
1322                     lineDst[0] = (uint8_t)(tmp >> 24);
1323                     lineDst[1] = (uint8_t)(tmp >> 16);
1324                     lineDst[2] = (uint8_t)(tmp >> 8);
1325                     lineDst[3] = (uint8_t)tmp;
1326                     lineSrc += m_nStride;
1327                     lineDst += pDst->m_nStride;
1328                 }
1329             }
1330         } else {
1331             shift1 = s1 - d1;
1332             shift2 = 32 - shift1;
1333             for(yy = yd0; yy < yd1; yy++) {
1334                 tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) | (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
1335                 tmp2 = JBIG2_GETDWORD(lineDst);
1336                 switch(op) {
1337                     case JBIG2_COMPOSE_OR:
1338                         tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
1339                         break;
1340                     case JBIG2_COMPOSE_AND:
1341                         tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
1342                         break;
1343                     case JBIG2_COMPOSE_XOR:
1344                         tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
1345                         break;
1346                     case JBIG2_COMPOSE_XNOR:
1347                         tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
1348                         break;
1349                     case JBIG2_COMPOSE_REPLACE:
1350                         tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
1351                         break;
1352                 }
1353                 lineDst[0] = (uint8_t)(tmp >> 24);
1354                 lineDst[1] = (uint8_t)(tmp >> 16);
1355                 lineDst[2] = (uint8_t)(tmp >> 8);
1356                 lineDst[3] = (uint8_t)tmp;
1357                 lineSrc += m_nStride;
1358                 lineDst += pDst->m_nStride;
1359             }
1360         }
1361     } else {
1362         if(s1 > d1) {
1363             shift1 = s1 - d1;
1364             shift2 = 32 - shift1;
1365             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1366             for(yy = yd0; yy < yd1; yy++) {
1367                 sp = lineSrc;
1368                 dp = lineDst;
1369                 if(d1 != 0) {
1370                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (JBIG2_GETDWORD(sp + 4) >> shift2);
1371                     tmp2 = JBIG2_GETDWORD(dp);
1372                     switch(op) {
1373                         case JBIG2_COMPOSE_OR:
1374                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1375                             break;
1376                         case JBIG2_COMPOSE_AND:
1377                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1378                             break;
1379                         case JBIG2_COMPOSE_XOR:
1380                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1381                             break;
1382                         case JBIG2_COMPOSE_XNOR:
1383                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1384                             break;
1385                         case JBIG2_COMPOSE_REPLACE:
1386                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1387                             break;
1388                     }
1389                     dp[0] = (uint8_t)(tmp >> 24);
1390                     dp[1] = (uint8_t)(tmp >> 16);
1391                     dp[2] = (uint8_t)(tmp >> 8);
1392                     dp[3] = (uint8_t)tmp;
1393                     sp += 4;
1394                     dp += 4;
1395                 }
1396                 for(xx = 0; xx < middleDwords; xx++) {
1397                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (JBIG2_GETDWORD(sp + 4) >> shift2);
1398                     tmp2 = JBIG2_GETDWORD(dp);
1399                     switch(op) {
1400                         case JBIG2_COMPOSE_OR:
1401                             tmp = tmp1 | tmp2;
1402                             break;
1403                         case JBIG2_COMPOSE_AND:
1404                             tmp = tmp1 & tmp2;
1405                             break;
1406                         case JBIG2_COMPOSE_XOR:
1407                             tmp = tmp1 ^ tmp2;
1408                             break;
1409                         case JBIG2_COMPOSE_XNOR:
1410                             tmp = ~(tmp1 ^ tmp2);
1411                             break;
1412                         case JBIG2_COMPOSE_REPLACE:
1413                             tmp = tmp1;
1414                             break;
1415                     }
1416                     dp[0] = (uint8_t)(tmp >> 24);
1417                     dp[1] = (uint8_t)(tmp >> 16);
1418                     dp[2] = (uint8_t)(tmp >> 8);
1419                     dp[3] = (uint8_t)tmp;
1420                     sp += 4;
1421                     dp += 4;
1422                 }
1423                 if(d2 != 0) {
1424                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (
1425                                ((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift2);
1426                     tmp2 = JBIG2_GETDWORD(dp);
1427                     switch(op) {
1428                         case JBIG2_COMPOSE_OR:
1429                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1430                             break;
1431                         case JBIG2_COMPOSE_AND:
1432                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1433                             break;
1434                         case JBIG2_COMPOSE_XOR:
1435                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1436                             break;
1437                         case JBIG2_COMPOSE_XNOR:
1438                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1439                             break;
1440                         case JBIG2_COMPOSE_REPLACE:
1441                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1442                             break;
1443                     }
1444                     dp[0] = (uint8_t)(tmp >> 24);
1445                     dp[1] = (uint8_t)(tmp >> 16);
1446                     dp[2] = (uint8_t)(tmp >> 8);
1447                     dp[3] = (uint8_t)tmp;
1448                 }
1449                 lineSrc += m_nStride;
1450                 lineDst += pDst->m_nStride;
1451             }
1452         } else if(s1 == d1) {
1453             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1454             for(yy = yd0; yy < yd1; yy++) {
1455                 sp = lineSrc;
1456                 dp = lineDst;
1457                 if(d1 != 0) {
1458                     tmp1 = JBIG2_GETDWORD(sp);
1459                     tmp2 = JBIG2_GETDWORD(dp);
1460                     switch(op) {
1461                         case JBIG2_COMPOSE_OR:
1462                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1463                             break;
1464                         case JBIG2_COMPOSE_AND:
1465                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1466                             break;
1467                         case JBIG2_COMPOSE_XOR:
1468                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1469                             break;
1470                         case JBIG2_COMPOSE_XNOR:
1471                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1472                             break;
1473                         case JBIG2_COMPOSE_REPLACE:
1474                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1475                             break;
1476                     }
1477                     dp[0] = (uint8_t)(tmp >> 24);
1478                     dp[1] = (uint8_t)(tmp >> 16);
1479                     dp[2] = (uint8_t)(tmp >> 8);
1480                     dp[3] = (uint8_t)tmp;
1481                     sp += 4;
1482                     dp += 4;
1483                 }
1484                 for(xx = 0; xx < middleDwords; xx++) {
1485                     tmp1 = JBIG2_GETDWORD(sp);
1486                     tmp2 = JBIG2_GETDWORD(dp);
1487                     switch(op) {
1488                         case JBIG2_COMPOSE_OR:
1489                             tmp = tmp1 | tmp2;
1490                             break;
1491                         case JBIG2_COMPOSE_AND:
1492                             tmp = tmp1 & tmp2;
1493                             break;
1494                         case JBIG2_COMPOSE_XOR:
1495                             tmp = tmp1 ^ tmp2;
1496                             break;
1497                         case JBIG2_COMPOSE_XNOR:
1498                             tmp = ~(tmp1 ^ tmp2);
1499                             break;
1500                         case JBIG2_COMPOSE_REPLACE:
1501                             tmp = tmp1;
1502                             break;
1503                     }
1504                     dp[0] = (uint8_t)(tmp >> 24);
1505                     dp[1] = (uint8_t)(tmp >> 16);
1506                     dp[2] = (uint8_t)(tmp >> 8);
1507                     dp[3] = (uint8_t)tmp;
1508                     sp += 4;
1509                     dp += 4;
1510                 }
1511                 if(d2 != 0) {
1512                     tmp1 = JBIG2_GETDWORD(sp);
1513                     tmp2 = JBIG2_GETDWORD(dp);
1514                     switch(op) {
1515                         case JBIG2_COMPOSE_OR:
1516                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1517                             break;
1518                         case JBIG2_COMPOSE_AND:
1519                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1520                             break;
1521                         case JBIG2_COMPOSE_XOR:
1522                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1523                             break;
1524                         case JBIG2_COMPOSE_XNOR:
1525                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1526                             break;
1527                         case JBIG2_COMPOSE_REPLACE:
1528                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1529                             break;
1530                     }
1531                     dp[0] = (uint8_t)(tmp >> 24);
1532                     dp[1] = (uint8_t)(tmp >> 16);
1533                     dp[2] = (uint8_t)(tmp >> 8);
1534                     dp[3] = (uint8_t)tmp;
1535                 }
1536                 lineSrc += m_nStride;
1537                 lineDst += pDst->m_nStride;
1538             }
1539         } else {
1540             shift1 = d1 - s1;
1541             shift2 = 32 - shift1;
1542             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1543             for(yy = yd0; yy < yd1; yy++) {
1544                 sp = lineSrc;
1545                 dp = lineDst;
1546                 if(d1 != 0) {
1547                     tmp1 = JBIG2_GETDWORD(sp) >> shift1;
1548                     tmp2 = JBIG2_GETDWORD(dp);
1549                     switch(op) {
1550                         case JBIG2_COMPOSE_OR:
1551                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1552                             break;
1553                         case JBIG2_COMPOSE_AND:
1554                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1555                             break;
1556                         case JBIG2_COMPOSE_XOR:
1557                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1558                             break;
1559                         case JBIG2_COMPOSE_XNOR:
1560                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1561                             break;
1562                         case JBIG2_COMPOSE_REPLACE:
1563                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1564                             break;
1565                     }
1566                     dp[0] = (uint8_t)(tmp >> 24);
1567                     dp[1] = (uint8_t)(tmp >> 16);
1568                     dp[2] = (uint8_t)(tmp >> 8);
1569                     dp[3] = (uint8_t)tmp;
1570                     dp += 4;
1571                 }
1572                 for(xx = 0; xx < middleDwords; xx++) {
1573                     tmp1 = (JBIG2_GETDWORD(sp) << shift2) | ((JBIG2_GETDWORD(sp + 4)) >> shift1);
1574                     tmp2 = JBIG2_GETDWORD(dp);
1575                     switch(op) {
1576                         case JBIG2_COMPOSE_OR:
1577                             tmp = tmp1 | tmp2;
1578                             break;
1579                         case JBIG2_COMPOSE_AND:
1580                             tmp = tmp1 & tmp2;
1581                             break;
1582                         case JBIG2_COMPOSE_XOR:
1583                             tmp = tmp1 ^ tmp2;
1584                             break;
1585                         case JBIG2_COMPOSE_XNOR:
1586                             tmp = ~(tmp1 ^ tmp2);
1587                             break;
1588                         case JBIG2_COMPOSE_REPLACE:
1589                             tmp = tmp1;
1590                             break;
1591                     }
1592                     dp[0] = (uint8_t)(tmp >> 24);
1593                     dp[1] = (uint8_t)(tmp >> 16);
1594                     dp[2] = (uint8_t)(tmp >> 8);
1595                     dp[3] = (uint8_t)tmp;
1596                     sp += 4;
1597                     dp += 4;
1598                 }
1599                 if(d2 != 0) {
1600                     tmp1 = (JBIG2_GETDWORD(sp) << shift2) | (
1601                                ((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift1);
1602                     tmp2 = JBIG2_GETDWORD(dp);
1603                     switch(op) {
1604                         case JBIG2_COMPOSE_OR:
1605                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1606                             break;
1607                         case JBIG2_COMPOSE_AND:
1608                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1609                             break;
1610                         case JBIG2_COMPOSE_XOR:
1611                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1612                             break;
1613                         case JBIG2_COMPOSE_XNOR:
1614                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1615                             break;
1616                         case JBIG2_COMPOSE_REPLACE:
1617                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1618                             break;
1619                     }
1620                     dp[0] = (uint8_t)(tmp >> 24);
1621                     dp[1] = (uint8_t)(tmp >> 16);
1622                     dp[2] = (uint8_t)(tmp >> 8);
1623                     dp[3] = (uint8_t)tmp;
1624                 }
1625                 lineSrc += m_nStride;
1626                 lineDst += pDst->m_nStride;
1627             }
1628         }
1629     }
1630     return 1;
1631 }