Home | History | Annotate | Download | only in jbig2
      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 
     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 
     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 
     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 
     69 CJBig2_Image::~CJBig2_Image() {}
     70 
     71 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 
     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 
    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 }
    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 }
    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 }
    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 
    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 }
    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 
    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 
    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 
    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 
    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