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