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
13CJBig2_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}
30CJBig2_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}
38CJBig2_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}
52CJBig2_Image::~CJBig2_Image()
53{
54    if(m_bNeedFree && m_pData) {
55        m_pModule->JBig2_Free(m_pData);
56    }
57}
58FX_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
75FX_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}
96void 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}
107void 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}
114FX_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}
121FX_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}
131FX_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
198FX_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}
684FX_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}
691FX_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}
698CJBig2_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]))
711CJBig2_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}
768void CJBig2_Image::expand(FX_INT32 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 = (FX_BYTE*)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}
791FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image *pDst, FX_INT32 x, FX_INT32 y, JBig2ComposeOp op)
792{
793    FX_INT32 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    FX_BYTE *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] = (FX_BYTE)(tmp >> 24);
870                    lineDst[1] = (FX_BYTE)(tmp >> 16);
871                    lineDst[2] = (FX_BYTE)(tmp >> 8);
872                    lineDst[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
899                    lineDst[1] = (FX_BYTE)(tmp >> 16);
900                    lineDst[2] = (FX_BYTE)(tmp >> 8);
901                    lineDst[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
930                lineDst[1] = (FX_BYTE)(tmp >> 16);
931                lineDst[2] = (FX_BYTE)(tmp >> 8);
932                lineDst[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
966                    dp[1] = (FX_BYTE)(tmp >> 16);
967                    dp[2] = (FX_BYTE)(tmp >> 8);
968                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
993                    dp[1] = (FX_BYTE)(tmp >> 16);
994                    dp[2] = (FX_BYTE)(tmp >> 8);
995                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1021                    dp[1] = (FX_BYTE)(tmp >> 16);
1022                    dp[2] = (FX_BYTE)(tmp >> 8);
1023                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1054                    dp[1] = (FX_BYTE)(tmp >> 16);
1055                    dp[2] = (FX_BYTE)(tmp >> 8);
1056                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1081                    dp[1] = (FX_BYTE)(tmp >> 16);
1082                    dp[2] = (FX_BYTE)(tmp >> 8);
1083                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1108                    dp[1] = (FX_BYTE)(tmp >> 16);
1109                    dp[2] = (FX_BYTE)(tmp >> 8);
1110                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1143                    dp[1] = (FX_BYTE)(tmp >> 16);
1144                    dp[2] = (FX_BYTE)(tmp >> 8);
1145                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1169                    dp[1] = (FX_BYTE)(tmp >> 16);
1170                    dp[2] = (FX_BYTE)(tmp >> 8);
1171                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1197                    dp[1] = (FX_BYTE)(tmp >> 16);
1198                    dp[2] = (FX_BYTE)(tmp >> 8);
1199                    dp[3] = (FX_BYTE)tmp;
1200                }
1201                lineSrc += m_nStride;
1202                lineDst += pDst->m_nStride;
1203            }
1204        }
1205    }
1206    return 1;
1207}
1208FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image *pDst, FX_INT32 x, FX_INT32 y, JBig2ComposeOp op, const FX_RECT* pSrcRect)
1209{
1210    FX_INT32 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    FX_BYTE *lineSrc, *lineDst, *sp, *dp;
1213    FX_INT32 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] = (FX_BYTE)(tmp >> 24);
1293                    lineDst[1] = (FX_BYTE)(tmp >> 16);
1294                    lineDst[2] = (FX_BYTE)(tmp >> 8);
1295                    lineDst[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1322                    lineDst[1] = (FX_BYTE)(tmp >> 16);
1323                    lineDst[2] = (FX_BYTE)(tmp >> 8);
1324                    lineDst[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1353                lineDst[1] = (FX_BYTE)(tmp >> 16);
1354                lineDst[2] = (FX_BYTE)(tmp >> 8);
1355                lineDst[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1389                    dp[1] = (FX_BYTE)(tmp >> 16);
1390                    dp[2] = (FX_BYTE)(tmp >> 8);
1391                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1416                    dp[1] = (FX_BYTE)(tmp >> 16);
1417                    dp[2] = (FX_BYTE)(tmp >> 8);
1418                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1444                    dp[1] = (FX_BYTE)(tmp >> 16);
1445                    dp[2] = (FX_BYTE)(tmp >> 8);
1446                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1477                    dp[1] = (FX_BYTE)(tmp >> 16);
1478                    dp[2] = (FX_BYTE)(tmp >> 8);
1479                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1504                    dp[1] = (FX_BYTE)(tmp >> 16);
1505                    dp[2] = (FX_BYTE)(tmp >> 8);
1506                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1531                    dp[1] = (FX_BYTE)(tmp >> 16);
1532                    dp[2] = (FX_BYTE)(tmp >> 8);
1533                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1566                    dp[1] = (FX_BYTE)(tmp >> 16);
1567                    dp[2] = (FX_BYTE)(tmp >> 8);
1568                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1592                    dp[1] = (FX_BYTE)(tmp >> 16);
1593                    dp[2] = (FX_BYTE)(tmp >> 8);
1594                    dp[3] = (FX_BYTE)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] = (FX_BYTE)(tmp >> 24);
1620                    dp[1] = (FX_BYTE)(tmp >> 16);
1621                    dp[2] = (FX_BYTE)(tmp >> 8);
1622                    dp[3] = (FX_BYTE)tmp;
1623                }
1624                lineSrc += m_nStride;
1625                lineDst += pDst->m_nStride;
1626            }
1627        }
1628    }
1629    return 1;
1630}
1631