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