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