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