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