Home | History | Annotate | Download | only in dib
      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/fxge/fx_dib.h"
      8 
      9 #include <limits.h>
     10 
     11 #include <algorithm>
     12 #include <memory>
     13 #include <utility>
     14 
     15 #include "core/fxcodec/fx_codec.h"
     16 #include "core/fxcrt/cfx_maybe_owned.h"
     17 #include "core/fxge/cfx_gemodule.h"
     18 #include "core/fxge/dib/dib_int.h"
     19 #include "core/fxge/ge/cfx_cliprgn.h"
     20 #include "third_party/base/ptr_util.h"
     21 
     22 void CmykDecode(uint32_t cmyk, int& c, int& m, int& y, int& k) {
     23   c = FXSYS_GetCValue(cmyk);
     24   m = FXSYS_GetMValue(cmyk);
     25   y = FXSYS_GetYValue(cmyk);
     26   k = FXSYS_GetKValue(cmyk);
     27 }
     28 
     29 void ArgbDecode(uint32_t argb, int& a, int& r, int& g, int& b) {
     30   a = FXARGB_A(argb);
     31   r = FXARGB_R(argb);
     32   g = FXARGB_G(argb);
     33   b = FXARGB_B(argb);
     34 }
     35 
     36 void ArgbDecode(uint32_t argb, int& a, FX_COLORREF& rgb) {
     37   a = FXARGB_A(argb);
     38   rgb = FXSYS_RGB(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
     39 }
     40 
     41 uint32_t ArgbEncode(int a, FX_COLORREF rgb) {
     42   return FXARGB_MAKE(a, FXSYS_GetRValue(rgb), FXSYS_GetGValue(rgb),
     43                      FXSYS_GetBValue(rgb));
     44 }
     45 
     46 CFX_DIBSource::CFX_DIBSource()
     47     : m_pAlphaMask(nullptr),
     48       m_Width(0),
     49       m_Height(0),
     50       m_bpp(0),
     51       m_AlphaFlag(0),
     52       m_Pitch(0) {}
     53 
     54 CFX_DIBSource::~CFX_DIBSource() {
     55   delete m_pAlphaMask;
     56 }
     57 
     58 uint8_t* CFX_DIBSource::GetBuffer() const {
     59   return nullptr;
     60 }
     61 
     62 bool CFX_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const {
     63   return false;
     64 }
     65 
     66 CFX_DIBitmap::CFX_DIBitmap() {
     67   m_bExtBuf = false;
     68   m_pBuffer = nullptr;
     69   m_pPalette = nullptr;
     70 #ifdef _SKIA_SUPPORT_PATHS_
     71   m_nFormat = Format::kCleared;
     72 #endif
     73 }
     74 
     75 #define _MAX_OOM_LIMIT_ 12000000
     76 bool CFX_DIBitmap::Create(int width,
     77                           int height,
     78                           FXDIB_Format format,
     79                           uint8_t* pBuffer,
     80                           int pitch) {
     81   m_pBuffer = nullptr;
     82   m_bpp = (uint8_t)format;
     83   m_AlphaFlag = (uint8_t)(format >> 8);
     84   m_Width = m_Height = m_Pitch = 0;
     85   if (width <= 0 || height <= 0 || pitch < 0) {
     86     return false;
     87   }
     88   if ((INT_MAX - 31) / width < (format & 0xff)) {
     89     return false;
     90   }
     91   if (!pitch) {
     92     pitch = (width * (format & 0xff) + 31) / 32 * 4;
     93   }
     94   if ((1 << 30) / pitch < height) {
     95     return false;
     96   }
     97   if (pBuffer) {
     98     m_pBuffer = pBuffer;
     99     m_bExtBuf = true;
    100   } else {
    101     int size = pitch * height + 4;
    102     int oomlimit = _MAX_OOM_LIMIT_;
    103     if (oomlimit >= 0 && size >= oomlimit) {
    104       m_pBuffer = FX_TryAlloc(uint8_t, size);
    105       if (!m_pBuffer) {
    106         return false;
    107       }
    108     } else {
    109       m_pBuffer = FX_Alloc(uint8_t, size);
    110     }
    111   }
    112   m_Width = width;
    113   m_Height = height;
    114   m_Pitch = pitch;
    115   if (HasAlpha() && format != FXDIB_Argb) {
    116     bool ret = true;
    117     ret = BuildAlphaMask();
    118     if (!ret) {
    119       if (!m_bExtBuf) {
    120         FX_Free(m_pBuffer);
    121         m_pBuffer = nullptr;
    122         m_Width = m_Height = m_Pitch = 0;
    123         return false;
    124       }
    125     }
    126   }
    127   return true;
    128 }
    129 
    130 bool CFX_DIBitmap::Copy(const CFX_DIBSource* pSrc) {
    131   if (m_pBuffer)
    132     return false;
    133 
    134   if (!Create(pSrc->GetWidth(), pSrc->GetHeight(), pSrc->GetFormat()))
    135     return false;
    136 
    137   SetPalette(pSrc->GetPalette());
    138   SetAlphaMask(pSrc->m_pAlphaMask);
    139   for (int row = 0; row < pSrc->GetHeight(); row++)
    140     FXSYS_memcpy(m_pBuffer + row * m_Pitch, pSrc->GetScanline(row), m_Pitch);
    141 
    142   return true;
    143 }
    144 
    145 CFX_DIBitmap::~CFX_DIBitmap() {
    146   if (!m_bExtBuf)
    147     FX_Free(m_pBuffer);
    148 
    149   m_pBuffer = nullptr;
    150 }
    151 
    152 uint8_t* CFX_DIBitmap::GetBuffer() const {
    153   return m_pBuffer;
    154 }
    155 
    156 const uint8_t* CFX_DIBitmap::GetScanline(int line) const {
    157   return m_pBuffer ? m_pBuffer + line * m_Pitch : nullptr;
    158 }
    159 
    160 void CFX_DIBitmap::TakeOver(CFX_DIBitmap* pSrcBitmap) {
    161   if (!m_bExtBuf)
    162     FX_Free(m_pBuffer);
    163 
    164   delete m_pAlphaMask;
    165   m_pBuffer = pSrcBitmap->m_pBuffer;
    166   m_pPalette = std::move(pSrcBitmap->m_pPalette);
    167   m_pAlphaMask = pSrcBitmap->m_pAlphaMask;
    168   pSrcBitmap->m_pBuffer = nullptr;
    169   pSrcBitmap->m_pAlphaMask = nullptr;
    170   m_bpp = pSrcBitmap->m_bpp;
    171   m_bExtBuf = pSrcBitmap->m_bExtBuf;
    172   m_AlphaFlag = pSrcBitmap->m_AlphaFlag;
    173   m_Width = pSrcBitmap->m_Width;
    174   m_Height = pSrcBitmap->m_Height;
    175   m_Pitch = pSrcBitmap->m_Pitch;
    176 }
    177 
    178 std::unique_ptr<CFX_DIBitmap> CFX_DIBSource::Clone(const FX_RECT* pClip) const {
    179   FX_RECT rect(0, 0, m_Width, m_Height);
    180   if (pClip) {
    181     rect.Intersect(*pClip);
    182     if (rect.IsEmpty())
    183       return nullptr;
    184   }
    185   auto pNewBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
    186   if (!pNewBitmap->Create(rect.Width(), rect.Height(), GetFormat()))
    187     return nullptr;
    188 
    189   pNewBitmap->SetPalette(m_pPalette.get());
    190   pNewBitmap->SetAlphaMask(m_pAlphaMask, pClip);
    191   if (GetBPP() == 1 && rect.left % 8 != 0) {
    192     int left_shift = rect.left % 32;
    193     int right_shift = 32 - left_shift;
    194     int dword_count = pNewBitmap->m_Pitch / 4;
    195     for (int row = rect.top; row < rect.bottom; row++) {
    196       uint32_t* src_scan = (uint32_t*)GetScanline(row) + rect.left / 32;
    197       uint32_t* dest_scan = (uint32_t*)pNewBitmap->GetScanline(row - rect.top);
    198       for (int i = 0; i < dword_count; i++) {
    199         dest_scan[i] =
    200             (src_scan[i] << left_shift) | (src_scan[i + 1] >> right_shift);
    201       }
    202     }
    203   } else {
    204     int copy_len = (pNewBitmap->GetWidth() * pNewBitmap->GetBPP() + 7) / 8;
    205     if (m_Pitch < (uint32_t)copy_len)
    206       copy_len = m_Pitch;
    207 
    208     for (int row = rect.top; row < rect.bottom; row++) {
    209       const uint8_t* src_scan = GetScanline(row) + rect.left * m_bpp / 8;
    210       uint8_t* dest_scan = (uint8_t*)pNewBitmap->GetScanline(row - rect.top);
    211       FXSYS_memcpy(dest_scan, src_scan, copy_len);
    212     }
    213   }
    214   return pNewBitmap;
    215 }
    216 
    217 void CFX_DIBSource::BuildPalette() {
    218   if (m_pPalette)
    219     return;
    220 
    221   if (GetBPP() == 1) {
    222     m_pPalette.reset(FX_Alloc(uint32_t, 2));
    223     if (IsCmykImage()) {
    224       m_pPalette.get()[0] = 0xff;
    225       m_pPalette.get()[1] = 0;
    226     } else {
    227       m_pPalette.get()[0] = 0xff000000;
    228       m_pPalette.get()[1] = 0xffffffff;
    229     }
    230   } else if (GetBPP() == 8) {
    231     m_pPalette.reset(FX_Alloc(uint32_t, 256));
    232     if (IsCmykImage()) {
    233       for (int i = 0; i < 256; i++)
    234         m_pPalette.get()[i] = 0xff - i;
    235     } else {
    236       for (int i = 0; i < 256; i++)
    237         m_pPalette.get()[i] = 0xff000000 | (i * 0x10101);
    238     }
    239   }
    240 }
    241 
    242 bool CFX_DIBSource::BuildAlphaMask() {
    243   if (m_pAlphaMask) {
    244     return true;
    245   }
    246   m_pAlphaMask = new CFX_DIBitmap;
    247   if (!m_pAlphaMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
    248     delete m_pAlphaMask;
    249     m_pAlphaMask = nullptr;
    250     return false;
    251   }
    252   FXSYS_memset(m_pAlphaMask->GetBuffer(), 0xff,
    253                m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch());
    254   return true;
    255 }
    256 
    257 uint32_t CFX_DIBSource::GetPaletteEntry(int index) const {
    258   ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
    259   if (m_pPalette) {
    260     return m_pPalette.get()[index];
    261   }
    262   if (IsCmykImage()) {
    263     if (GetBPP() == 1) {
    264       return index ? 0 : 0xff;
    265     }
    266     return 0xff - index;
    267   }
    268   if (GetBPP() == 1) {
    269     return index ? 0xffffffff : 0xff000000;
    270   }
    271   return index * 0x10101 | 0xff000000;
    272 }
    273 
    274 void CFX_DIBSource::SetPaletteEntry(int index, uint32_t color) {
    275   ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
    276   if (!m_pPalette) {
    277     BuildPalette();
    278   }
    279   m_pPalette.get()[index] = color;
    280 }
    281 
    282 int CFX_DIBSource::FindPalette(uint32_t color) const {
    283   ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
    284   if (!m_pPalette) {
    285     if (IsCmykImage()) {
    286       if (GetBPP() == 1) {
    287         return ((uint8_t)color == 0xff) ? 0 : 1;
    288       }
    289       return 0xff - (uint8_t)color;
    290     }
    291     if (GetBPP() == 1) {
    292       return ((uint8_t)color == 0xff) ? 1 : 0;
    293     }
    294     return (uint8_t)color;
    295   }
    296   int palsize = (1 << GetBPP());
    297   for (int i = 0; i < palsize; i++)
    298     if (m_pPalette.get()[i] == color) {
    299       return i;
    300     }
    301   return -1;
    302 }
    303 
    304 void CFX_DIBitmap::Clear(uint32_t color) {
    305   if (!m_pBuffer) {
    306     return;
    307   }
    308   switch (GetFormat()) {
    309     case FXDIB_1bppMask:
    310       FXSYS_memset(m_pBuffer, (color & 0xff000000) ? 0xff : 0,
    311                    m_Pitch * m_Height);
    312       break;
    313     case FXDIB_1bppRgb: {
    314       int index = FindPalette(color);
    315       FXSYS_memset(m_pBuffer, index ? 0xff : 0, m_Pitch * m_Height);
    316       break;
    317     }
    318     case FXDIB_8bppMask:
    319       FXSYS_memset(m_pBuffer, color >> 24, m_Pitch * m_Height);
    320       break;
    321     case FXDIB_8bppRgb: {
    322       int index = FindPalette(color);
    323       FXSYS_memset(m_pBuffer, index, m_Pitch * m_Height);
    324       break;
    325     }
    326     case FXDIB_Rgb:
    327     case FXDIB_Rgba: {
    328       int a, r, g, b;
    329       ArgbDecode(color, a, r, g, b);
    330       if (r == g && g == b) {
    331         FXSYS_memset(m_pBuffer, r, m_Pitch * m_Height);
    332       } else {
    333         int byte_pos = 0;
    334         for (int col = 0; col < m_Width; col++) {
    335           m_pBuffer[byte_pos++] = b;
    336           m_pBuffer[byte_pos++] = g;
    337           m_pBuffer[byte_pos++] = r;
    338         }
    339         for (int row = 1; row < m_Height; row++) {
    340           FXSYS_memcpy(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch);
    341         }
    342       }
    343       break;
    344     }
    345     case FXDIB_Rgb32:
    346     case FXDIB_Argb: {
    347       color = IsCmykImage() ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
    348 #ifdef _SKIA_SUPPORT_
    349       if (FXDIB_Rgb32 == GetFormat() && !IsCmykImage()) {
    350         color |= 0xFF000000;
    351       }
    352 #endif
    353       for (int i = 0; i < m_Width; i++) {
    354         ((uint32_t*)m_pBuffer)[i] = color;
    355       }
    356       for (int row = 1; row < m_Height; row++) {
    357         FXSYS_memcpy(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch);
    358       }
    359       break;
    360     }
    361     default:
    362       break;
    363   }
    364 }
    365 
    366 void CFX_DIBSource::GetOverlapRect(int& dest_left,
    367                                    int& dest_top,
    368                                    int& width,
    369                                    int& height,
    370                                    int src_width,
    371                                    int src_height,
    372                                    int& src_left,
    373                                    int& src_top,
    374                                    const CFX_ClipRgn* pClipRgn) {
    375   if (width == 0 || height == 0) {
    376     return;
    377   }
    378   ASSERT(width > 0 && height > 0);
    379   if (dest_left > m_Width || dest_top > m_Height) {
    380     width = 0;
    381     height = 0;
    382     return;
    383   }
    384   int x_offset = dest_left - src_left;
    385   int y_offset = dest_top - src_top;
    386   FX_RECT src_rect(src_left, src_top, src_left + width, src_top + height);
    387   FX_RECT src_bound(0, 0, src_width, src_height);
    388   src_rect.Intersect(src_bound);
    389   FX_RECT dest_rect(src_rect.left + x_offset, src_rect.top + y_offset,
    390                     src_rect.right + x_offset, src_rect.bottom + y_offset);
    391   FX_RECT dest_bound(0, 0, m_Width, m_Height);
    392   dest_rect.Intersect(dest_bound);
    393   if (pClipRgn) {
    394     dest_rect.Intersect(pClipRgn->GetBox());
    395   }
    396   dest_left = dest_rect.left;
    397   dest_top = dest_rect.top;
    398   src_left = dest_left - x_offset;
    399   src_top = dest_top - y_offset;
    400   width = dest_rect.right - dest_rect.left;
    401   height = dest_rect.bottom - dest_rect.top;
    402 }
    403 
    404 bool CFX_DIBitmap::TransferBitmap(int dest_left,
    405                                   int dest_top,
    406                                   int width,
    407                                   int height,
    408                                   const CFX_DIBSource* pSrcBitmap,
    409                                   int src_left,
    410                                   int src_top) {
    411   if (!m_pBuffer)
    412     return false;
    413 
    414   GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(),
    415                  pSrcBitmap->GetHeight(), src_left, src_top, nullptr);
    416   if (width == 0 || height == 0)
    417     return true;
    418 
    419   FXDIB_Format dest_format = GetFormat();
    420   FXDIB_Format src_format = pSrcBitmap->GetFormat();
    421   if (dest_format == src_format) {
    422     if (GetBPP() == 1) {
    423       for (int row = 0; row < height; row++) {
    424         uint8_t* dest_scan = m_pBuffer + (dest_top + row) * m_Pitch;
    425         const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
    426         for (int col = 0; col < width; col++) {
    427           if (src_scan[(src_left + col) / 8] &
    428               (1 << (7 - (src_left + col) % 8))) {
    429             dest_scan[(dest_left + col) / 8] |= 1
    430                                                 << (7 - (dest_left + col) % 8);
    431           } else {
    432             dest_scan[(dest_left + col) / 8] &=
    433                 ~(1 << (7 - (dest_left + col) % 8));
    434           }
    435         }
    436       }
    437     } else {
    438       int Bpp = GetBPP() / 8;
    439       for (int row = 0; row < height; row++) {
    440         uint8_t* dest_scan =
    441             m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp;
    442         const uint8_t* src_scan =
    443             pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
    444         FXSYS_memcpy(dest_scan, src_scan, width * Bpp);
    445       }
    446     }
    447   } else {
    448     if (m_pPalette)
    449       return false;
    450 
    451     if (m_bpp == 8)
    452       dest_format = FXDIB_8bppMask;
    453 
    454     uint8_t* dest_buf =
    455         m_pBuffer + dest_top * m_Pitch + dest_left * GetBPP() / 8;
    456     std::unique_ptr<uint32_t, FxFreeDeleter> d_plt;
    457     if (!ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height,
    458                        pSrcBitmap, src_left, src_top, &d_plt)) {
    459       return false;
    460     }
    461   }
    462   return true;
    463 }
    464 
    465 bool CFX_DIBitmap::TransferMask(int dest_left,
    466                                 int dest_top,
    467                                 int width,
    468                                 int height,
    469                                 const CFX_DIBSource* pMask,
    470                                 uint32_t color,
    471                                 int src_left,
    472                                 int src_top,
    473                                 int alpha_flag,
    474                                 void* pIccTransform) {
    475   if (!m_pBuffer) {
    476     return false;
    477   }
    478   ASSERT(HasAlpha() && (m_bpp >= 24));
    479   ASSERT(pMask->IsAlphaMask());
    480   if (!HasAlpha() || !pMask->IsAlphaMask() || m_bpp < 24) {
    481     return false;
    482   }
    483   GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(),
    484                  pMask->GetHeight(), src_left, src_top, nullptr);
    485   if (width == 0 || height == 0) {
    486     return true;
    487   }
    488   int src_bpp = pMask->GetBPP();
    489   int alpha;
    490   uint32_t dst_color;
    491   if (alpha_flag >> 8) {
    492     alpha = alpha_flag & 0xff;
    493     dst_color = FXCMYK_TODIB(color);
    494   } else {
    495     alpha = FXARGB_A(color);
    496     dst_color = FXARGB_TODIB(color);
    497   }
    498   uint8_t* color_p = (uint8_t*)&dst_color;
    499   if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() &&
    500       CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
    501     CCodec_IccModule* pIccModule =
    502         CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
    503     pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1);
    504   } else {
    505     if (alpha_flag >> 8 && !IsCmykImage()) {
    506       AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
    507                          FXSYS_GetYValue(color), FXSYS_GetKValue(color),
    508                          color_p[2], color_p[1], color_p[0]);
    509     } else if (!(alpha_flag >> 8) && IsCmykImage()) {
    510       return false;
    511     }
    512   }
    513   if (!IsCmykImage()) {
    514     color_p[3] = (uint8_t)alpha;
    515   }
    516   if (GetFormat() == FXDIB_Argb) {
    517     for (int row = 0; row < height; row++) {
    518       uint32_t* dest_pos =
    519           (uint32_t*)(m_pBuffer + (dest_top + row) * m_Pitch + dest_left * 4);
    520       const uint8_t* src_scan = pMask->GetScanline(src_top + row);
    521       if (src_bpp == 1) {
    522         for (int col = 0; col < width; col++) {
    523           int src_bitpos = src_left + col;
    524           if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) {
    525             *dest_pos = dst_color;
    526           } else {
    527             *dest_pos = 0;
    528           }
    529           dest_pos++;
    530         }
    531       } else {
    532         src_scan += src_left;
    533         dst_color = FXARGB_TODIB(dst_color);
    534         dst_color &= 0xffffff;
    535         for (int col = 0; col < width; col++) {
    536           FXARGB_SETDIB(dest_pos++,
    537                         dst_color | ((alpha * (*src_scan++) / 255) << 24));
    538         }
    539       }
    540     }
    541   } else {
    542     int comps = m_bpp / 8;
    543     for (int row = 0; row < height; row++) {
    544       uint8_t* dest_color_pos =
    545           m_pBuffer + (dest_top + row) * m_Pitch + dest_left * comps;
    546       uint8_t* dest_alpha_pos =
    547           (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left;
    548       const uint8_t* src_scan = pMask->GetScanline(src_top + row);
    549       if (src_bpp == 1) {
    550         for (int col = 0; col < width; col++) {
    551           int src_bitpos = src_left + col;
    552           if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) {
    553             FXSYS_memcpy(dest_color_pos, color_p, comps);
    554             *dest_alpha_pos = 0xff;
    555           } else {
    556             FXSYS_memset(dest_color_pos, 0, comps);
    557             *dest_alpha_pos = 0;
    558           }
    559           dest_color_pos += comps;
    560           dest_alpha_pos++;
    561         }
    562       } else {
    563         src_scan += src_left;
    564         for (int col = 0; col < width; col++) {
    565           FXSYS_memcpy(dest_color_pos, color_p, comps);
    566           dest_color_pos += comps;
    567           *dest_alpha_pos++ = (alpha * (*src_scan++) / 255);
    568         }
    569       }
    570     }
    571   }
    572   return true;
    573 }
    574 
    575 void CFX_DIBSource::SetPalette(const uint32_t* pSrc) {
    576   static const uint32_t kPaletteSize = 256;
    577   if (!pSrc || GetBPP() > 8) {
    578     m_pPalette.reset();
    579     return;
    580   }
    581   uint32_t pal_size = 1 << GetBPP();
    582   if (!m_pPalette)
    583     m_pPalette.reset(FX_Alloc(uint32_t, pal_size));
    584   pal_size = std::min(pal_size, kPaletteSize);
    585   FXSYS_memcpy(m_pPalette.get(), pSrc, pal_size * sizeof(uint32_t));
    586 }
    587 
    588 void CFX_DIBSource::GetPalette(uint32_t* pal, int alpha) const {
    589   ASSERT(GetBPP() <= 8 && !IsCmykImage());
    590   if (GetBPP() == 1) {
    591     pal[0] = ((m_pPalette ? m_pPalette.get()[0] : 0xff000000) & 0xffffff) |
    592              (alpha << 24);
    593     pal[1] = ((m_pPalette ? m_pPalette.get()[1] : 0xffffffff) & 0xffffff) |
    594              (alpha << 24);
    595     return;
    596   }
    597   if (m_pPalette) {
    598     for (int i = 0; i < 256; i++) {
    599       pal[i] = (m_pPalette.get()[i] & 0x00ffffff) | (alpha << 24);
    600     }
    601   } else {
    602     for (int i = 0; i < 256; i++) {
    603       pal[i] = (i * 0x10101) | (alpha << 24);
    604     }
    605   }
    606 }
    607 
    608 std::unique_ptr<CFX_DIBitmap> CFX_DIBSource::CloneAlphaMask(
    609     const FX_RECT* pClip) const {
    610   ASSERT(GetFormat() == FXDIB_Argb);
    611   FX_RECT rect(0, 0, m_Width, m_Height);
    612   if (pClip) {
    613     rect.Intersect(*pClip);
    614     if (rect.IsEmpty())
    615       return nullptr;
    616   }
    617   auto pMask = pdfium::MakeUnique<CFX_DIBitmap>();
    618   if (!pMask->Create(rect.Width(), rect.Height(), FXDIB_8bppMask))
    619     return nullptr;
    620 
    621   for (int row = rect.top; row < rect.bottom; row++) {
    622     const uint8_t* src_scan = GetScanline(row) + rect.left * 4 + 3;
    623     uint8_t* dest_scan =
    624         const_cast<uint8_t*>(pMask->GetScanline(row - rect.top));
    625     for (int col = rect.left; col < rect.right; col++) {
    626       *dest_scan++ = *src_scan;
    627       src_scan += 4;
    628     }
    629   }
    630   return pMask;
    631 }
    632 
    633 bool CFX_DIBSource::SetAlphaMask(const CFX_DIBSource* pAlphaMask,
    634                                  const FX_RECT* pClip) {
    635   if (!HasAlpha() || GetFormat() == FXDIB_Argb)
    636     return false;
    637 
    638   if (!pAlphaMask) {
    639     m_pAlphaMask->Clear(0xff000000);
    640     return true;
    641   }
    642   FX_RECT rect(0, 0, pAlphaMask->m_Width, pAlphaMask->m_Height);
    643   if (pClip) {
    644     rect.Intersect(*pClip);
    645     if (rect.IsEmpty() || rect.Width() != m_Width ||
    646         rect.Height() != m_Height) {
    647       return false;
    648     }
    649   } else {
    650     if (pAlphaMask->m_Width != m_Width || pAlphaMask->m_Height != m_Height)
    651       return false;
    652   }
    653   for (int row = 0; row < m_Height; row++) {
    654     FXSYS_memcpy(const_cast<uint8_t*>(m_pAlphaMask->GetScanline(row)),
    655                  pAlphaMask->GetScanline(row + rect.top) + rect.left,
    656                  m_pAlphaMask->m_Pitch);
    657   }
    658   return true;
    659 }
    660 
    661 const int g_ChannelOffset[] = {0, 2, 1, 0, 0, 1, 2, 3, 3};
    662 bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel,
    663                                CFX_DIBSource* pSrcBitmap,
    664                                FXDIB_Channel srcChannel) {
    665   if (!m_pBuffer)
    666     return false;
    667 
    668   CFX_MaybeOwned<CFX_DIBSource> pSrcClone(pSrcBitmap);
    669   int srcOffset;
    670   if (srcChannel == FXDIB_Alpha) {
    671     if (!pSrcBitmap->HasAlpha() && !pSrcBitmap->IsAlphaMask())
    672       return false;
    673 
    674     if (pSrcBitmap->GetBPP() == 1) {
    675       pSrcClone = pSrcBitmap->CloneConvert(FXDIB_8bppMask);
    676       if (!pSrcClone)
    677         return false;
    678     }
    679     srcOffset = pSrcBitmap->GetFormat() == FXDIB_Argb ? 3 : 0;
    680   } else {
    681     if (pSrcBitmap->IsAlphaMask())
    682       return false;
    683 
    684     if (pSrcBitmap->GetBPP() < 24) {
    685       if (pSrcBitmap->IsCmykImage()) {
    686         pSrcClone = pSrcBitmap->CloneConvert(static_cast<FXDIB_Format>(
    687             (pSrcBitmap->GetFormat() & 0xff00) | 0x20));
    688       } else {
    689         pSrcClone = pSrcBitmap->CloneConvert(static_cast<FXDIB_Format>(
    690             (pSrcBitmap->GetFormat() & 0xff00) | 0x18));
    691       }
    692       if (!pSrcClone)
    693         return false;
    694     }
    695     srcOffset = g_ChannelOffset[srcChannel];
    696   }
    697   int destOffset = 0;
    698   if (destChannel == FXDIB_Alpha) {
    699     if (IsAlphaMask()) {
    700       if (!ConvertFormat(FXDIB_8bppMask))
    701         return false;
    702     } else {
    703       if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb))
    704         return false;
    705 
    706       if (GetFormat() == FXDIB_Argb)
    707         destOffset = 3;
    708     }
    709   } else {
    710     if (IsAlphaMask())
    711       return false;
    712 
    713     if (GetBPP() < 24) {
    714       if (HasAlpha()) {
    715         if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb))
    716           return false;
    717 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
    718       } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) {
    719 #else
    720       } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) {
    721 #endif
    722         return false;
    723       }
    724     }
    725     destOffset = g_ChannelOffset[destChannel];
    726   }
    727   if (srcChannel == FXDIB_Alpha && pSrcClone->m_pAlphaMask) {
    728     CFX_MaybeOwned<CFX_DIBSource> pAlphaMask(pSrcClone->m_pAlphaMask);
    729     if (pSrcClone->GetWidth() != m_Width ||
    730         pSrcClone->GetHeight() != m_Height) {
    731       if (pAlphaMask) {
    732         pAlphaMask = pAlphaMask->StretchTo(m_Width, m_Height);
    733         if (!pAlphaMask)
    734           return false;
    735       }
    736     }
    737     pSrcClone = std::move(pAlphaMask);
    738     srcOffset = 0;
    739   } else if (pSrcClone->GetWidth() != m_Width ||
    740              pSrcClone->GetHeight() != m_Height) {
    741     std::unique_ptr<CFX_DIBitmap> pSrcMatched =
    742         pSrcClone->StretchTo(m_Width, m_Height);
    743     if (!pSrcMatched)
    744       return false;
    745 
    746     pSrcClone = std::move(pSrcMatched);
    747   }
    748   CFX_DIBitmap* pDst = this;
    749   if (destChannel == FXDIB_Alpha && m_pAlphaMask) {
    750     pDst = m_pAlphaMask;
    751     destOffset = 0;
    752   }
    753   int srcBytes = pSrcClone->GetBPP() / 8;
    754   int destBytes = pDst->GetBPP() / 8;
    755   for (int row = 0; row < m_Height; row++) {
    756     uint8_t* dest_pos = (uint8_t*)pDst->GetScanline(row) + destOffset;
    757     const uint8_t* src_pos = pSrcClone->GetScanline(row) + srcOffset;
    758     for (int col = 0; col < m_Width; col++) {
    759       *dest_pos = *src_pos;
    760       dest_pos += destBytes;
    761       src_pos += srcBytes;
    762     }
    763   }
    764   return true;
    765 }
    766 
    767 bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, int value) {
    768   if (!m_pBuffer) {
    769     return false;
    770   }
    771   int destOffset;
    772   if (destChannel == FXDIB_Alpha) {
    773     if (IsAlphaMask()) {
    774       if (!ConvertFormat(FXDIB_8bppMask)) {
    775         return false;
    776       }
    777       destOffset = 0;
    778     } else {
    779       destOffset = 0;
    780       if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {
    781         return false;
    782       }
    783       if (GetFormat() == FXDIB_Argb) {
    784         destOffset = 3;
    785       }
    786     }
    787   } else {
    788     if (IsAlphaMask()) {
    789       return false;
    790     }
    791     if (GetBPP() < 24) {
    792       if (HasAlpha()) {
    793         if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {
    794           return false;
    795         }
    796 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
    797       } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) {
    798 #else
    799       } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) {
    800 #endif
    801         return false;
    802       }
    803     }
    804     destOffset = g_ChannelOffset[destChannel];
    805   }
    806   int Bpp = GetBPP() / 8;
    807   if (Bpp == 1) {
    808     FXSYS_memset(m_pBuffer, value, m_Height * m_Pitch);
    809     return true;
    810   }
    811   if (destChannel == FXDIB_Alpha && m_pAlphaMask) {
    812     FXSYS_memset(m_pAlphaMask->GetBuffer(), value,
    813                  m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch());
    814     return true;
    815   }
    816   for (int row = 0; row < m_Height; row++) {
    817     uint8_t* scan_line = m_pBuffer + row * m_Pitch + destOffset;
    818     for (int col = 0; col < m_Width; col++) {
    819       *scan_line = value;
    820       scan_line += Bpp;
    821     }
    822   }
    823   return true;
    824 }
    825 
    826 bool CFX_DIBitmap::MultiplyAlpha(CFX_DIBSource* pSrcBitmap) {
    827   if (!m_pBuffer)
    828     return false;
    829 
    830   ASSERT(pSrcBitmap->IsAlphaMask());
    831   if (!pSrcBitmap->IsAlphaMask())
    832     return false;
    833 
    834   if (!IsAlphaMask() && !HasAlpha())
    835     return LoadChannel(FXDIB_Alpha, pSrcBitmap, FXDIB_Alpha);
    836 
    837   CFX_MaybeOwned<CFX_DIBitmap> pSrcClone(
    838       static_cast<CFX_DIBitmap*>(pSrcBitmap));
    839   if (pSrcBitmap->GetWidth() != m_Width ||
    840       pSrcBitmap->GetHeight() != m_Height) {
    841     pSrcClone = pSrcBitmap->StretchTo(m_Width, m_Height);
    842     if (!pSrcClone)
    843       return false;
    844   }
    845   if (IsAlphaMask()) {
    846     if (!ConvertFormat(FXDIB_8bppMask))
    847       return false;
    848 
    849     for (int row = 0; row < m_Height; row++) {
    850       uint8_t* dest_scan = m_pBuffer + m_Pitch * row;
    851       uint8_t* src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row;
    852       if (pSrcClone->GetBPP() == 1) {
    853         for (int col = 0; col < m_Width; col++) {
    854           if (!((1 << (7 - col % 8)) & src_scan[col / 8]))
    855             dest_scan[col] = 0;
    856         }
    857       } else {
    858         for (int col = 0; col < m_Width; col++) {
    859           *dest_scan = (*dest_scan) * src_scan[col] / 255;
    860           dest_scan++;
    861         }
    862       }
    863     }
    864   } else {
    865     if (GetFormat() == FXDIB_Argb) {
    866       if (pSrcClone->GetBPP() == 1)
    867         return false;
    868 
    869       for (int row = 0; row < m_Height; row++) {
    870         uint8_t* dest_scan = m_pBuffer + m_Pitch * row + 3;
    871         uint8_t* src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row;
    872         for (int col = 0; col < m_Width; col++) {
    873           *dest_scan = (*dest_scan) * src_scan[col] / 255;
    874           dest_scan += 4;
    875         }
    876       }
    877     } else {
    878       m_pAlphaMask->MultiplyAlpha(pSrcClone.Get());
    879     }
    880   }
    881   return true;
    882 }
    883 
    884 bool CFX_DIBitmap::GetGrayData(void* pIccTransform) {
    885   if (!m_pBuffer) {
    886     return false;
    887   }
    888   switch (GetFormat()) {
    889     case FXDIB_1bppRgb: {
    890       if (!m_pPalette) {
    891         return false;
    892       }
    893       uint8_t gray[2];
    894       for (int i = 0; i < 2; i++) {
    895         int r = static_cast<uint8_t>(m_pPalette.get()[i] >> 16);
    896         int g = static_cast<uint8_t>(m_pPalette.get()[i] >> 8);
    897         int b = static_cast<uint8_t>(m_pPalette.get()[i]);
    898         gray[i] = static_cast<uint8_t>(FXRGB2GRAY(r, g, b));
    899       }
    900       CFX_DIBitmap* pMask = new CFX_DIBitmap;
    901       if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
    902         delete pMask;
    903         return false;
    904       }
    905       FXSYS_memset(pMask->GetBuffer(), gray[0], pMask->GetPitch() * m_Height);
    906       for (int row = 0; row < m_Height; row++) {
    907         uint8_t* src_pos = m_pBuffer + row * m_Pitch;
    908         uint8_t* dest_pos = (uint8_t*)pMask->GetScanline(row);
    909         for (int col = 0; col < m_Width; col++) {
    910           if (src_pos[col / 8] & (1 << (7 - col % 8))) {
    911             *dest_pos = gray[1];
    912           }
    913           dest_pos++;
    914         }
    915       }
    916       TakeOver(pMask);
    917       delete pMask;
    918       break;
    919     }
    920     case FXDIB_8bppRgb: {
    921       if (!m_pPalette) {
    922         return false;
    923       }
    924       uint8_t gray[256];
    925       for (int i = 0; i < 256; i++) {
    926         int r = static_cast<uint8_t>(m_pPalette.get()[i] >> 16);
    927         int g = static_cast<uint8_t>(m_pPalette.get()[i] >> 8);
    928         int b = static_cast<uint8_t>(m_pPalette.get()[i]);
    929         gray[i] = static_cast<uint8_t>(FXRGB2GRAY(r, g, b));
    930       }
    931       CFX_DIBitmap* pMask = new CFX_DIBitmap;
    932       if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
    933         delete pMask;
    934         return false;
    935       }
    936       for (int row = 0; row < m_Height; row++) {
    937         uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();
    938         uint8_t* src_pos = m_pBuffer + row * m_Pitch;
    939         for (int col = 0; col < m_Width; col++) {
    940           *dest_pos++ = gray[*src_pos++];
    941         }
    942       }
    943       TakeOver(pMask);
    944       delete pMask;
    945       break;
    946     }
    947     case FXDIB_Rgb: {
    948       CFX_DIBitmap* pMask = new CFX_DIBitmap;
    949       if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
    950         delete pMask;
    951         return false;
    952       }
    953       for (int row = 0; row < m_Height; row++) {
    954         uint8_t* src_pos = m_pBuffer + row * m_Pitch;
    955         uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();
    956         for (int col = 0; col < m_Width; col++) {
    957           *dest_pos++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos);
    958           src_pos += 3;
    959         }
    960       }
    961       TakeOver(pMask);
    962       delete pMask;
    963       break;
    964     }
    965     case FXDIB_Rgb32: {
    966       CFX_DIBitmap* pMask = new CFX_DIBitmap;
    967       if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
    968         delete pMask;
    969         return false;
    970       }
    971       for (int row = 0; row < m_Height; row++) {
    972         uint8_t* src_pos = m_pBuffer + row * m_Pitch;
    973         uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();
    974         for (int col = 0; col < m_Width; col++) {
    975           *dest_pos++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos);
    976           src_pos += 4;
    977         }
    978       }
    979       TakeOver(pMask);
    980       delete pMask;
    981       break;
    982     }
    983     default:
    984       return false;
    985   }
    986   return true;
    987 }
    988 
    989 bool CFX_DIBitmap::MultiplyAlpha(int alpha) {
    990   if (!m_pBuffer) {
    991     return false;
    992   }
    993   switch (GetFormat()) {
    994     case FXDIB_1bppMask:
    995       if (!ConvertFormat(FXDIB_8bppMask)) {
    996         return false;
    997       }
    998       MultiplyAlpha(alpha);
    999       break;
   1000     case FXDIB_8bppMask: {
   1001       for (int row = 0; row < m_Height; row++) {
   1002         uint8_t* scan_line = m_pBuffer + row * m_Pitch;
   1003         for (int col = 0; col < m_Width; col++) {
   1004           scan_line[col] = scan_line[col] * alpha / 255;
   1005         }
   1006       }
   1007       break;
   1008     }
   1009     case FXDIB_Argb: {
   1010       for (int row = 0; row < m_Height; row++) {
   1011         uint8_t* scan_line = m_pBuffer + row * m_Pitch + 3;
   1012         for (int col = 0; col < m_Width; col++) {
   1013           *scan_line = (*scan_line) * alpha / 255;
   1014           scan_line += 4;
   1015         }
   1016       }
   1017       break;
   1018     }
   1019     default:
   1020       if (HasAlpha()) {
   1021         m_pAlphaMask->MultiplyAlpha(alpha);
   1022       } else if (IsCmykImage()) {
   1023         if (!ConvertFormat((FXDIB_Format)(GetFormat() | 0x0200))) {
   1024           return false;
   1025         }
   1026         m_pAlphaMask->MultiplyAlpha(alpha);
   1027       } else {
   1028         if (!ConvertFormat(FXDIB_Argb)) {
   1029           return false;
   1030         }
   1031         MultiplyAlpha(alpha);
   1032       }
   1033       break;
   1034   }
   1035   return true;
   1036 }
   1037 
   1038 uint32_t CFX_DIBitmap::GetPixel(int x, int y) const {
   1039   if (!m_pBuffer) {
   1040     return 0;
   1041   }
   1042   uint8_t* pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8;
   1043   switch (GetFormat()) {
   1044     case FXDIB_1bppMask: {
   1045       if ((*pos) & (1 << (7 - x % 8))) {
   1046         return 0xff000000;
   1047       }
   1048       return 0;
   1049     }
   1050     case FXDIB_1bppRgb: {
   1051       if ((*pos) & (1 << (7 - x % 8))) {
   1052         return m_pPalette ? m_pPalette.get()[1] : 0xffffffff;
   1053       }
   1054       return m_pPalette ? m_pPalette.get()[0] : 0xff000000;
   1055     }
   1056     case FXDIB_8bppMask:
   1057       return (*pos) << 24;
   1058     case FXDIB_8bppRgb:
   1059       return m_pPalette ? m_pPalette.get()[*pos]
   1060                         : (0xff000000 | ((*pos) * 0x10101));
   1061     case FXDIB_Rgb:
   1062     case FXDIB_Rgba:
   1063     case FXDIB_Rgb32:
   1064       return FXARGB_GETDIB(pos) | 0xff000000;
   1065     case FXDIB_Argb:
   1066       return FXARGB_GETDIB(pos);
   1067     default:
   1068       break;
   1069   }
   1070   return 0;
   1071 }
   1072 
   1073 void CFX_DIBitmap::SetPixel(int x, int y, uint32_t color) {
   1074   if (!m_pBuffer) {
   1075     return;
   1076   }
   1077   if (x < 0 || x >= m_Width || y < 0 || y >= m_Height) {
   1078     return;
   1079   }
   1080   uint8_t* pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8;
   1081   switch (GetFormat()) {
   1082     case FXDIB_1bppMask:
   1083       if (color >> 24) {
   1084         *pos |= 1 << (7 - x % 8);
   1085       } else {
   1086         *pos &= ~(1 << (7 - x % 8));
   1087       }
   1088       break;
   1089     case FXDIB_1bppRgb:
   1090       if (m_pPalette) {
   1091         if (color == m_pPalette.get()[1]) {
   1092           *pos |= 1 << (7 - x % 8);
   1093         } else {
   1094           *pos &= ~(1 << (7 - x % 8));
   1095         }
   1096       } else {
   1097         if (color == 0xffffffff) {
   1098           *pos |= 1 << (7 - x % 8);
   1099         } else {
   1100           *pos &= ~(1 << (7 - x % 8));
   1101         }
   1102       }
   1103       break;
   1104     case FXDIB_8bppMask:
   1105       *pos = (uint8_t)(color >> 24);
   1106       break;
   1107     case FXDIB_8bppRgb: {
   1108       if (m_pPalette) {
   1109         for (int i = 0; i < 256; i++) {
   1110           if (m_pPalette.get()[i] == color) {
   1111             *pos = (uint8_t)i;
   1112             return;
   1113           }
   1114         }
   1115         *pos = 0;
   1116       } else {
   1117         *pos = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
   1118       }
   1119       break;
   1120     }
   1121     case FXDIB_Rgb:
   1122     case FXDIB_Rgb32: {
   1123       int alpha = FXARGB_A(color);
   1124       pos[0] = (FXARGB_B(color) * alpha + pos[0] * (255 - alpha)) / 255;
   1125       pos[1] = (FXARGB_G(color) * alpha + pos[1] * (255 - alpha)) / 255;
   1126       pos[2] = (FXARGB_R(color) * alpha + pos[2] * (255 - alpha)) / 255;
   1127       break;
   1128     }
   1129     case FXDIB_Rgba: {
   1130       pos[0] = FXARGB_B(color);
   1131       pos[1] = FXARGB_G(color);
   1132       pos[2] = FXARGB_R(color);
   1133       break;
   1134     }
   1135     case FXDIB_Argb:
   1136       FXARGB_SETDIB(pos, color);
   1137       break;
   1138     default:
   1139       break;
   1140   }
   1141 }
   1142 
   1143 void CFX_DIBitmap::DownSampleScanline(int line,
   1144                                       uint8_t* dest_scan,
   1145                                       int dest_bpp,
   1146                                       int dest_width,
   1147                                       bool bFlipX,
   1148                                       int clip_left,
   1149                                       int clip_width) const {
   1150   if (!m_pBuffer) {
   1151     return;
   1152   }
   1153   int src_Bpp = m_bpp / 8;
   1154   uint8_t* scanline = m_pBuffer + line * m_Pitch;
   1155   if (src_Bpp == 0) {
   1156     for (int i = 0; i < clip_width; i++) {
   1157       uint32_t dest_x = clip_left + i;
   1158       uint32_t src_x = dest_x * m_Width / dest_width;
   1159       if (bFlipX) {
   1160         src_x = m_Width - src_x - 1;
   1161       }
   1162       src_x %= m_Width;
   1163       dest_scan[i] = (scanline[src_x / 8] & (1 << (7 - src_x % 8))) ? 255 : 0;
   1164     }
   1165   } else if (src_Bpp == 1) {
   1166     for (int i = 0; i < clip_width; i++) {
   1167       uint32_t dest_x = clip_left + i;
   1168       uint32_t src_x = dest_x * m_Width / dest_width;
   1169       if (bFlipX) {
   1170         src_x = m_Width - src_x - 1;
   1171       }
   1172       src_x %= m_Width;
   1173       int dest_pos = i;
   1174       if (m_pPalette) {
   1175         if (!IsCmykImage()) {
   1176           dest_pos *= 3;
   1177           FX_ARGB argb = m_pPalette.get()[scanline[src_x]];
   1178           dest_scan[dest_pos] = FXARGB_B(argb);
   1179           dest_scan[dest_pos + 1] = FXARGB_G(argb);
   1180           dest_scan[dest_pos + 2] = FXARGB_R(argb);
   1181         } else {
   1182           dest_pos *= 4;
   1183           FX_CMYK cmyk = m_pPalette.get()[scanline[src_x]];
   1184           dest_scan[dest_pos] = FXSYS_GetCValue(cmyk);
   1185           dest_scan[dest_pos + 1] = FXSYS_GetMValue(cmyk);
   1186           dest_scan[dest_pos + 2] = FXSYS_GetYValue(cmyk);
   1187           dest_scan[dest_pos + 3] = FXSYS_GetKValue(cmyk);
   1188         }
   1189       } else {
   1190         dest_scan[dest_pos] = scanline[src_x];
   1191       }
   1192     }
   1193   } else {
   1194     for (int i = 0; i < clip_width; i++) {
   1195       uint32_t dest_x = clip_left + i;
   1196       uint32_t src_x =
   1197           bFlipX ? (m_Width - dest_x * m_Width / dest_width - 1) * src_Bpp
   1198                  : (dest_x * m_Width / dest_width) * src_Bpp;
   1199       src_x %= m_Width * src_Bpp;
   1200       int dest_pos = i * src_Bpp;
   1201       for (int b = 0; b < src_Bpp; b++) {
   1202         dest_scan[dest_pos + b] = scanline[src_x + b];
   1203       }
   1204     }
   1205   }
   1206 }
   1207 
   1208 // TODO(weili): Split this function into two for handling CMYK and RGB
   1209 // colors separately.
   1210 bool CFX_DIBitmap::ConvertColorScale(uint32_t forecolor, uint32_t backcolor) {
   1211   ASSERT(!IsAlphaMask());
   1212   if (!m_pBuffer || IsAlphaMask()) {
   1213     return false;
   1214   }
   1215   // Values used for CMYK colors.
   1216   int fc = 0;
   1217   int fm = 0;
   1218   int fy = 0;
   1219   int fk = 0;
   1220   int bc = 0;
   1221   int bm = 0;
   1222   int by = 0;
   1223   int bk = 0;
   1224   // Values used for RGB colors.
   1225   int fr = 0;
   1226   int fg = 0;
   1227   int fb = 0;
   1228   int br = 0;
   1229   int bg = 0;
   1230   int bb = 0;
   1231   bool isCmykImage = IsCmykImage();
   1232   if (isCmykImage) {
   1233     fc = FXSYS_GetCValue(forecolor);
   1234     fm = FXSYS_GetMValue(forecolor);
   1235     fy = FXSYS_GetYValue(forecolor);
   1236     fk = FXSYS_GetKValue(forecolor);
   1237     bc = FXSYS_GetCValue(backcolor);
   1238     bm = FXSYS_GetMValue(backcolor);
   1239     by = FXSYS_GetYValue(backcolor);
   1240     bk = FXSYS_GetKValue(backcolor);
   1241   } else {
   1242     fr = FXSYS_GetRValue(forecolor);
   1243     fg = FXSYS_GetGValue(forecolor);
   1244     fb = FXSYS_GetBValue(forecolor);
   1245     br = FXSYS_GetRValue(backcolor);
   1246     bg = FXSYS_GetGValue(backcolor);
   1247     bb = FXSYS_GetBValue(backcolor);
   1248   }
   1249   if (m_bpp <= 8) {
   1250     if (isCmykImage) {
   1251       if (forecolor == 0xff && backcolor == 0 && !m_pPalette) {
   1252         return true;
   1253       }
   1254     } else if (forecolor == 0 && backcolor == 0xffffff && !m_pPalette) {
   1255       return true;
   1256     }
   1257     if (!m_pPalette) {
   1258       BuildPalette();
   1259     }
   1260     int size = 1 << m_bpp;
   1261     if (isCmykImage) {
   1262       for (int i = 0; i < size; i++) {
   1263         uint8_t b, g, r;
   1264         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(m_pPalette.get()[i]),
   1265                            FXSYS_GetMValue(m_pPalette.get()[i]),
   1266                            FXSYS_GetYValue(m_pPalette.get()[i]),
   1267                            FXSYS_GetKValue(m_pPalette.get()[i]), r, g, b);
   1268         int gray = 255 - FXRGB2GRAY(r, g, b);
   1269         m_pPalette.get()[i] = CmykEncode(
   1270             bc + (fc - bc) * gray / 255, bm + (fm - bm) * gray / 255,
   1271             by + (fy - by) * gray / 255, bk + (fk - bk) * gray / 255);
   1272       }
   1273     } else {
   1274       for (int i = 0; i < size; i++) {
   1275         int gray = FXRGB2GRAY(FXARGB_R(m_pPalette.get()[i]),
   1276                               FXARGB_G(m_pPalette.get()[i]),
   1277                               FXARGB_B(m_pPalette.get()[i]));
   1278         m_pPalette.get()[i] = FXARGB_MAKE(0xff, br + (fr - br) * gray / 255,
   1279                                           bg + (fg - bg) * gray / 255,
   1280                                           bb + (fb - bb) * gray / 255);
   1281       }
   1282     }
   1283     return true;
   1284   }
   1285   if (isCmykImage) {
   1286     if (forecolor == 0xff && backcolor == 0x00) {
   1287       for (int row = 0; row < m_Height; row++) {
   1288         uint8_t* scanline = m_pBuffer + row * m_Pitch;
   1289         for (int col = 0; col < m_Width; col++) {
   1290           uint8_t b, g, r;
   1291           AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3],
   1292                              r, g, b);
   1293           *scanline++ = 0;
   1294           *scanline++ = 0;
   1295           *scanline++ = 0;
   1296           *scanline++ = 255 - FXRGB2GRAY(r, g, b);
   1297         }
   1298       }
   1299       return true;
   1300     }
   1301   } else if (forecolor == 0 && backcolor == 0xffffff) {
   1302     for (int row = 0; row < m_Height; row++) {
   1303       uint8_t* scanline = m_pBuffer + row * m_Pitch;
   1304       int gap = m_bpp / 8 - 2;
   1305       for (int col = 0; col < m_Width; col++) {
   1306         int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]);
   1307         *scanline++ = gray;
   1308         *scanline++ = gray;
   1309         *scanline = gray;
   1310         scanline += gap;
   1311       }
   1312     }
   1313     return true;
   1314   }
   1315   if (isCmykImage) {
   1316     for (int row = 0; row < m_Height; row++) {
   1317       uint8_t* scanline = m_pBuffer + row * m_Pitch;
   1318       for (int col = 0; col < m_Width; col++) {
   1319         uint8_t b, g, r;
   1320         AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3],
   1321                            r, g, b);
   1322         int gray = 255 - FXRGB2GRAY(r, g, b);
   1323         *scanline++ = bc + (fc - bc) * gray / 255;
   1324         *scanline++ = bm + (fm - bm) * gray / 255;
   1325         *scanline++ = by + (fy - by) * gray / 255;
   1326         *scanline++ = bk + (fk - bk) * gray / 255;
   1327       }
   1328     }
   1329   } else {
   1330     for (int row = 0; row < m_Height; row++) {
   1331       uint8_t* scanline = m_pBuffer + row * m_Pitch;
   1332       int gap = m_bpp / 8 - 2;
   1333       for (int col = 0; col < m_Width; col++) {
   1334         int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]);
   1335         *scanline++ = bb + (fb - bb) * gray / 255;
   1336         *scanline++ = bg + (fg - bg) * gray / 255;
   1337         *scanline = br + (fr - br) * gray / 255;
   1338         scanline += gap;
   1339       }
   1340     }
   1341   }
   1342   return true;
   1343 }
   1344 
   1345 std::unique_ptr<CFX_DIBitmap> CFX_DIBSource::FlipImage(bool bXFlip,
   1346                                                        bool bYFlip) const {
   1347   auto pFlipped = pdfium::MakeUnique<CFX_DIBitmap>();
   1348   if (!pFlipped->Create(m_Width, m_Height, GetFormat()))
   1349     return nullptr;
   1350 
   1351   pFlipped->SetPalette(m_pPalette.get());
   1352   uint8_t* pDestBuffer = pFlipped->GetBuffer();
   1353   int Bpp = m_bpp / 8;
   1354   for (int row = 0; row < m_Height; row++) {
   1355     const uint8_t* src_scan = GetScanline(row);
   1356     uint8_t* dest_scan =
   1357         pDestBuffer + m_Pitch * (bYFlip ? (m_Height - row - 1) : row);
   1358     if (!bXFlip) {
   1359       FXSYS_memcpy(dest_scan, src_scan, m_Pitch);
   1360       continue;
   1361     }
   1362     if (m_bpp == 1) {
   1363       FXSYS_memset(dest_scan, 0, m_Pitch);
   1364       for (int col = 0; col < m_Width; col++)
   1365         if (src_scan[col / 8] & (1 << (7 - col % 8))) {
   1366           int dest_col = m_Width - col - 1;
   1367           dest_scan[dest_col / 8] |= (1 << (7 - dest_col % 8));
   1368         }
   1369     } else {
   1370       dest_scan += (m_Width - 1) * Bpp;
   1371       if (Bpp == 1) {
   1372         for (int col = 0; col < m_Width; col++) {
   1373           *dest_scan = *src_scan;
   1374           dest_scan--;
   1375           src_scan++;
   1376         }
   1377       } else if (Bpp == 3) {
   1378         for (int col = 0; col < m_Width; col++) {
   1379           dest_scan[0] = src_scan[0];
   1380           dest_scan[1] = src_scan[1];
   1381           dest_scan[2] = src_scan[2];
   1382           dest_scan -= 3;
   1383           src_scan += 3;
   1384         }
   1385       } else {
   1386         ASSERT(Bpp == 4);
   1387         for (int col = 0; col < m_Width; col++) {
   1388           *(uint32_t*)dest_scan = *(uint32_t*)src_scan;
   1389           dest_scan -= 4;
   1390           src_scan += 4;
   1391         }
   1392       }
   1393     }
   1394   }
   1395   if (m_pAlphaMask) {
   1396     pDestBuffer = pFlipped->m_pAlphaMask->GetBuffer();
   1397     uint32_t dest_pitch = pFlipped->m_pAlphaMask->GetPitch();
   1398     for (int row = 0; row < m_Height; row++) {
   1399       const uint8_t* src_scan = m_pAlphaMask->GetScanline(row);
   1400       uint8_t* dest_scan =
   1401           pDestBuffer + dest_pitch * (bYFlip ? (m_Height - row - 1) : row);
   1402       if (!bXFlip) {
   1403         FXSYS_memcpy(dest_scan, src_scan, dest_pitch);
   1404         continue;
   1405       }
   1406       dest_scan += (m_Width - 1);
   1407       for (int col = 0; col < m_Width; col++) {
   1408         *dest_scan = *src_scan;
   1409         dest_scan--;
   1410         src_scan++;
   1411       }
   1412     }
   1413   }
   1414   return pFlipped;
   1415 }
   1416 
   1417 CFX_DIBExtractor::CFX_DIBExtractor(const CFX_DIBSource* pSrc) {
   1418   if (pSrc->GetBuffer()) {
   1419     m_pBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
   1420     if (!m_pBitmap->Create(pSrc->GetWidth(), pSrc->GetHeight(),
   1421                            pSrc->GetFormat(), pSrc->GetBuffer())) {
   1422       m_pBitmap.reset();
   1423       return;
   1424     }
   1425     m_pBitmap->SetPalette(pSrc->GetPalette());
   1426     m_pBitmap->SetAlphaMask(pSrc->m_pAlphaMask);
   1427   } else {
   1428     m_pBitmap = pSrc->Clone();
   1429   }
   1430 }
   1431 
   1432 CFX_DIBExtractor::~CFX_DIBExtractor() {}
   1433 
   1434 CFX_FilteredDIB::CFX_FilteredDIB() : m_pSrc(nullptr) {}
   1435 
   1436 CFX_FilteredDIB::~CFX_FilteredDIB() {
   1437   if (m_bAutoDropSrc) {
   1438     delete m_pSrc;
   1439   }
   1440 }
   1441 
   1442 void CFX_FilteredDIB::LoadSrc(const CFX_DIBSource* pSrc, bool bAutoDropSrc) {
   1443   m_pSrc = pSrc;
   1444   m_bAutoDropSrc = bAutoDropSrc;
   1445   m_Width = pSrc->GetWidth();
   1446   m_Height = pSrc->GetHeight();
   1447   FXDIB_Format format = GetDestFormat();
   1448   m_bpp = (uint8_t)format;
   1449   m_AlphaFlag = (uint8_t)(format >> 8);
   1450   m_Pitch = (m_Width * (format & 0xff) + 31) / 32 * 4;
   1451   m_pPalette.reset(GetDestPalette());
   1452   m_Scanline.resize(m_Pitch);
   1453 }
   1454 
   1455 const uint8_t* CFX_FilteredDIB::GetScanline(int line) const {
   1456   TranslateScanline(m_pSrc->GetScanline(line), &m_Scanline);
   1457   return m_Scanline.data();
   1458 }
   1459 
   1460 void CFX_FilteredDIB::DownSampleScanline(int line,
   1461                                          uint8_t* dest_scan,
   1462                                          int dest_bpp,
   1463                                          int dest_width,
   1464                                          bool bFlipX,
   1465                                          int clip_left,
   1466                                          int clip_width) const {
   1467   m_pSrc->DownSampleScanline(line, dest_scan, dest_bpp, dest_width, bFlipX,
   1468                              clip_left, clip_width);
   1469   TranslateDownSamples(dest_scan, dest_scan, clip_width, dest_bpp);
   1470 }
   1471 
   1472 CFX_ImageRenderer::CFX_ImageRenderer() {
   1473   m_Status = 0;
   1474   m_pIccTransform = nullptr;
   1475   m_bRgbByteOrder = false;
   1476   m_BlendType = FXDIB_BLEND_NORMAL;
   1477 }
   1478 
   1479 CFX_ImageRenderer::~CFX_ImageRenderer() {}
   1480 
   1481 bool CFX_ImageRenderer::Start(CFX_DIBitmap* pDevice,
   1482                               const CFX_ClipRgn* pClipRgn,
   1483                               const CFX_DIBSource* pSource,
   1484                               int bitmap_alpha,
   1485                               uint32_t mask_color,
   1486                               const CFX_Matrix* pMatrix,
   1487                               uint32_t dib_flags,
   1488                               bool bRgbByteOrder,
   1489                               int alpha_flag,
   1490                               void* pIccTransform,
   1491                               int blend_type) {
   1492   m_Matrix = *pMatrix;
   1493   CFX_FloatRect image_rect_f = m_Matrix.GetUnitRect();
   1494   FX_RECT image_rect = image_rect_f.GetOuterRect();
   1495   m_ClipBox = pClipRgn ? pClipRgn->GetBox() : FX_RECT(0, 0, pDevice->GetWidth(),
   1496                                                       pDevice->GetHeight());
   1497   m_ClipBox.Intersect(image_rect);
   1498   if (m_ClipBox.IsEmpty())
   1499     return false;
   1500 
   1501   m_pDevice = pDevice;
   1502   m_pClipRgn = pClipRgn;
   1503   m_MaskColor = mask_color;
   1504   m_BitmapAlpha = bitmap_alpha;
   1505   m_Matrix = *pMatrix;
   1506   m_Flags = dib_flags;
   1507   m_AlphaFlag = alpha_flag;
   1508   m_pIccTransform = pIccTransform;
   1509   m_bRgbByteOrder = bRgbByteOrder;
   1510   m_BlendType = blend_type;
   1511 
   1512   if ((FXSYS_fabs(m_Matrix.b) >= 0.5f || m_Matrix.a == 0) ||
   1513       (FXSYS_fabs(m_Matrix.c) >= 0.5f || m_Matrix.d == 0)) {
   1514     if (FXSYS_fabs(m_Matrix.a) < FXSYS_fabs(m_Matrix.b) / 20 &&
   1515         FXSYS_fabs(m_Matrix.d) < FXSYS_fabs(m_Matrix.c) / 20 &&
   1516         FXSYS_fabs(m_Matrix.a) < 0.5f && FXSYS_fabs(m_Matrix.d) < 0.5f) {
   1517       int dest_width = image_rect.Width();
   1518       int dest_height = image_rect.Height();
   1519       FX_RECT bitmap_clip = m_ClipBox;
   1520       bitmap_clip.Offset(-image_rect.left, -image_rect.top);
   1521       bitmap_clip = FXDIB_SwapClipBox(bitmap_clip, dest_width, dest_height,
   1522                                       m_Matrix.c > 0, m_Matrix.b < 0);
   1523       m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox,
   1524                          true, m_Matrix.c > 0, m_Matrix.b < 0, m_bRgbByteOrder,
   1525                          alpha_flag, pIccTransform, m_BlendType);
   1526       m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
   1527           &m_Composer, pSource, dest_height, dest_width, bitmap_clip,
   1528           dib_flags);
   1529       if (!m_Stretcher->Start())
   1530         return false;
   1531 
   1532       m_Status = 1;
   1533       return true;
   1534     }
   1535     m_Status = 2;
   1536     m_pTransformer.reset(
   1537         new CFX_ImageTransformer(pSource, &m_Matrix, dib_flags, &m_ClipBox));
   1538     m_pTransformer->Start();
   1539     return true;
   1540   }
   1541 
   1542   int dest_width = image_rect.Width();
   1543   if (m_Matrix.a < 0)
   1544     dest_width = -dest_width;
   1545 
   1546   int dest_height = image_rect.Height();
   1547   if (m_Matrix.d > 0)
   1548     dest_height = -dest_height;
   1549 
   1550   if (dest_width == 0 || dest_height == 0)
   1551     return false;
   1552 
   1553   FX_RECT bitmap_clip = m_ClipBox;
   1554   bitmap_clip.Offset(-image_rect.left, -image_rect.top);
   1555   m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox,
   1556                      false, false, false, m_bRgbByteOrder, alpha_flag,
   1557                      pIccTransform, m_BlendType);
   1558   m_Status = 1;
   1559   m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
   1560       &m_Composer, pSource, dest_width, dest_height, bitmap_clip, dib_flags);
   1561   return m_Stretcher->Start();
   1562 }
   1563 
   1564 bool CFX_ImageRenderer::Continue(IFX_Pause* pPause) {
   1565   if (m_Status == 1)
   1566     return m_Stretcher->Continue(pPause);
   1567 
   1568   if (m_Status == 2) {
   1569     if (m_pTransformer->Continue(pPause))
   1570       return true;
   1571 
   1572     std::unique_ptr<CFX_DIBitmap> pBitmap(m_pTransformer->DetachBitmap());
   1573     if (!pBitmap || !pBitmap->GetBuffer())
   1574       return false;
   1575 
   1576     if (pBitmap->IsAlphaMask()) {
   1577       if (m_BitmapAlpha != 255) {
   1578         if (m_AlphaFlag >> 8) {
   1579           m_AlphaFlag =
   1580               (((uint8_t)((m_AlphaFlag & 0xff) * m_BitmapAlpha / 255)) |
   1581                ((m_AlphaFlag >> 8) << 8));
   1582         } else {
   1583           m_MaskColor = FXARGB_MUL_ALPHA(m_MaskColor, m_BitmapAlpha);
   1584         }
   1585       }
   1586       m_pDevice->CompositeMask(
   1587           m_pTransformer->result().left, m_pTransformer->result().top,
   1588           pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap.get(), m_MaskColor,
   1589           0, 0, m_BlendType, m_pClipRgn, m_bRgbByteOrder, m_AlphaFlag,
   1590           m_pIccTransform);
   1591     } else {
   1592       if (m_BitmapAlpha != 255)
   1593         pBitmap->MultiplyAlpha(m_BitmapAlpha);
   1594       m_pDevice->CompositeBitmap(
   1595           m_pTransformer->result().left, m_pTransformer->result().top,
   1596           pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap.get(), 0, 0,
   1597           m_BlendType, m_pClipRgn, m_bRgbByteOrder, m_pIccTransform);
   1598     }
   1599     return false;
   1600   }
   1601   return false;
   1602 }
   1603 
   1604 CFX_BitmapStorer::CFX_BitmapStorer() {
   1605 }
   1606 
   1607 CFX_BitmapStorer::~CFX_BitmapStorer() {
   1608 }
   1609 
   1610 std::unique_ptr<CFX_DIBitmap> CFX_BitmapStorer::Detach() {
   1611   return std::move(m_pBitmap);
   1612 }
   1613 
   1614 void CFX_BitmapStorer::Replace(std::unique_ptr<CFX_DIBitmap> pBitmap) {
   1615   m_pBitmap = std::move(pBitmap);
   1616 }
   1617 
   1618 void CFX_BitmapStorer::ComposeScanline(int line,
   1619                                        const uint8_t* scanline,
   1620                                        const uint8_t* scan_extra_alpha) {
   1621   uint8_t* dest_buf = const_cast<uint8_t*>(m_pBitmap->GetScanline(line));
   1622   uint8_t* dest_alpha_buf =
   1623       m_pBitmap->m_pAlphaMask
   1624           ? const_cast<uint8_t*>(m_pBitmap->m_pAlphaMask->GetScanline(line))
   1625           : nullptr;
   1626   if (dest_buf)
   1627     FXSYS_memcpy(dest_buf, scanline, m_pBitmap->GetPitch());
   1628 
   1629   if (dest_alpha_buf) {
   1630     FXSYS_memcpy(dest_alpha_buf, scan_extra_alpha,
   1631                  m_pBitmap->m_pAlphaMask->GetPitch());
   1632   }
   1633 }
   1634 
   1635 bool CFX_BitmapStorer::SetInfo(int width,
   1636                                int height,
   1637                                FXDIB_Format src_format,
   1638                                uint32_t* pSrcPalette) {
   1639   m_pBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
   1640   if (!m_pBitmap->Create(width, height, src_format)) {
   1641     m_pBitmap.reset();
   1642     return false;
   1643   }
   1644   if (pSrcPalette)
   1645     m_pBitmap->SetPalette(pSrcPalette);
   1646   return true;
   1647 }
   1648