free, rather than delete, malloc'd object.
[pdfium.git] / core / src / fxcodec / jbig2 / JBig2_Image.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4  
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "JBig2_Image.h"
8 #include "../../../include/fxcrt/fx_basic.h"
9 #include "../../../include/fxcrt/fx_coordinates.h"
10 #include <limits.h>
11 CJBig2_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 }
28 CJBig2_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 }
36 CJBig2_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 }
50 CJBig2_Image::~CJBig2_Image()
51 {
52     if(m_bNeedFree && m_pData) {
53         m_pModule->JBig2_Free(m_pData);
54     }
55 }
56 FX_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
73 FX_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 }
94 void 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 }
105 void 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 }
112 FX_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 }
119 FX_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 }
129 FX_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
196 FX_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 }
682 FX_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 }
689 FX_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 }
696 CJBig2_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]))
709 CJBig2_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 }
766 void 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 }
777 FX_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 }
1197 FX_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 }