_FETAL => _FATAL.
[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_coordinates.h"
10 #include "../../../include/fxcrt/fx_safe_types.h"
11 #include "JBig2_Image.h"
12
13 CJBig2_Image::CJBig2_Image(int32_t w, int32_t 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 = (uint8_t *)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(int32_t w, int32_t h, int32_t stride, uint8_t*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 = (uint8_t*)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(int32_t x, int32_t y)
59 {
60     if (!m_pData) {
61         return 0;
62     }
63     int32_t 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 int32_t CJBig2_Image::setPixel(int32_t x, int32_t y, FX_BOOL v)
76 {
77     if (!m_pData) {
78         return 0;
79     }
80     int32_t 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(int32_t hTo, int32_t 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, int32_t x, int32_t 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, int32_t x, int32_t 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, int32_t x, int32_t y, JBig2ComposeOp op)
132 {
133     int32_t w, h, dx, dy;
134     int32_t 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, int32_t x, int32_t y, JBig2ComposeOp op)
199 {
200     int32_t x0, x1, y0, y1, xx, yy;
201     uint8_t *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 = (uint8_t)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 = (uint8_t)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 = (uint8_t)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 = (uint8_t)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 = (uint8_t)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 = (uint8_t)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 = (uint8_t)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 = (uint8_t)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 = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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++ = (uint8_t)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 = (uint8_t)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(int32_t x, int32_t 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(int32_t x, int32_t 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(int32_t x, int32_t y, int32_t w, int32_t h)
699 {
700     CJBig2_Image *pImage;
701     int32_t 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(int32_t x, int32_t y, int32_t w, int32_t h)
712 {
713     CJBig2_Image *pImage;
714     int32_t m, n, j;
715     uint8_t *pLineSrc, *pLineDst;
716     FX_DWORD wTmp;
717     uint8_t *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] = (uint8_t)(wTmp >> 24);
758                 pDst[1] = (uint8_t)(wTmp >> 16);
759                 pDst[2] = (uint8_t)(wTmp >> 8);
760                 pDst[3] = (uint8_t)wTmp;
761             }
762             pLineSrc += m_nStride;
763             pLineDst += pImage->m_nStride;
764         }
765     }
766     return pImage;
767 }
768 void CJBig2_Image::expand(int32_t h, FX_BOOL v)
769 {
770     if (!m_pData || h <= m_nHeight) {
771         return;
772     }
773     FX_DWORD dwH = pdfium::base::checked_cast<FX_DWORD>(h);
774     FX_DWORD dwStride = pdfium::base::checked_cast<FX_DWORD>(m_nStride);
775     FX_DWORD dwHeight = pdfium::base::checked_cast<FX_DWORD>(m_nHeight);
776     FX_SAFE_DWORD safeMemSize = dwH; 
777     safeMemSize *= dwStride;
778     if (!safeMemSize.IsValid()) {
779         return;
780     }
781     //The guaranteed reallocated memory is to be < 4GB (unsigned int). 
782     m_pData = (uint8_t*)m_pModule->JBig2_Realloc(m_pData, safeMemSize.ValueOrDie());
783     //The result of dwHeight * dwStride doesn't overflow after the 
784     //checking of safeMemSize.
785     //The same as the result of (dwH - dwHeight) * dwStride) because
786     //dwH - dwHeight is always less than dwH(h) which is checked in
787     //the calculation of dwH * dwStride. 
788     JBIG2_memset(m_pData + dwHeight * dwStride, v ? 0xff : 0, (dwH - dwHeight) * dwStride);
789     m_nHeight = h;
790 }
791 FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op)
792 {
793     int32_t xs0 = 0, ys0  = 0, xs1  = 0, ys1   = 0, xd0    = 0, yd0          = 0, xd1      = 0, 
794              yd1 = 0, xx   = 0, yy   = 0, w     = 0, h      = 0, middleDwords = 0, lineLeft = 0;
795
796     FX_DWORD s1  = 0, d1   = 0, d2   = 0, shift = 0, shift1 = 0, shift2       = 0, 
797              tmp = 0, tmp1 = 0, tmp2 = 0, maskL = 0, maskR  = 0, maskM        = 0;
798
799     uint8_t *lineSrc = NULL, *lineDst = NULL, *sp = NULL, *dp = NULL;
800
801     if (!m_pData) {
802         return FALSE;
803     }
804     if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
805         return FALSE;
806     }
807     if(y < 0) {
808         ys0 = -y;
809     }
810     if(y + m_nHeight > pDst->m_nHeight) {
811         ys1 = pDst->m_nHeight - y;
812     } else {
813         ys1 = m_nHeight;
814     }
815     if(x < 0) {
816         xs0 = -x;
817     }
818     if(x + m_nWidth > pDst->m_nWidth) {
819         xs1 = pDst->m_nWidth - x;
820     } else {
821         xs1 = m_nWidth;
822     }
823     if((ys0 >= ys1) || (xs0 >= xs1)) {
824         return 0;
825     }
826     w = xs1 - xs0;
827     h = ys1 - ys0;
828     if(y >= 0) {
829         yd0 = y;
830     } 
831     if(x >= 0) {
832         xd0 = x;
833     }
834     xd1 = xd0 + w;
835     yd1 = yd0 + h;
836     d1 = xd0 & 31;
837     d2 = xd1 & 31;
838     s1 = xs0 & 31;
839     maskL = 0xffffffff >> d1;
840     maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
841     maskM = maskL & maskR;
842     lineSrc = m_pData + ys0 * m_nStride + ((xs0 >> 5) << 2);
843     lineLeft = m_nStride - ((xs0 >> 5) << 2);
844     lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
845     if((xd0 & ~31) == ((xd1 - 1) & ~31)) {
846         if((xs0 & ~31) == ((xs1 - 1) & ~31)) {
847             if(s1 > d1) {
848                 shift = s1 - d1;
849                 for(yy = yd0; yy < yd1; yy++) {
850                     tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
851                     tmp2 = JBIG2_GETDWORD(lineDst);
852                     switch(op) {
853                         case JBIG2_COMPOSE_OR:
854                             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
855                             break;
856                         case JBIG2_COMPOSE_AND:
857                             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
858                             break;
859                         case JBIG2_COMPOSE_XOR:
860                             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
861                             break;
862                         case JBIG2_COMPOSE_XNOR:
863                             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
864                             break;
865                         case JBIG2_COMPOSE_REPLACE:
866                             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
867                             break;
868                     }
869                     lineDst[0] = (uint8_t)(tmp >> 24);
870                     lineDst[1] = (uint8_t)(tmp >> 16);
871                     lineDst[2] = (uint8_t)(tmp >> 8);
872                     lineDst[3] = (uint8_t)tmp;
873                     lineSrc += m_nStride;
874                     lineDst += pDst->m_nStride;
875                 }
876             } else {
877                 shift = d1 - s1;
878                 for(yy = yd0; yy < yd1; yy++) {
879                     tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
880                     tmp2 = JBIG2_GETDWORD(lineDst);
881                     switch(op) {
882                         case JBIG2_COMPOSE_OR:
883                             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
884                             break;
885                         case JBIG2_COMPOSE_AND:
886                             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
887                             break;
888                         case JBIG2_COMPOSE_XOR:
889                             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
890                             break;
891                         case JBIG2_COMPOSE_XNOR:
892                             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
893                             break;
894                         case JBIG2_COMPOSE_REPLACE:
895                             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
896                             break;
897                     }
898                     lineDst[0] = (uint8_t)(tmp >> 24);
899                     lineDst[1] = (uint8_t)(tmp >> 16);
900                     lineDst[2] = (uint8_t)(tmp >> 8);
901                     lineDst[3] = (uint8_t)tmp;
902                     lineSrc += m_nStride;
903                     lineDst += pDst->m_nStride;
904                 }
905             }
906         } else {
907             shift1 = s1 - d1;
908             shift2 = 32 - shift1;
909             for(yy = yd0; yy < yd1; yy++) {
910                 tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) | (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
911                 tmp2 = JBIG2_GETDWORD(lineDst);
912                 switch(op) {
913                     case JBIG2_COMPOSE_OR:
914                         tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
915                         break;
916                     case JBIG2_COMPOSE_AND:
917                         tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
918                         break;
919                     case JBIG2_COMPOSE_XOR:
920                         tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
921                         break;
922                     case JBIG2_COMPOSE_XNOR:
923                         tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
924                         break;
925                     case JBIG2_COMPOSE_REPLACE:
926                         tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
927                         break;
928                 }
929                 lineDst[0] = (uint8_t)(tmp >> 24);
930                 lineDst[1] = (uint8_t)(tmp >> 16);
931                 lineDst[2] = (uint8_t)(tmp >> 8);
932                 lineDst[3] = (uint8_t)tmp;
933                 lineSrc += m_nStride;
934                 lineDst += pDst->m_nStride;
935             }
936         }
937     } else {
938         if(s1 > d1) {
939             shift1 = s1 - d1;
940             shift2 = 32 - shift1;
941             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
942             for(yy = yd0; yy < yd1; yy++) {
943                 sp = lineSrc;
944                 dp = lineDst;
945                 if(d1 != 0) {
946                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (JBIG2_GETDWORD(sp + 4) >> shift2);
947                     tmp2 = JBIG2_GETDWORD(dp);
948                     switch(op) {
949                         case JBIG2_COMPOSE_OR:
950                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
951                             break;
952                         case JBIG2_COMPOSE_AND:
953                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
954                             break;
955                         case JBIG2_COMPOSE_XOR:
956                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
957                             break;
958                         case JBIG2_COMPOSE_XNOR:
959                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
960                             break;
961                         case JBIG2_COMPOSE_REPLACE:
962                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
963                             break;
964                     }
965                     dp[0] = (uint8_t)(tmp >> 24);
966                     dp[1] = (uint8_t)(tmp >> 16);
967                     dp[2] = (uint8_t)(tmp >> 8);
968                     dp[3] = (uint8_t)tmp;
969                     sp += 4;
970                     dp += 4;
971                 }
972                 for(xx = 0; xx < middleDwords; xx++) {
973                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (JBIG2_GETDWORD(sp + 4) >> shift2);
974                     tmp2 = JBIG2_GETDWORD(dp);
975                     switch(op) {
976                         case JBIG2_COMPOSE_OR:
977                             tmp = tmp1 | tmp2;
978                             break;
979                         case JBIG2_COMPOSE_AND:
980                             tmp = tmp1 & tmp2;
981                             break;
982                         case JBIG2_COMPOSE_XOR:
983                             tmp = tmp1 ^ tmp2;
984                             break;
985                         case JBIG2_COMPOSE_XNOR:
986                             tmp = ~(tmp1 ^ tmp2);
987                             break;
988                         case JBIG2_COMPOSE_REPLACE:
989                             tmp = tmp1;
990                             break;
991                     }
992                     dp[0] = (uint8_t)(tmp >> 24);
993                     dp[1] = (uint8_t)(tmp >> 16);
994                     dp[2] = (uint8_t)(tmp >> 8);
995                     dp[3] = (uint8_t)tmp;
996                     sp += 4;
997                     dp += 4;
998                 }
999                 if(d2 != 0) {
1000                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (
1001                                ((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift2);
1002                     tmp2 = JBIG2_GETDWORD(dp);
1003                     switch(op) {
1004                         case JBIG2_COMPOSE_OR:
1005                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1006                             break;
1007                         case JBIG2_COMPOSE_AND:
1008                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1009                             break;
1010                         case JBIG2_COMPOSE_XOR:
1011                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1012                             break;
1013                         case JBIG2_COMPOSE_XNOR:
1014                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1015                             break;
1016                         case JBIG2_COMPOSE_REPLACE:
1017                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1018                             break;
1019                     }
1020                     dp[0] = (uint8_t)(tmp >> 24);
1021                     dp[1] = (uint8_t)(tmp >> 16);
1022                     dp[2] = (uint8_t)(tmp >> 8);
1023                     dp[3] = (uint8_t)tmp;
1024                 }
1025                 lineSrc += m_nStride;
1026                 lineDst += pDst->m_nStride;
1027             }
1028         } else if(s1 == d1) {
1029             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1030             for(yy = yd0; yy < yd1; yy++) {
1031                 sp = lineSrc;
1032                 dp = lineDst;
1033                 if(d1 != 0) {
1034                     tmp1 = JBIG2_GETDWORD(sp);
1035                     tmp2 = JBIG2_GETDWORD(dp);
1036                     switch(op) {
1037                         case JBIG2_COMPOSE_OR:
1038                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1039                             break;
1040                         case JBIG2_COMPOSE_AND:
1041                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1042                             break;
1043                         case JBIG2_COMPOSE_XOR:
1044                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1045                             break;
1046                         case JBIG2_COMPOSE_XNOR:
1047                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1048                             break;
1049                         case JBIG2_COMPOSE_REPLACE:
1050                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1051                             break;
1052                     }
1053                     dp[0] = (uint8_t)(tmp >> 24);
1054                     dp[1] = (uint8_t)(tmp >> 16);
1055                     dp[2] = (uint8_t)(tmp >> 8);
1056                     dp[3] = (uint8_t)tmp;
1057                     sp += 4;
1058                     dp += 4;
1059                 }
1060                 for(xx = 0; xx < middleDwords; xx++) {
1061                     tmp1 = JBIG2_GETDWORD(sp);
1062                     tmp2 = JBIG2_GETDWORD(dp);
1063                     switch(op) {
1064                         case JBIG2_COMPOSE_OR:
1065                             tmp = tmp1 | tmp2;
1066                             break;
1067                         case JBIG2_COMPOSE_AND:
1068                             tmp = tmp1 & tmp2;
1069                             break;
1070                         case JBIG2_COMPOSE_XOR:
1071                             tmp = tmp1 ^ tmp2;
1072                             break;
1073                         case JBIG2_COMPOSE_XNOR:
1074                             tmp = ~(tmp1 ^ tmp2);
1075                             break;
1076                         case JBIG2_COMPOSE_REPLACE:
1077                             tmp = tmp1;
1078                             break;
1079                     }
1080                     dp[0] = (uint8_t)(tmp >> 24);
1081                     dp[1] = (uint8_t)(tmp >> 16);
1082                     dp[2] = (uint8_t)(tmp >> 8);
1083                     dp[3] = (uint8_t)tmp;
1084                     sp += 4;
1085                     dp += 4;
1086                 }
1087                 if(d2 != 0) {
1088                     tmp1 = JBIG2_GETDWORD(sp);
1089                     tmp2 = JBIG2_GETDWORD(dp);
1090                     switch(op) {
1091                         case JBIG2_COMPOSE_OR:
1092                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1093                             break;
1094                         case JBIG2_COMPOSE_AND:
1095                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1096                             break;
1097                         case JBIG2_COMPOSE_XOR:
1098                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1099                             break;
1100                         case JBIG2_COMPOSE_XNOR:
1101                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1102                             break;
1103                         case JBIG2_COMPOSE_REPLACE:
1104                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1105                             break;
1106                     }
1107                     dp[0] = (uint8_t)(tmp >> 24);
1108                     dp[1] = (uint8_t)(tmp >> 16);
1109                     dp[2] = (uint8_t)(tmp >> 8);
1110                     dp[3] = (uint8_t)tmp;
1111                 }
1112                 lineSrc += m_nStride;
1113                 lineDst += pDst->m_nStride;
1114             }
1115         } else {
1116             shift1 = d1 - s1;
1117             shift2 = 32 - shift1;
1118             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1119             for(yy = yd0; yy < yd1; yy++) {
1120                 sp = lineSrc;
1121                 dp = lineDst;
1122                 if(d1 != 0) {
1123                     tmp1 = JBIG2_GETDWORD(sp) >> shift1;
1124                     tmp2 = JBIG2_GETDWORD(dp);
1125                     switch(op) {
1126                         case JBIG2_COMPOSE_OR:
1127                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1128                             break;
1129                         case JBIG2_COMPOSE_AND:
1130                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1131                             break;
1132                         case JBIG2_COMPOSE_XOR:
1133                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1134                             break;
1135                         case JBIG2_COMPOSE_XNOR:
1136                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1137                             break;
1138                         case JBIG2_COMPOSE_REPLACE:
1139                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1140                             break;
1141                     }
1142                     dp[0] = (uint8_t)(tmp >> 24);
1143                     dp[1] = (uint8_t)(tmp >> 16);
1144                     dp[2] = (uint8_t)(tmp >> 8);
1145                     dp[3] = (uint8_t)tmp;
1146                     dp += 4;
1147                 }
1148                 for(xx = 0; xx < middleDwords; xx++) {
1149                     tmp1 = (JBIG2_GETDWORD(sp) << shift2) | ((JBIG2_GETDWORD(sp + 4)) >> shift1);
1150                     tmp2 = JBIG2_GETDWORD(dp);
1151                     switch(op) {
1152                         case JBIG2_COMPOSE_OR:
1153                             tmp = tmp1 | tmp2;
1154                             break;
1155                         case JBIG2_COMPOSE_AND:
1156                             tmp = tmp1 & tmp2;
1157                             break;
1158                         case JBIG2_COMPOSE_XOR:
1159                             tmp = tmp1 ^ tmp2;
1160                             break;
1161                         case JBIG2_COMPOSE_XNOR:
1162                             tmp = ~(tmp1 ^ tmp2);
1163                             break;
1164                         case JBIG2_COMPOSE_REPLACE:
1165                             tmp = tmp1;
1166                             break;
1167                     }
1168                     dp[0] = (uint8_t)(tmp >> 24);
1169                     dp[1] = (uint8_t)(tmp >> 16);
1170                     dp[2] = (uint8_t)(tmp >> 8);
1171                     dp[3] = (uint8_t)tmp;
1172                     sp += 4;
1173                     dp += 4;
1174                 }
1175                 if(d2 != 0) {
1176                     tmp1 = (JBIG2_GETDWORD(sp) << shift2) | (
1177                                ((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift1);
1178                     tmp2 = JBIG2_GETDWORD(dp);
1179                     switch(op) {
1180                         case JBIG2_COMPOSE_OR:
1181                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1182                             break;
1183                         case JBIG2_COMPOSE_AND:
1184                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1185                             break;
1186                         case JBIG2_COMPOSE_XOR:
1187                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1188                             break;
1189                         case JBIG2_COMPOSE_XNOR:
1190                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1191                             break;
1192                         case JBIG2_COMPOSE_REPLACE:
1193                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1194                             break;
1195                     }
1196                     dp[0] = (uint8_t)(tmp >> 24);
1197                     dp[1] = (uint8_t)(tmp >> 16);
1198                     dp[2] = (uint8_t)(tmp >> 8);
1199                     dp[3] = (uint8_t)tmp;
1200                 }
1201                 lineSrc += m_nStride;
1202                 lineDst += pDst->m_nStride;
1203             }
1204         }
1205     }
1206     return 1;
1207 }
1208 FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op, const FX_RECT* pSrcRect)
1209 {
1210     int32_t xs0, ys0, xs1, ys1, xd0, yd0, xd1, yd1, xx, yy, w, h, middleDwords, lineLeft;
1211     FX_DWORD s1, d1, d2, shift, shift1, shift2, tmp, tmp1, tmp2, maskL, maskR, maskM;
1212     uint8_t *lineSrc, *lineDst, *sp, *dp;
1213     int32_t sw, sh;
1214     if (!m_pData) {
1215         return FALSE;
1216     }
1217     if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
1218         return FALSE;
1219     }
1220     sw = pSrcRect->Width();
1221     sh = pSrcRect->Height();
1222     if(y < 0) {
1223         ys0 = -y;
1224     } else {
1225         ys0 = 0;
1226     }
1227     if(y + sh > pDst->m_nHeight) {
1228         ys1 = pDst->m_nHeight - y;
1229     } else {
1230         ys1 = sh;
1231     }
1232     if(x < 0) {
1233         xs0 = -x;
1234     } else {
1235         xs0 = 0;
1236     }
1237     if(x + sw > pDst->m_nWidth) {
1238         xs1 = pDst->m_nWidth - x;
1239     } else {
1240         xs1 = sw;
1241     }
1242     if((ys0 >= ys1) || (xs0 >= xs1)) {
1243         return 0;
1244     }
1245     w = xs1 - xs0;
1246     h = ys1 - ys0;
1247     if(y < 0) {
1248         yd0 = 0;
1249     } else {
1250         yd0 = y;
1251     }
1252     if(x < 0) {
1253         xd0 = 0;
1254     } else {
1255         xd0 = x;
1256     }
1257     xd1 = xd0 + w;
1258     yd1 = yd0 + h;
1259     d1 = xd0 & 31;
1260     d2 = xd1 & 31;
1261     s1 = xs0 & 31;
1262     maskL = 0xffffffff >> d1;
1263     maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
1264     maskM = maskL & maskR;
1265     lineSrc = m_pData + (pSrcRect->top + ys0) * m_nStride + (((xs0 + pSrcRect->left) >> 5) << 2);
1266     lineLeft = m_nStride - ((xs0 >> 5) << 2);
1267     lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
1268     if((xd0 & ~31) == ((xd1 - 1) & ~31)) {
1269         if((xs0 & ~31) == ((xs1 - 1) & ~31)) {
1270             if(s1 > d1) {
1271                 shift = s1 - d1;
1272                 for(yy = yd0; yy < yd1; yy++) {
1273                     tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
1274                     tmp2 = JBIG2_GETDWORD(lineDst);
1275                     switch(op) {
1276                         case JBIG2_COMPOSE_OR:
1277                             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
1278                             break;
1279                         case JBIG2_COMPOSE_AND:
1280                             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
1281                             break;
1282                         case JBIG2_COMPOSE_XOR:
1283                             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
1284                             break;
1285                         case JBIG2_COMPOSE_XNOR:
1286                             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
1287                             break;
1288                         case JBIG2_COMPOSE_REPLACE:
1289                             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
1290                             break;
1291                     }
1292                     lineDst[0] = (uint8_t)(tmp >> 24);
1293                     lineDst[1] = (uint8_t)(tmp >> 16);
1294                     lineDst[2] = (uint8_t)(tmp >> 8);
1295                     lineDst[3] = (uint8_t)tmp;
1296                     lineSrc += m_nStride;
1297                     lineDst += pDst->m_nStride;
1298                 }
1299             } else {
1300                 shift = d1 - s1;
1301                 for(yy = yd0; yy < yd1; yy++) {
1302                     tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
1303                     tmp2 = JBIG2_GETDWORD(lineDst);
1304                     switch(op) {
1305                         case JBIG2_COMPOSE_OR:
1306                             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
1307                             break;
1308                         case JBIG2_COMPOSE_AND:
1309                             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
1310                             break;
1311                         case JBIG2_COMPOSE_XOR:
1312                             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
1313                             break;
1314                         case JBIG2_COMPOSE_XNOR:
1315                             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
1316                             break;
1317                         case JBIG2_COMPOSE_REPLACE:
1318                             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
1319                             break;
1320                     }
1321                     lineDst[0] = (uint8_t)(tmp >> 24);
1322                     lineDst[1] = (uint8_t)(tmp >> 16);
1323                     lineDst[2] = (uint8_t)(tmp >> 8);
1324                     lineDst[3] = (uint8_t)tmp;
1325                     lineSrc += m_nStride;
1326                     lineDst += pDst->m_nStride;
1327                 }
1328             }
1329         } else {
1330             shift1 = s1 - d1;
1331             shift2 = 32 - shift1;
1332             for(yy = yd0; yy < yd1; yy++) {
1333                 tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) | (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
1334                 tmp2 = JBIG2_GETDWORD(lineDst);
1335                 switch(op) {
1336                     case JBIG2_COMPOSE_OR:
1337                         tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
1338                         break;
1339                     case JBIG2_COMPOSE_AND:
1340                         tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
1341                         break;
1342                     case JBIG2_COMPOSE_XOR:
1343                         tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
1344                         break;
1345                     case JBIG2_COMPOSE_XNOR:
1346                         tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
1347                         break;
1348                     case JBIG2_COMPOSE_REPLACE:
1349                         tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
1350                         break;
1351                 }
1352                 lineDst[0] = (uint8_t)(tmp >> 24);
1353                 lineDst[1] = (uint8_t)(tmp >> 16);
1354                 lineDst[2] = (uint8_t)(tmp >> 8);
1355                 lineDst[3] = (uint8_t)tmp;
1356                 lineSrc += m_nStride;
1357                 lineDst += pDst->m_nStride;
1358             }
1359         }
1360     } else {
1361         if(s1 > d1) {
1362             shift1 = s1 - d1;
1363             shift2 = 32 - shift1;
1364             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1365             for(yy = yd0; yy < yd1; yy++) {
1366                 sp = lineSrc;
1367                 dp = lineDst;
1368                 if(d1 != 0) {
1369                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (JBIG2_GETDWORD(sp + 4) >> shift2);
1370                     tmp2 = JBIG2_GETDWORD(dp);
1371                     switch(op) {
1372                         case JBIG2_COMPOSE_OR:
1373                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1374                             break;
1375                         case JBIG2_COMPOSE_AND:
1376                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1377                             break;
1378                         case JBIG2_COMPOSE_XOR:
1379                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1380                             break;
1381                         case JBIG2_COMPOSE_XNOR:
1382                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1383                             break;
1384                         case JBIG2_COMPOSE_REPLACE:
1385                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1386                             break;
1387                     }
1388                     dp[0] = (uint8_t)(tmp >> 24);
1389                     dp[1] = (uint8_t)(tmp >> 16);
1390                     dp[2] = (uint8_t)(tmp >> 8);
1391                     dp[3] = (uint8_t)tmp;
1392                     sp += 4;
1393                     dp += 4;
1394                 }
1395                 for(xx = 0; xx < middleDwords; xx++) {
1396                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (JBIG2_GETDWORD(sp + 4) >> shift2);
1397                     tmp2 = JBIG2_GETDWORD(dp);
1398                     switch(op) {
1399                         case JBIG2_COMPOSE_OR:
1400                             tmp = tmp1 | tmp2;
1401                             break;
1402                         case JBIG2_COMPOSE_AND:
1403                             tmp = tmp1 & tmp2;
1404                             break;
1405                         case JBIG2_COMPOSE_XOR:
1406                             tmp = tmp1 ^ tmp2;
1407                             break;
1408                         case JBIG2_COMPOSE_XNOR:
1409                             tmp = ~(tmp1 ^ tmp2);
1410                             break;
1411                         case JBIG2_COMPOSE_REPLACE:
1412                             tmp = tmp1;
1413                             break;
1414                     }
1415                     dp[0] = (uint8_t)(tmp >> 24);
1416                     dp[1] = (uint8_t)(tmp >> 16);
1417                     dp[2] = (uint8_t)(tmp >> 8);
1418                     dp[3] = (uint8_t)tmp;
1419                     sp += 4;
1420                     dp += 4;
1421                 }
1422                 if(d2 != 0) {
1423                     tmp1 = (JBIG2_GETDWORD(sp) << shift1) | (
1424                                ((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift2);
1425                     tmp2 = JBIG2_GETDWORD(dp);
1426                     switch(op) {
1427                         case JBIG2_COMPOSE_OR:
1428                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1429                             break;
1430                         case JBIG2_COMPOSE_AND:
1431                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1432                             break;
1433                         case JBIG2_COMPOSE_XOR:
1434                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1435                             break;
1436                         case JBIG2_COMPOSE_XNOR:
1437                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1438                             break;
1439                         case JBIG2_COMPOSE_REPLACE:
1440                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1441                             break;
1442                     }
1443                     dp[0] = (uint8_t)(tmp >> 24);
1444                     dp[1] = (uint8_t)(tmp >> 16);
1445                     dp[2] = (uint8_t)(tmp >> 8);
1446                     dp[3] = (uint8_t)tmp;
1447                 }
1448                 lineSrc += m_nStride;
1449                 lineDst += pDst->m_nStride;
1450             }
1451         } else if(s1 == d1) {
1452             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1453             for(yy = yd0; yy < yd1; yy++) {
1454                 sp = lineSrc;
1455                 dp = lineDst;
1456                 if(d1 != 0) {
1457                     tmp1 = JBIG2_GETDWORD(sp);
1458                     tmp2 = JBIG2_GETDWORD(dp);
1459                     switch(op) {
1460                         case JBIG2_COMPOSE_OR:
1461                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1462                             break;
1463                         case JBIG2_COMPOSE_AND:
1464                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1465                             break;
1466                         case JBIG2_COMPOSE_XOR:
1467                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1468                             break;
1469                         case JBIG2_COMPOSE_XNOR:
1470                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1471                             break;
1472                         case JBIG2_COMPOSE_REPLACE:
1473                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1474                             break;
1475                     }
1476                     dp[0] = (uint8_t)(tmp >> 24);
1477                     dp[1] = (uint8_t)(tmp >> 16);
1478                     dp[2] = (uint8_t)(tmp >> 8);
1479                     dp[3] = (uint8_t)tmp;
1480                     sp += 4;
1481                     dp += 4;
1482                 }
1483                 for(xx = 0; xx < middleDwords; xx++) {
1484                     tmp1 = JBIG2_GETDWORD(sp);
1485                     tmp2 = JBIG2_GETDWORD(dp);
1486                     switch(op) {
1487                         case JBIG2_COMPOSE_OR:
1488                             tmp = tmp1 | tmp2;
1489                             break;
1490                         case JBIG2_COMPOSE_AND:
1491                             tmp = tmp1 & tmp2;
1492                             break;
1493                         case JBIG2_COMPOSE_XOR:
1494                             tmp = tmp1 ^ tmp2;
1495                             break;
1496                         case JBIG2_COMPOSE_XNOR:
1497                             tmp = ~(tmp1 ^ tmp2);
1498                             break;
1499                         case JBIG2_COMPOSE_REPLACE:
1500                             tmp = tmp1;
1501                             break;
1502                     }
1503                     dp[0] = (uint8_t)(tmp >> 24);
1504                     dp[1] = (uint8_t)(tmp >> 16);
1505                     dp[2] = (uint8_t)(tmp >> 8);
1506                     dp[3] = (uint8_t)tmp;
1507                     sp += 4;
1508                     dp += 4;
1509                 }
1510                 if(d2 != 0) {
1511                     tmp1 = JBIG2_GETDWORD(sp);
1512                     tmp2 = JBIG2_GETDWORD(dp);
1513                     switch(op) {
1514                         case JBIG2_COMPOSE_OR:
1515                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1516                             break;
1517                         case JBIG2_COMPOSE_AND:
1518                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1519                             break;
1520                         case JBIG2_COMPOSE_XOR:
1521                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1522                             break;
1523                         case JBIG2_COMPOSE_XNOR:
1524                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1525                             break;
1526                         case JBIG2_COMPOSE_REPLACE:
1527                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1528                             break;
1529                     }
1530                     dp[0] = (uint8_t)(tmp >> 24);
1531                     dp[1] = (uint8_t)(tmp >> 16);
1532                     dp[2] = (uint8_t)(tmp >> 8);
1533                     dp[3] = (uint8_t)tmp;
1534                 }
1535                 lineSrc += m_nStride;
1536                 lineDst += pDst->m_nStride;
1537             }
1538         } else {
1539             shift1 = d1 - s1;
1540             shift2 = 32 - shift1;
1541             middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1542             for(yy = yd0; yy < yd1; yy++) {
1543                 sp = lineSrc;
1544                 dp = lineDst;
1545                 if(d1 != 0) {
1546                     tmp1 = JBIG2_GETDWORD(sp) >> shift1;
1547                     tmp2 = JBIG2_GETDWORD(dp);
1548                     switch(op) {
1549                         case JBIG2_COMPOSE_OR:
1550                             tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1551                             break;
1552                         case JBIG2_COMPOSE_AND:
1553                             tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1554                             break;
1555                         case JBIG2_COMPOSE_XOR:
1556                             tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1557                             break;
1558                         case JBIG2_COMPOSE_XNOR:
1559                             tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1560                             break;
1561                         case JBIG2_COMPOSE_REPLACE:
1562                             tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1563                             break;
1564                     }
1565                     dp[0] = (uint8_t)(tmp >> 24);
1566                     dp[1] = (uint8_t)(tmp >> 16);
1567                     dp[2] = (uint8_t)(tmp >> 8);
1568                     dp[3] = (uint8_t)tmp;
1569                     dp += 4;
1570                 }
1571                 for(xx = 0; xx < middleDwords; xx++) {
1572                     tmp1 = (JBIG2_GETDWORD(sp) << shift2) | ((JBIG2_GETDWORD(sp + 4)) >> shift1);
1573                     tmp2 = JBIG2_GETDWORD(dp);
1574                     switch(op) {
1575                         case JBIG2_COMPOSE_OR:
1576                             tmp = tmp1 | tmp2;
1577                             break;
1578                         case JBIG2_COMPOSE_AND:
1579                             tmp = tmp1 & tmp2;
1580                             break;
1581                         case JBIG2_COMPOSE_XOR:
1582                             tmp = tmp1 ^ tmp2;
1583                             break;
1584                         case JBIG2_COMPOSE_XNOR:
1585                             tmp = ~(tmp1 ^ tmp2);
1586                             break;
1587                         case JBIG2_COMPOSE_REPLACE:
1588                             tmp = tmp1;
1589                             break;
1590                     }
1591                     dp[0] = (uint8_t)(tmp >> 24);
1592                     dp[1] = (uint8_t)(tmp >> 16);
1593                     dp[2] = (uint8_t)(tmp >> 8);
1594                     dp[3] = (uint8_t)tmp;
1595                     sp += 4;
1596                     dp += 4;
1597                 }
1598                 if(d2 != 0) {
1599                     tmp1 = (JBIG2_GETDWORD(sp) << shift2) | (
1600                                ((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >> shift1);
1601                     tmp2 = JBIG2_GETDWORD(dp);
1602                     switch(op) {
1603                         case JBIG2_COMPOSE_OR:
1604                             tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1605                             break;
1606                         case JBIG2_COMPOSE_AND:
1607                             tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1608                             break;
1609                         case JBIG2_COMPOSE_XOR:
1610                             tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1611                             break;
1612                         case JBIG2_COMPOSE_XNOR:
1613                             tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1614                             break;
1615                         case JBIG2_COMPOSE_REPLACE:
1616                             tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1617                             break;
1618                     }
1619                     dp[0] = (uint8_t)(tmp >> 24);
1620                     dp[1] = (uint8_t)(tmp >> 16);
1621                     dp[2] = (uint8_t)(tmp >> 8);
1622                     dp[3] = (uint8_t)tmp;
1623                 }
1624                 lineSrc += m_nStride;
1625                 lineDst += pDst->m_nStride;
1626             }
1627         }
1628     }
1629     return 1;
1630 }