Make a bunch of JBig2 classes independent of CJBig2_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 <limits.h>
8
9 #include "../../../include/fxcrt/fx_coordinates.h"
10 #include "../../../include/fxcrt/fx_safe_types.h"
11 #include "JBig2_Image.h"
12
13 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h) {
14   m_nWidth = w;
15   m_nHeight = h;
16   if (m_nWidth <= 0 || m_nHeight <= 0 || m_nWidth > INT_MAX - 31) {
17     m_pData = NULL;
18     m_bNeedFree = FALSE;
19     return;
20   }
21   m_nStride = ((w + 31) >> 5) << 2;
22   if (m_nStride * m_nHeight > 0 && 104857600 / (int)m_nStride > m_nHeight) {
23     m_pData = (uint8_t*)m_pModule->JBig2_Malloc2(m_nStride, m_nHeight);
24   } else {
25     m_pData = NULL;
26   }
27   m_bNeedFree = TRUE;
28 }
29 CJBig2_Image::CJBig2_Image(int32_t w,
30                            int32_t h,
31                            int32_t stride,
32                            uint8_t* pBuf) {
33   m_nWidth = w;
34   m_nHeight = h;
35   m_nStride = stride;
36   m_pData = pBuf;
37   m_bNeedFree = FALSE;
38 }
39 CJBig2_Image::CJBig2_Image(CJBig2_Image& im) {
40   m_pModule = im.m_pModule;
41   m_nWidth = im.m_nWidth;
42   m_nHeight = im.m_nHeight;
43   m_nStride = im.m_nStride;
44   if (im.m_pData) {
45     m_pData = (uint8_t*)m_pModule->JBig2_Malloc2(m_nStride, m_nHeight);
46     JBIG2_memcpy(m_pData, im.m_pData, m_nStride * m_nHeight);
47   } else {
48     m_pData = NULL;
49   }
50   m_bNeedFree = TRUE;
51 }
52 CJBig2_Image::~CJBig2_Image() {
53   if (m_bNeedFree && m_pData) {
54     m_pModule->JBig2_Free(m_pData);
55   }
56 }
57 FX_BOOL CJBig2_Image::getPixel(int32_t x, int32_t y) {
58   if (!m_pData) {
59     return 0;
60   }
61   int32_t 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 int32_t CJBig2_Image::setPixel(int32_t x, int32_t y, FX_BOOL v) {
74   if (!m_pData) {
75     return 0;
76   }
77   int32_t m, n;
78   if (x < 0 || x >= m_nWidth) {
79     return 0;
80   }
81   if (y < 0 || y >= m_nHeight) {
82     return 0;
83   }
84   m = y * m_nStride + (x >> 3);
85   n = x & 7;
86   if (v) {
87     m_pData[m] |= 1 << (7 - n);
88   } else {
89     m_pData[m] &= ~(1 << (7 - n));
90   }
91   return 1;
92 }
93 void CJBig2_Image::copyLine(int32_t hTo, int32_t hFrom) {
94   if (!m_pData) {
95     return;
96   }
97   if (hFrom < 0 || hFrom >= m_nHeight) {
98     JBIG2_memset(m_pData + hTo * m_nStride, 0, m_nStride);
99   } else {
100     JBIG2_memcpy(m_pData + hTo * m_nStride, m_pData + hFrom * m_nStride,
101                  m_nStride);
102   }
103 }
104 void CJBig2_Image::fill(FX_BOOL v) {
105   if (!m_pData) {
106     return;
107   }
108   JBIG2_memset(m_pData, v ? 0xff : 0, m_nStride * m_nHeight);
109 }
110 FX_BOOL CJBig2_Image::composeTo(CJBig2_Image* pDst,
111                                 int32_t x,
112                                 int32_t y,
113                                 JBig2ComposeOp op) {
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,
120                                 int32_t x,
121                                 int32_t y,
122                                 JBig2ComposeOp op,
123                                 const FX_RECT* pSrcRect) {
124   if (!m_pData) {
125     return FALSE;
126   }
127   if (NULL == pSrcRect || *pSrcRect == FX_RECT(0, 0, m_nWidth, m_nHeight)) {
128     return composeTo_opt2(pDst, x, y, op);
129   }
130   return composeTo_opt2(pDst, x, y, op, pSrcRect);
131 }
132
133 FX_BOOL CJBig2_Image::composeFrom(int32_t x,
134                                   int32_t y,
135                                   CJBig2_Image* pSrc,
136                                   JBig2ComposeOp op) {
137   if (!m_pData) {
138     return FALSE;
139   }
140   return pSrc->composeTo(this, x, y, op);
141 }
142 FX_BOOL CJBig2_Image::composeFrom(int32_t x,
143                                   int32_t y,
144                                   CJBig2_Image* pSrc,
145                                   JBig2ComposeOp op,
146                                   const FX_RECT* pSrcRect) {
147   if (!m_pData) {
148     return FALSE;
149   }
150   return pSrc->composeTo(this, x, y, op, pSrcRect);
151 }
152 #define JBIG2_GETDWORD(buf) \
153   ((FX_DWORD)(((buf)[0] << 24) | ((buf)[1] << 16) | ((buf)[2] << 8) | (buf)[3]))
154 CJBig2_Image* CJBig2_Image::subImage(int32_t x,
155                                      int32_t y,
156                                      int32_t w,
157                                      int32_t h) {
158   CJBig2_Image* pImage;
159   int32_t m, n, j;
160   uint8_t *pLineSrc, *pLineDst;
161   FX_DWORD wTmp;
162   uint8_t *pSrc, *pSrcEnd, *pDst, *pDstEnd;
163   if (w == 0 || h == 0) {
164     return NULL;
165   }
166   JBIG2_ALLOC(pImage, CJBig2_Image(w, h));
167   if (!m_pData) {
168     pImage->fill(0);
169     return pImage;
170   }
171   if (!pImage->m_pData) {
172     return pImage;
173   }
174   pLineSrc = m_pData + m_nStride * y;
175   pLineDst = pImage->m_pData;
176   m = (x >> 5) << 2;
177   n = x & 31;
178   if (n == 0) {
179     for (j = 0; j < h; j++) {
180       pSrc = pLineSrc + m;
181       pSrcEnd = pLineSrc + m_nStride;
182       pDst = pLineDst;
183       pDstEnd = pLineDst + pImage->m_nStride;
184       for (; pDst < pDstEnd; pSrc += 4, pDst += 4) {
185         *((FX_DWORD*)pDst) = *((FX_DWORD*)pSrc);
186       }
187       pLineSrc += m_nStride;
188       pLineDst += pImage->m_nStride;
189     }
190   } else {
191     for (j = 0; j < h; j++) {
192       pSrc = pLineSrc + m;
193       pSrcEnd = pLineSrc + m_nStride;
194       pDst = pLineDst;
195       pDstEnd = pLineDst + pImage->m_nStride;
196       for (; pDst < pDstEnd; pSrc += 4, pDst += 4) {
197         if (pSrc + 4 < pSrcEnd) {
198           wTmp = (JBIG2_GETDWORD(pSrc) << n) |
199                  (JBIG2_GETDWORD(pSrc + 4) >> (32 - n));
200         } else {
201           wTmp = JBIG2_GETDWORD(pSrc) << n;
202         }
203         pDst[0] = (uint8_t)(wTmp >> 24);
204         pDst[1] = (uint8_t)(wTmp >> 16);
205         pDst[2] = (uint8_t)(wTmp >> 8);
206         pDst[3] = (uint8_t)wTmp;
207       }
208       pLineSrc += m_nStride;
209       pLineDst += pImage->m_nStride;
210     }
211   }
212   return pImage;
213 }
214 void CJBig2_Image::expand(int32_t h, FX_BOOL v) {
215   if (!m_pData || h <= m_nHeight) {
216     return;
217   }
218   FX_DWORD dwH = pdfium::base::checked_cast<FX_DWORD>(h);
219   FX_DWORD dwStride = pdfium::base::checked_cast<FX_DWORD>(m_nStride);
220   FX_DWORD dwHeight = pdfium::base::checked_cast<FX_DWORD>(m_nHeight);
221   FX_SAFE_DWORD safeMemSize = dwH;
222   safeMemSize *= dwStride;
223   if (!safeMemSize.IsValid()) {
224     return;
225   }
226   // The guaranteed reallocated memory is to be < 4GB (unsigned int).
227   m_pData =
228       (uint8_t*)m_pModule->JBig2_Realloc(m_pData, safeMemSize.ValueOrDie());
229   // The result of dwHeight * dwStride doesn't overflow after the
230   // checking of safeMemSize.
231   // The same as the result of (dwH - dwHeight) * dwStride) because
232   // dwH - dwHeight is always less than dwH(h) which is checked in
233   // the calculation of dwH * dwStride.
234   JBIG2_memset(m_pData + dwHeight * dwStride, v ? 0xff : 0,
235                (dwH - dwHeight) * dwStride);
236   m_nHeight = h;
237 }
238 FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst,
239                                      int32_t x,
240                                      int32_t y,
241                                      JBig2ComposeOp op) {
242   int32_t xs0 = 0, ys0 = 0, xs1 = 0, ys1 = 0, xd0 = 0, yd0 = 0, xd1 = 0,
243           yd1 = 0, xx = 0, yy = 0, w = 0, h = 0, middleDwords = 0, lineLeft = 0;
244
245   FX_DWORD s1 = 0, d1 = 0, d2 = 0, shift = 0, shift1 = 0, shift2 = 0, tmp = 0,
246            tmp1 = 0, tmp2 = 0, maskL = 0, maskR = 0, maskM = 0;
247
248   uint8_t *lineSrc = NULL, *lineDst = NULL, *sp = NULL, *dp = NULL;
249
250   if (!m_pData) {
251     return FALSE;
252   }
253   if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
254     return FALSE;
255   }
256   if (y < 0) {
257     ys0 = -y;
258   }
259   if (y + m_nHeight > pDst->m_nHeight) {
260     ys1 = pDst->m_nHeight - y;
261   } else {
262     ys1 = m_nHeight;
263   }
264   if (x < 0) {
265     xs0 = -x;
266   }
267   if (x + m_nWidth > pDst->m_nWidth) {
268     xs1 = pDst->m_nWidth - x;
269   } else {
270     xs1 = m_nWidth;
271   }
272   if ((ys0 >= ys1) || (xs0 >= xs1)) {
273     return 0;
274   }
275   w = xs1 - xs0;
276   h = ys1 - ys0;
277   if (y >= 0) {
278     yd0 = y;
279   }
280   if (x >= 0) {
281     xd0 = x;
282   }
283   xd1 = xd0 + w;
284   yd1 = yd0 + h;
285   d1 = xd0 & 31;
286   d2 = xd1 & 31;
287   s1 = xs0 & 31;
288   maskL = 0xffffffff >> d1;
289   maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
290   maskM = maskL & maskR;
291   lineSrc = m_pData + ys0 * m_nStride + ((xs0 >> 5) << 2);
292   lineLeft = m_nStride - ((xs0 >> 5) << 2);
293   lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
294   if ((xd0 & ~31) == ((xd1 - 1) & ~31)) {
295     if ((xs0 & ~31) == ((xs1 - 1) & ~31)) {
296       if (s1 > d1) {
297         shift = s1 - d1;
298         for (yy = yd0; yy < yd1; yy++) {
299           tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
300           tmp2 = JBIG2_GETDWORD(lineDst);
301           switch (op) {
302             case JBIG2_COMPOSE_OR:
303               tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
304               break;
305             case JBIG2_COMPOSE_AND:
306               tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
307               break;
308             case JBIG2_COMPOSE_XOR:
309               tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
310               break;
311             case JBIG2_COMPOSE_XNOR:
312               tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
313               break;
314             case JBIG2_COMPOSE_REPLACE:
315               tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
316               break;
317           }
318           lineDst[0] = (uint8_t)(tmp >> 24);
319           lineDst[1] = (uint8_t)(tmp >> 16);
320           lineDst[2] = (uint8_t)(tmp >> 8);
321           lineDst[3] = (uint8_t)tmp;
322           lineSrc += m_nStride;
323           lineDst += pDst->m_nStride;
324         }
325       } else {
326         shift = d1 - s1;
327         for (yy = yd0; yy < yd1; yy++) {
328           tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
329           tmp2 = JBIG2_GETDWORD(lineDst);
330           switch (op) {
331             case JBIG2_COMPOSE_OR:
332               tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
333               break;
334             case JBIG2_COMPOSE_AND:
335               tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
336               break;
337             case JBIG2_COMPOSE_XOR:
338               tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
339               break;
340             case JBIG2_COMPOSE_XNOR:
341               tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
342               break;
343             case JBIG2_COMPOSE_REPLACE:
344               tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
345               break;
346           }
347           lineDst[0] = (uint8_t)(tmp >> 24);
348           lineDst[1] = (uint8_t)(tmp >> 16);
349           lineDst[2] = (uint8_t)(tmp >> 8);
350           lineDst[3] = (uint8_t)tmp;
351           lineSrc += m_nStride;
352           lineDst += pDst->m_nStride;
353         }
354       }
355     } else {
356       shift1 = s1 - d1;
357       shift2 = 32 - shift1;
358       for (yy = yd0; yy < yd1; yy++) {
359         tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) |
360                (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
361         tmp2 = JBIG2_GETDWORD(lineDst);
362         switch (op) {
363           case JBIG2_COMPOSE_OR:
364             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
365             break;
366           case JBIG2_COMPOSE_AND:
367             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
368             break;
369           case JBIG2_COMPOSE_XOR:
370             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
371             break;
372           case JBIG2_COMPOSE_XNOR:
373             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
374             break;
375           case JBIG2_COMPOSE_REPLACE:
376             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
377             break;
378         }
379         lineDst[0] = (uint8_t)(tmp >> 24);
380         lineDst[1] = (uint8_t)(tmp >> 16);
381         lineDst[2] = (uint8_t)(tmp >> 8);
382         lineDst[3] = (uint8_t)tmp;
383         lineSrc += m_nStride;
384         lineDst += pDst->m_nStride;
385       }
386     }
387   } else {
388     if (s1 > d1) {
389       shift1 = s1 - d1;
390       shift2 = 32 - shift1;
391       middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
392       for (yy = yd0; yy < yd1; yy++) {
393         sp = lineSrc;
394         dp = lineDst;
395         if (d1 != 0) {
396           tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
397                  (JBIG2_GETDWORD(sp + 4) >> shift2);
398           tmp2 = JBIG2_GETDWORD(dp);
399           switch (op) {
400             case JBIG2_COMPOSE_OR:
401               tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
402               break;
403             case JBIG2_COMPOSE_AND:
404               tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
405               break;
406             case JBIG2_COMPOSE_XOR:
407               tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
408               break;
409             case JBIG2_COMPOSE_XNOR:
410               tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
411               break;
412             case JBIG2_COMPOSE_REPLACE:
413               tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
414               break;
415           }
416           dp[0] = (uint8_t)(tmp >> 24);
417           dp[1] = (uint8_t)(tmp >> 16);
418           dp[2] = (uint8_t)(tmp >> 8);
419           dp[3] = (uint8_t)tmp;
420           sp += 4;
421           dp += 4;
422         }
423         for (xx = 0; xx < middleDwords; xx++) {
424           tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
425                  (JBIG2_GETDWORD(sp + 4) >> shift2);
426           tmp2 = JBIG2_GETDWORD(dp);
427           switch (op) {
428             case JBIG2_COMPOSE_OR:
429               tmp = tmp1 | tmp2;
430               break;
431             case JBIG2_COMPOSE_AND:
432               tmp = tmp1 & tmp2;
433               break;
434             case JBIG2_COMPOSE_XOR:
435               tmp = tmp1 ^ tmp2;
436               break;
437             case JBIG2_COMPOSE_XNOR:
438               tmp = ~(tmp1 ^ tmp2);
439               break;
440             case JBIG2_COMPOSE_REPLACE:
441               tmp = tmp1;
442               break;
443           }
444           dp[0] = (uint8_t)(tmp >> 24);
445           dp[1] = (uint8_t)(tmp >> 16);
446           dp[2] = (uint8_t)(tmp >> 8);
447           dp[3] = (uint8_t)tmp;
448           sp += 4;
449           dp += 4;
450         }
451         if (d2 != 0) {
452           tmp1 =
453               (JBIG2_GETDWORD(sp) << shift1) |
454               (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
455                shift2);
456           tmp2 = JBIG2_GETDWORD(dp);
457           switch (op) {
458             case JBIG2_COMPOSE_OR:
459               tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
460               break;
461             case JBIG2_COMPOSE_AND:
462               tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
463               break;
464             case JBIG2_COMPOSE_XOR:
465               tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
466               break;
467             case JBIG2_COMPOSE_XNOR:
468               tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
469               break;
470             case JBIG2_COMPOSE_REPLACE:
471               tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
472               break;
473           }
474           dp[0] = (uint8_t)(tmp >> 24);
475           dp[1] = (uint8_t)(tmp >> 16);
476           dp[2] = (uint8_t)(tmp >> 8);
477           dp[3] = (uint8_t)tmp;
478         }
479         lineSrc += m_nStride;
480         lineDst += pDst->m_nStride;
481       }
482     } else if (s1 == d1) {
483       middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
484       for (yy = yd0; yy < yd1; yy++) {
485         sp = lineSrc;
486         dp = lineDst;
487         if (d1 != 0) {
488           tmp1 = JBIG2_GETDWORD(sp);
489           tmp2 = JBIG2_GETDWORD(dp);
490           switch (op) {
491             case JBIG2_COMPOSE_OR:
492               tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
493               break;
494             case JBIG2_COMPOSE_AND:
495               tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
496               break;
497             case JBIG2_COMPOSE_XOR:
498               tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
499               break;
500             case JBIG2_COMPOSE_XNOR:
501               tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
502               break;
503             case JBIG2_COMPOSE_REPLACE:
504               tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
505               break;
506           }
507           dp[0] = (uint8_t)(tmp >> 24);
508           dp[1] = (uint8_t)(tmp >> 16);
509           dp[2] = (uint8_t)(tmp >> 8);
510           dp[3] = (uint8_t)tmp;
511           sp += 4;
512           dp += 4;
513         }
514         for (xx = 0; xx < middleDwords; xx++) {
515           tmp1 = JBIG2_GETDWORD(sp);
516           tmp2 = JBIG2_GETDWORD(dp);
517           switch (op) {
518             case JBIG2_COMPOSE_OR:
519               tmp = tmp1 | tmp2;
520               break;
521             case JBIG2_COMPOSE_AND:
522               tmp = tmp1 & tmp2;
523               break;
524             case JBIG2_COMPOSE_XOR:
525               tmp = tmp1 ^ tmp2;
526               break;
527             case JBIG2_COMPOSE_XNOR:
528               tmp = ~(tmp1 ^ tmp2);
529               break;
530             case JBIG2_COMPOSE_REPLACE:
531               tmp = tmp1;
532               break;
533           }
534           dp[0] = (uint8_t)(tmp >> 24);
535           dp[1] = (uint8_t)(tmp >> 16);
536           dp[2] = (uint8_t)(tmp >> 8);
537           dp[3] = (uint8_t)tmp;
538           sp += 4;
539           dp += 4;
540         }
541         if (d2 != 0) {
542           tmp1 = JBIG2_GETDWORD(sp);
543           tmp2 = JBIG2_GETDWORD(dp);
544           switch (op) {
545             case JBIG2_COMPOSE_OR:
546               tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
547               break;
548             case JBIG2_COMPOSE_AND:
549               tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
550               break;
551             case JBIG2_COMPOSE_XOR:
552               tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
553               break;
554             case JBIG2_COMPOSE_XNOR:
555               tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
556               break;
557             case JBIG2_COMPOSE_REPLACE:
558               tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
559               break;
560           }
561           dp[0] = (uint8_t)(tmp >> 24);
562           dp[1] = (uint8_t)(tmp >> 16);
563           dp[2] = (uint8_t)(tmp >> 8);
564           dp[3] = (uint8_t)tmp;
565         }
566         lineSrc += m_nStride;
567         lineDst += pDst->m_nStride;
568       }
569     } else {
570       shift1 = d1 - s1;
571       shift2 = 32 - shift1;
572       middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
573       for (yy = yd0; yy < yd1; yy++) {
574         sp = lineSrc;
575         dp = lineDst;
576         if (d1 != 0) {
577           tmp1 = JBIG2_GETDWORD(sp) >> shift1;
578           tmp2 = JBIG2_GETDWORD(dp);
579           switch (op) {
580             case JBIG2_COMPOSE_OR:
581               tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
582               break;
583             case JBIG2_COMPOSE_AND:
584               tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
585               break;
586             case JBIG2_COMPOSE_XOR:
587               tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
588               break;
589             case JBIG2_COMPOSE_XNOR:
590               tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
591               break;
592             case JBIG2_COMPOSE_REPLACE:
593               tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
594               break;
595           }
596           dp[0] = (uint8_t)(tmp >> 24);
597           dp[1] = (uint8_t)(tmp >> 16);
598           dp[2] = (uint8_t)(tmp >> 8);
599           dp[3] = (uint8_t)tmp;
600           dp += 4;
601         }
602         for (xx = 0; xx < middleDwords; xx++) {
603           tmp1 = (JBIG2_GETDWORD(sp) << shift2) |
604                  ((JBIG2_GETDWORD(sp + 4)) >> shift1);
605           tmp2 = JBIG2_GETDWORD(dp);
606           switch (op) {
607             case JBIG2_COMPOSE_OR:
608               tmp = tmp1 | tmp2;
609               break;
610             case JBIG2_COMPOSE_AND:
611               tmp = tmp1 & tmp2;
612               break;
613             case JBIG2_COMPOSE_XOR:
614               tmp = tmp1 ^ tmp2;
615               break;
616             case JBIG2_COMPOSE_XNOR:
617               tmp = ~(tmp1 ^ tmp2);
618               break;
619             case JBIG2_COMPOSE_REPLACE:
620               tmp = tmp1;
621               break;
622           }
623           dp[0] = (uint8_t)(tmp >> 24);
624           dp[1] = (uint8_t)(tmp >> 16);
625           dp[2] = (uint8_t)(tmp >> 8);
626           dp[3] = (uint8_t)tmp;
627           sp += 4;
628           dp += 4;
629         }
630         if (d2 != 0) {
631           tmp1 =
632               (JBIG2_GETDWORD(sp) << shift2) |
633               (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
634                shift1);
635           tmp2 = JBIG2_GETDWORD(dp);
636           switch (op) {
637             case JBIG2_COMPOSE_OR:
638               tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
639               break;
640             case JBIG2_COMPOSE_AND:
641               tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
642               break;
643             case JBIG2_COMPOSE_XOR:
644               tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
645               break;
646             case JBIG2_COMPOSE_XNOR:
647               tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
648               break;
649             case JBIG2_COMPOSE_REPLACE:
650               tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
651               break;
652           }
653           dp[0] = (uint8_t)(tmp >> 24);
654           dp[1] = (uint8_t)(tmp >> 16);
655           dp[2] = (uint8_t)(tmp >> 8);
656           dp[3] = (uint8_t)tmp;
657         }
658         lineSrc += m_nStride;
659         lineDst += pDst->m_nStride;
660       }
661     }
662   }
663   return 1;
664 }
665 FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst,
666                                      int32_t x,
667                                      int32_t y,
668                                      JBig2ComposeOp op,
669                                      const FX_RECT* pSrcRect) {
670   int32_t xs0, ys0, xs1, ys1, xd0, yd0, xd1, yd1, xx, yy, w, h, middleDwords,
671       lineLeft;
672   FX_DWORD s1, d1, d2, shift, shift1, shift2, tmp, tmp1, tmp2, maskL, maskR,
673       maskM;
674   uint8_t *lineSrc, *lineDst, *sp, *dp;
675   int32_t sw, sh;
676   if (!m_pData) {
677     return FALSE;
678   }
679   if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
680     return FALSE;
681   }
682   sw = pSrcRect->Width();
683   sh = pSrcRect->Height();
684   if (y < 0) {
685     ys0 = -y;
686   } else {
687     ys0 = 0;
688   }
689   if (y + sh > pDst->m_nHeight) {
690     ys1 = pDst->m_nHeight - y;
691   } else {
692     ys1 = sh;
693   }
694   if (x < 0) {
695     xs0 = -x;
696   } else {
697     xs0 = 0;
698   }
699   if (x + sw > pDst->m_nWidth) {
700     xs1 = pDst->m_nWidth - x;
701   } else {
702     xs1 = sw;
703   }
704   if ((ys0 >= ys1) || (xs0 >= xs1)) {
705     return 0;
706   }
707   w = xs1 - xs0;
708   h = ys1 - ys0;
709   if (y < 0) {
710     yd0 = 0;
711   } else {
712     yd0 = y;
713   }
714   if (x < 0) {
715     xd0 = 0;
716   } else {
717     xd0 = x;
718   }
719   xd1 = xd0 + w;
720   yd1 = yd0 + h;
721   d1 = xd0 & 31;
722   d2 = xd1 & 31;
723   s1 = xs0 & 31;
724   maskL = 0xffffffff >> d1;
725   maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
726   maskM = maskL & maskR;
727   lineSrc = m_pData + (pSrcRect->top + ys0) * m_nStride +
728             (((xs0 + pSrcRect->left) >> 5) << 2);
729   lineLeft = m_nStride - ((xs0 >> 5) << 2);
730   lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
731   if ((xd0 & ~31) == ((xd1 - 1) & ~31)) {
732     if ((xs0 & ~31) == ((xs1 - 1) & ~31)) {
733       if (s1 > d1) {
734         shift = s1 - d1;
735         for (yy = yd0; yy < yd1; yy++) {
736           tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
737           tmp2 = JBIG2_GETDWORD(lineDst);
738           switch (op) {
739             case JBIG2_COMPOSE_OR:
740               tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
741               break;
742             case JBIG2_COMPOSE_AND:
743               tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
744               break;
745             case JBIG2_COMPOSE_XOR:
746               tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
747               break;
748             case JBIG2_COMPOSE_XNOR:
749               tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
750               break;
751             case JBIG2_COMPOSE_REPLACE:
752               tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
753               break;
754           }
755           lineDst[0] = (uint8_t)(tmp >> 24);
756           lineDst[1] = (uint8_t)(tmp >> 16);
757           lineDst[2] = (uint8_t)(tmp >> 8);
758           lineDst[3] = (uint8_t)tmp;
759           lineSrc += m_nStride;
760           lineDst += pDst->m_nStride;
761         }
762       } else {
763         shift = d1 - s1;
764         for (yy = yd0; yy < yd1; yy++) {
765           tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
766           tmp2 = JBIG2_GETDWORD(lineDst);
767           switch (op) {
768             case JBIG2_COMPOSE_OR:
769               tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
770               break;
771             case JBIG2_COMPOSE_AND:
772               tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
773               break;
774             case JBIG2_COMPOSE_XOR:
775               tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
776               break;
777             case JBIG2_COMPOSE_XNOR:
778               tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
779               break;
780             case JBIG2_COMPOSE_REPLACE:
781               tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
782               break;
783           }
784           lineDst[0] = (uint8_t)(tmp >> 24);
785           lineDst[1] = (uint8_t)(tmp >> 16);
786           lineDst[2] = (uint8_t)(tmp >> 8);
787           lineDst[3] = (uint8_t)tmp;
788           lineSrc += m_nStride;
789           lineDst += pDst->m_nStride;
790         }
791       }
792     } else {
793       shift1 = s1 - d1;
794       shift2 = 32 - shift1;
795       for (yy = yd0; yy < yd1; yy++) {
796         tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) |
797                (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
798         tmp2 = JBIG2_GETDWORD(lineDst);
799         switch (op) {
800           case JBIG2_COMPOSE_OR:
801             tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
802             break;
803           case JBIG2_COMPOSE_AND:
804             tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
805             break;
806           case JBIG2_COMPOSE_XOR:
807             tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
808             break;
809           case JBIG2_COMPOSE_XNOR:
810             tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
811             break;
812           case JBIG2_COMPOSE_REPLACE:
813             tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
814             break;
815         }
816         lineDst[0] = (uint8_t)(tmp >> 24);
817         lineDst[1] = (uint8_t)(tmp >> 16);
818         lineDst[2] = (uint8_t)(tmp >> 8);
819         lineDst[3] = (uint8_t)tmp;
820         lineSrc += m_nStride;
821         lineDst += pDst->m_nStride;
822       }
823     }
824   } else {
825     if (s1 > d1) {
826       shift1 = s1 - d1;
827       shift2 = 32 - shift1;
828       middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
829       for (yy = yd0; yy < yd1; yy++) {
830         sp = lineSrc;
831         dp = lineDst;
832         if (d1 != 0) {
833           tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
834                  (JBIG2_GETDWORD(sp + 4) >> shift2);
835           tmp2 = JBIG2_GETDWORD(dp);
836           switch (op) {
837             case JBIG2_COMPOSE_OR:
838               tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
839               break;
840             case JBIG2_COMPOSE_AND:
841               tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
842               break;
843             case JBIG2_COMPOSE_XOR:
844               tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
845               break;
846             case JBIG2_COMPOSE_XNOR:
847               tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
848               break;
849             case JBIG2_COMPOSE_REPLACE:
850               tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
851               break;
852           }
853           dp[0] = (uint8_t)(tmp >> 24);
854           dp[1] = (uint8_t)(tmp >> 16);
855           dp[2] = (uint8_t)(tmp >> 8);
856           dp[3] = (uint8_t)tmp;
857           sp += 4;
858           dp += 4;
859         }
860         for (xx = 0; xx < middleDwords; xx++) {
861           tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
862                  (JBIG2_GETDWORD(sp + 4) >> shift2);
863           tmp2 = JBIG2_GETDWORD(dp);
864           switch (op) {
865             case JBIG2_COMPOSE_OR:
866               tmp = tmp1 | tmp2;
867               break;
868             case JBIG2_COMPOSE_AND:
869               tmp = tmp1 & tmp2;
870               break;
871             case JBIG2_COMPOSE_XOR:
872               tmp = tmp1 ^ tmp2;
873               break;
874             case JBIG2_COMPOSE_XNOR:
875               tmp = ~(tmp1 ^ tmp2);
876               break;
877             case JBIG2_COMPOSE_REPLACE:
878               tmp = tmp1;
879               break;
880           }
881           dp[0] = (uint8_t)(tmp >> 24);
882           dp[1] = (uint8_t)(tmp >> 16);
883           dp[2] = (uint8_t)(tmp >> 8);
884           dp[3] = (uint8_t)tmp;
885           sp += 4;
886           dp += 4;
887         }
888         if (d2 != 0) {
889           tmp1 =
890               (JBIG2_GETDWORD(sp) << shift1) |
891               (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
892                shift2);
893           tmp2 = JBIG2_GETDWORD(dp);
894           switch (op) {
895             case JBIG2_COMPOSE_OR:
896               tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
897               break;
898             case JBIG2_COMPOSE_AND:
899               tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
900               break;
901             case JBIG2_COMPOSE_XOR:
902               tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
903               break;
904             case JBIG2_COMPOSE_XNOR:
905               tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
906               break;
907             case JBIG2_COMPOSE_REPLACE:
908               tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
909               break;
910           }
911           dp[0] = (uint8_t)(tmp >> 24);
912           dp[1] = (uint8_t)(tmp >> 16);
913           dp[2] = (uint8_t)(tmp >> 8);
914           dp[3] = (uint8_t)tmp;
915         }
916         lineSrc += m_nStride;
917         lineDst += pDst->m_nStride;
918       }
919     } else if (s1 == d1) {
920       middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
921       for (yy = yd0; yy < yd1; yy++) {
922         sp = lineSrc;
923         dp = lineDst;
924         if (d1 != 0) {
925           tmp1 = JBIG2_GETDWORD(sp);
926           tmp2 = JBIG2_GETDWORD(dp);
927           switch (op) {
928             case JBIG2_COMPOSE_OR:
929               tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
930               break;
931             case JBIG2_COMPOSE_AND:
932               tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
933               break;
934             case JBIG2_COMPOSE_XOR:
935               tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
936               break;
937             case JBIG2_COMPOSE_XNOR:
938               tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
939               break;
940             case JBIG2_COMPOSE_REPLACE:
941               tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
942               break;
943           }
944           dp[0] = (uint8_t)(tmp >> 24);
945           dp[1] = (uint8_t)(tmp >> 16);
946           dp[2] = (uint8_t)(tmp >> 8);
947           dp[3] = (uint8_t)tmp;
948           sp += 4;
949           dp += 4;
950         }
951         for (xx = 0; xx < middleDwords; xx++) {
952           tmp1 = JBIG2_GETDWORD(sp);
953           tmp2 = JBIG2_GETDWORD(dp);
954           switch (op) {
955             case JBIG2_COMPOSE_OR:
956               tmp = tmp1 | tmp2;
957               break;
958             case JBIG2_COMPOSE_AND:
959               tmp = tmp1 & tmp2;
960               break;
961             case JBIG2_COMPOSE_XOR:
962               tmp = tmp1 ^ tmp2;
963               break;
964             case JBIG2_COMPOSE_XNOR:
965               tmp = ~(tmp1 ^ tmp2);
966               break;
967             case JBIG2_COMPOSE_REPLACE:
968               tmp = tmp1;
969               break;
970           }
971           dp[0] = (uint8_t)(tmp >> 24);
972           dp[1] = (uint8_t)(tmp >> 16);
973           dp[2] = (uint8_t)(tmp >> 8);
974           dp[3] = (uint8_t)tmp;
975           sp += 4;
976           dp += 4;
977         }
978         if (d2 != 0) {
979           tmp1 = JBIG2_GETDWORD(sp);
980           tmp2 = JBIG2_GETDWORD(dp);
981           switch (op) {
982             case JBIG2_COMPOSE_OR:
983               tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
984               break;
985             case JBIG2_COMPOSE_AND:
986               tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
987               break;
988             case JBIG2_COMPOSE_XOR:
989               tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
990               break;
991             case JBIG2_COMPOSE_XNOR:
992               tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
993               break;
994             case JBIG2_COMPOSE_REPLACE:
995               tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
996               break;
997           }
998           dp[0] = (uint8_t)(tmp >> 24);
999           dp[1] = (uint8_t)(tmp >> 16);
1000           dp[2] = (uint8_t)(tmp >> 8);
1001           dp[3] = (uint8_t)tmp;
1002         }
1003         lineSrc += m_nStride;
1004         lineDst += pDst->m_nStride;
1005       }
1006     } else {
1007       shift1 = d1 - s1;
1008       shift2 = 32 - shift1;
1009       middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1010       for (yy = yd0; yy < yd1; yy++) {
1011         sp = lineSrc;
1012         dp = lineDst;
1013         if (d1 != 0) {
1014           tmp1 = JBIG2_GETDWORD(sp) >> shift1;
1015           tmp2 = JBIG2_GETDWORD(dp);
1016           switch (op) {
1017             case JBIG2_COMPOSE_OR:
1018               tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1019               break;
1020             case JBIG2_COMPOSE_AND:
1021               tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1022               break;
1023             case JBIG2_COMPOSE_XOR:
1024               tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1025               break;
1026             case JBIG2_COMPOSE_XNOR:
1027               tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1028               break;
1029             case JBIG2_COMPOSE_REPLACE:
1030               tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1031               break;
1032           }
1033           dp[0] = (uint8_t)(tmp >> 24);
1034           dp[1] = (uint8_t)(tmp >> 16);
1035           dp[2] = (uint8_t)(tmp >> 8);
1036           dp[3] = (uint8_t)tmp;
1037           dp += 4;
1038         }
1039         for (xx = 0; xx < middleDwords; xx++) {
1040           tmp1 = (JBIG2_GETDWORD(sp) << shift2) |
1041                  ((JBIG2_GETDWORD(sp + 4)) >> shift1);
1042           tmp2 = JBIG2_GETDWORD(dp);
1043           switch (op) {
1044             case JBIG2_COMPOSE_OR:
1045               tmp = tmp1 | tmp2;
1046               break;
1047             case JBIG2_COMPOSE_AND:
1048               tmp = tmp1 & tmp2;
1049               break;
1050             case JBIG2_COMPOSE_XOR:
1051               tmp = tmp1 ^ tmp2;
1052               break;
1053             case JBIG2_COMPOSE_XNOR:
1054               tmp = ~(tmp1 ^ tmp2);
1055               break;
1056             case JBIG2_COMPOSE_REPLACE:
1057               tmp = tmp1;
1058               break;
1059           }
1060           dp[0] = (uint8_t)(tmp >> 24);
1061           dp[1] = (uint8_t)(tmp >> 16);
1062           dp[2] = (uint8_t)(tmp >> 8);
1063           dp[3] = (uint8_t)tmp;
1064           sp += 4;
1065           dp += 4;
1066         }
1067         if (d2 != 0) {
1068           tmp1 =
1069               (JBIG2_GETDWORD(sp) << shift2) |
1070               (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
1071                shift1);
1072           tmp2 = JBIG2_GETDWORD(dp);
1073           switch (op) {
1074             case JBIG2_COMPOSE_OR:
1075               tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1076               break;
1077             case JBIG2_COMPOSE_AND:
1078               tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1079               break;
1080             case JBIG2_COMPOSE_XOR:
1081               tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1082               break;
1083             case JBIG2_COMPOSE_XNOR:
1084               tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1085               break;
1086             case JBIG2_COMPOSE_REPLACE:
1087               tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1088               break;
1089           }
1090           dp[0] = (uint8_t)(tmp >> 24);
1091           dp[1] = (uint8_t)(tmp >> 16);
1092           dp[2] = (uint8_t)(tmp >> 8);
1093           dp[3] = (uint8_t)tmp;
1094         }
1095         lineSrc += m_nStride;
1096         lineDst += pDst->m_nStride;
1097       }
1098     }
1099   }
1100   return 1;
1101 }