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