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_ge.h"
      8 #include "../../../include/fxcodec/fx_codec.h"
      9 #include "dib_int.h"
     10 const FX_BYTE g_GammaRamp[256] = {
     11     0,   0,   0,   0,   0,   0,   0,   1,   1,   1,   1,   1,   1,   1,   1,   1,
     12     1,   1,   2,   2,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3,   3,
     13     4,   4,   4,   4,   4,   5,   5,   5,   5,   6,   6,   6,   6,   7,   7,   7,
     14     8,   8,   8,   8,   9,   9,   9,  10,  10,  10,  11,  11,  12,  12,  12,  13,
     15     13,  13,  14,  14,  15,  15,  16,  16,  17,  17,  17,  18,  18,  19,  19,  20,
     16     20,  21,  22,  22,  23,  23,  24,  24,  25,  25,  26,  27,  27,  28,  29,  29,
     17     30,  30,  31,  32,  32,  33,  34,  35,  35,  36,  37,  37,  38,  39,  40,  41,
     18     41,  42,  43,  44,  45,  45,  46,  47,  48,  49,  50,  51,  51,  52,  53,  54,
     19     55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
     20     71,  72,  73,  74,  76,  77,  78,  79,  80,  81,  82,  84,  85,  86,  87,  88,
     21     90,  91,  92,  93,  95,  96,  97,  99, 100, 101, 103, 104, 105, 107, 108, 109,
     22     111, 112, 114, 115, 116, 118, 119, 121, 122, 124, 125, 127, 128, 130, 131, 133,
     23     134, 136, 138, 139, 141, 142, 144, 146, 147, 149, 151, 152, 154, 156, 157, 159,
     24     161, 163, 164, 166, 168, 170, 171, 173, 175, 177, 179, 181, 183, 184, 186, 188,
     25     190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220,
     26     222, 224, 226, 229, 231, 233, 235, 237, 239, 242, 244, 246, 248, 250, 253, 255,
     27 };
     28 const FX_BYTE g_GammaInverse[256] = {
     29     0,  13,  22,  28,  34,  38,  42,  46,  50,  53,  56,  59,  61,  64,  66,  69,
     30     71,  73,  75,  77,  79,  81,  83,  85,  86,  88,  90,  92,  93,  95,  96,  98,
     31     99, 101, 102, 104, 105, 106, 108, 109, 110, 112, 113, 114, 115, 117, 118, 119,
     32     120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
     33     137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, 151,
     34     152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164,
     35     165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 175, 176,
     36     177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184, 185, 185, 186, 187, 187,
     37     188, 189, 189, 190, 190, 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 197,
     38     198, 199, 199, 200, 200, 201, 202, 202, 203, 203, 204, 205, 205, 206, 206, 207,
     39     208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216,
     40     216, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224,
     41     225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
     42     233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240,
     43     241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248,
     44     248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255,
     45 };
     46 const FX_BYTE _color_sqrt[256] = {
     47     0x00, 0x03, 0x07, 0x0B, 0x0F, 0x12, 0x16, 0x19, 0x1D, 0x20, 0x23, 0x26, 0x29, 0x2C, 0x2F, 0x32,
     48     0x35, 0x37, 0x3A, 0x3C, 0x3F, 0x41, 0x43, 0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56,
     49     0x57, 0x59, 0x5B, 0x5C, 0x5E, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D,
     50     0x6E, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E,
     51     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E,
     52     0x8F, 0x90, 0x91, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C,
     53     0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5, 0xA6, 0xA7, 0xA7, 0xA8,
     54     0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE, 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB3, 0xB4,
     55     0xB5, 0xB5, 0xB6, 0xB7, 0xB7, 0xB8, 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBE, 0xBF,
     56     0xC0, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7, 0xC7, 0xC8, 0xC9, 0xC9,
     57     0xCA, 0xCB, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCE, 0xCF, 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD3,
     58     0xD4, 0xD4, 0xD5, 0xD6, 0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD,
     59     0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5, 0xE5, 0xE6,
     60     0xE6, 0xE7, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE,
     61     0xEF, 0xF0, 0xF0, 0xF1, 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7,
     62     0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFF
     63 };
     64 int _BLEND(int blend_mode, int back_color, int src_color)
     65 {
     66     switch (blend_mode) {
     67         case FXDIB_BLEND_NORMAL:
     68             return src_color;
     69         case FXDIB_BLEND_MULTIPLY:
     70             return src_color * back_color / 255;
     71         case FXDIB_BLEND_SCREEN:
     72             return src_color + back_color - src_color * back_color / 255;
     73         case FXDIB_BLEND_OVERLAY:
     74             return _BLEND(FXDIB_BLEND_HARDLIGHT, src_color, back_color);
     75         case FXDIB_BLEND_DARKEN:
     76             return src_color < back_color ? src_color : back_color;
     77         case FXDIB_BLEND_LIGHTEN:
     78             return src_color > back_color ? src_color : back_color;
     79         case FXDIB_BLEND_COLORDODGE: {
     80                 if (src_color == 255) {
     81                     return src_color;
     82                 }
     83                 int result = back_color * 255 / (255 - src_color);
     84                 if (result > 255) {
     85                     return 255;
     86                 }
     87                 return result;
     88             }
     89         case FXDIB_BLEND_COLORBURN: {
     90                 if (src_color == 0) {
     91                     return src_color;
     92                 }
     93                 int result = (255 - back_color) * 255 / src_color;
     94                 if (result > 255) {
     95                     result = 255;
     96                 }
     97                 return 255 - result;
     98             }
     99         case FXDIB_BLEND_HARDLIGHT:
    100             if (src_color < 128) {
    101                 return (src_color * back_color * 2) / 255;
    102             }
    103             return _BLEND(FXDIB_BLEND_SCREEN, back_color, 2 * src_color - 255);
    104         case FXDIB_BLEND_SOFTLIGHT: {
    105                 if (src_color < 128) {
    106                     return back_color - (255 - 2 * src_color) * back_color * (255 - back_color) / 255 / 255;
    107                 }
    108                 return back_color + (2 * src_color - 255) * (_color_sqrt[back_color] - back_color) / 255;
    109             }
    110         case FXDIB_BLEND_DIFFERENCE:
    111             return back_color < src_color ? src_color - back_color : back_color - src_color;
    112         case FXDIB_BLEND_EXCLUSION:
    113             return back_color + src_color - 2 * back_color * src_color / 255;
    114     }
    115     return src_color;
    116 }
    117 struct _RGB {
    118     int red;
    119     int green;
    120     int blue;
    121 };
    122 static inline int _Lum(_RGB color)
    123 {
    124     return (color.red * 30 + color.green * 59 + color.blue * 11) / 100;
    125 }
    126 static _RGB _ClipColor(_RGB color)
    127 {
    128     int l = _Lum(color);
    129     int n = color.red;
    130     if (color.green < n) {
    131         n = color.green;
    132     }
    133     if (color.blue < n) {
    134         n = color.blue;
    135     }
    136     int x = color.red;
    137     if (color.green > x) {
    138         x = color.green;
    139     }
    140     if (color.blue > x) {
    141         x = color.blue;
    142     }
    143     if (n < 0) {
    144         color.red = l + ((color.red - l) * l / (l - n));
    145         color.green = l + ((color.green - l) * l / (l - n));
    146         color.blue = l + ((color.blue - l) * l / (l - n));
    147     }
    148     if (x > 255) {
    149         color.red = l + ((color.red - l) * (255 - l) / (x - l));
    150         color.green = l + ((color.green - l) * (255 - l) / (x - l));
    151         color.blue = l + ((color.blue - l) * (255 - l) / (x - l));
    152     }
    153     return color;
    154 }
    155 static _RGB _SetLum(_RGB color, int l)
    156 {
    157     int d = l - _Lum(color);
    158     color.red += d;
    159     color.green += d;
    160     color.blue += d;
    161     return _ClipColor(color);
    162 }
    163 static int _Sat(_RGB color)
    164 {
    165     int n = color.red;
    166     if (color.green < n) {
    167         n = color.green;
    168     }
    169     if (color.blue < n) {
    170         n = color.blue;
    171     }
    172     int x = color.red;
    173     if (color.green > x) {
    174         x = color.green;
    175     }
    176     if (color.blue > x) {
    177         x = color.blue;
    178     }
    179     return x - n;
    180 }
    181 static _RGB _SetSat(_RGB color, int s)
    182 {
    183     int* max = &color.red;
    184     int* mid = &color.red;
    185     int* min = &color.red;
    186     if (color.green > *max) {
    187         max = &color.green;
    188     }
    189     if (color.blue > *max) {
    190         max = &color.blue;
    191     }
    192     if (color.green < *min) {
    193         min = &color.green;
    194     }
    195     if (color.blue < *min) {
    196         min = &color.blue;
    197     }
    198     if (*max == *min) {
    199         color.red = 0;
    200         color.green = 0;
    201         color.blue = 0;
    202         return color;
    203     }
    204     if (max == &color.red) {
    205         if (min == &color.green) {
    206             mid = &color.blue;
    207         } else {
    208             mid = &color.green;
    209         }
    210     } else if (max == &color.green) {
    211         if (min == &color.red) {
    212             mid = &color.blue;
    213         } else {
    214             mid = &color.red;
    215         }
    216     } else {
    217         if (min == &color.green) {
    218             mid = &color.red;
    219         } else {
    220             mid = &color.green;
    221         }
    222     }
    223     if (*max > *min) {
    224         *mid = (*mid - *min) * s / (*max - *min);
    225         *max = s;
    226         *min = 0;
    227     }
    228     return color;
    229 }
    230 void _RGB_Blend(int blend_mode, FX_LPCBYTE src_scan, FX_BYTE* dest_scan, int results[3])
    231 {
    232     _RGB src, back, result;
    233     src.red = src_scan[2];
    234     src.green = src_scan[1];
    235     src.blue = src_scan[0];
    236     back.red = dest_scan[2];
    237     back.green = dest_scan[1];
    238     back.blue = dest_scan[0];
    239     switch (blend_mode) {
    240         case FXDIB_BLEND_HUE:
    241             result = _SetLum(_SetSat(src, _Sat(back)), _Lum(back));
    242             break;
    243         case FXDIB_BLEND_SATURATION:
    244             result = _SetLum(_SetSat(back, _Sat(src)), _Lum(back));
    245             break;
    246         case FXDIB_BLEND_COLOR:
    247             result = _SetLum(src, _Lum(back));
    248             break;
    249         case FXDIB_BLEND_LUMINOSITY:
    250             result = _SetLum(back, _Lum(src));
    251             break;
    252     }
    253     results[0] = result.blue;
    254     results[1] = result.green;
    255     results[2] = result.red;
    256 }
    257 inline void _CompositeRow_Argb2Mask(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int pixel_count, FX_LPCBYTE clip_scan)
    258 {
    259     src_scan += 3;
    260     for (int col = 0; col < pixel_count; col ++) {
    261         int src_alpha = *src_scan;
    262         if (clip_scan) {
    263             src_alpha = clip_scan[col] * src_alpha / 255;
    264         }
    265         FX_BYTE back_alpha = *dest_scan;
    266         if (!back_alpha) {
    267             *dest_scan = src_alpha;
    268         } else if (src_alpha) {
    269             *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    270         }
    271         dest_scan ++;
    272         src_scan += 4;
    273     }
    274 }
    275 void _CompositeRow_Rgba2Mask(FX_LPBYTE dest_scan, FX_LPCBYTE src_alpha_scan, int pixel_count, FX_LPCBYTE clip_scan)
    276 {
    277     for (int col = 0; col < pixel_count; col ++) {
    278         int src_alpha = *src_alpha_scan++;
    279         if (clip_scan) {
    280             src_alpha = clip_scan[col] * src_alpha / 255;
    281         }
    282         FX_BYTE back_alpha = *dest_scan;
    283         if (!back_alpha) {
    284             *dest_scan = src_alpha;
    285         } else if (src_alpha) {
    286             *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    287         }
    288         dest_scan ++;
    289     }
    290 }
    291 void _CompositeRow_Rgb2Mask(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, FX_LPCBYTE clip_scan)
    292 {
    293     if (clip_scan) {
    294         for (int i = 0; i < width; i ++) {
    295             *dest_scan = FXDIB_ALPHA_UNION(*dest_scan, *clip_scan);
    296             dest_scan ++;
    297             clip_scan ++;
    298         }
    299     } else {
    300         FXSYS_memset8(dest_scan, 0xff, width);
    301     }
    302 }
    303 void _CompositeRow_Argb2Graya(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int pixel_count, int blend_type, FX_LPCBYTE clip_scan,
    304                               FX_LPCBYTE src_alpha_scan, FX_LPBYTE dst_alpha_scan, void* pIccTransform)
    305 {
    306     ICodec_IccModule* pIccModule = NULL;
    307     if (pIccTransform) {
    308         pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
    309     }
    310     if (blend_type) {
    311         FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    312         int blended_color;
    313         if (src_alpha_scan) {
    314             for (int col = 0; col < pixel_count; col ++) {
    315                 FX_BYTE back_alpha = *dst_alpha_scan;
    316                 if (back_alpha == 0) {
    317                     int src_alpha = *src_alpha_scan++;
    318                     if (clip_scan) {
    319                         src_alpha = clip_scan[col] * src_alpha / 255;
    320                     }
    321                     if (src_alpha) {
    322                         if (pIccTransform) {
    323                             pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
    324                         } else {
    325                             *dest_scan =  FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    326                         }
    327                         *dst_alpha_scan = src_alpha;
    328                     }
    329                     dest_scan ++;
    330                     dst_alpha_scan ++;
    331                     src_scan += 3;
    332                     continue;
    333                 }
    334                 FX_BYTE src_alpha = *src_alpha_scan++;
    335                 if (clip_scan) {
    336                     src_alpha = clip_scan[col] * src_alpha / 255;
    337                 }
    338                 if (src_alpha == 0) {
    339                     dest_scan ++;
    340                     dst_alpha_scan ++;
    341                     src_scan += 3;
    342                     continue;
    343                 }
    344                 *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha);
    345                 int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan);
    346                 FX_BYTE gray;
    347                 if (pIccTransform) {
    348                     pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    349                 } else {
    350                     gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    351                 }
    352                 if (bNonseparableBlend) {
    353                     blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    354                 }
    355                 gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
    356                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
    357                 dest_scan ++;
    358                 dst_alpha_scan++;
    359                 src_scan += 3;
    360             }
    361         } else
    362             for (int col = 0; col < pixel_count; col ++) {
    363                 FX_BYTE back_alpha = *dst_alpha_scan;
    364                 if (back_alpha == 0) {
    365                     int src_alpha = src_scan[3];
    366                     if (clip_scan) {
    367                         src_alpha = clip_scan[col] * src_alpha / 255;
    368                     }
    369                     if (src_alpha) {
    370                         if (pIccTransform) {
    371                             pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
    372                         } else {
    373                             *dest_scan =  FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    374                         }
    375                         *dst_alpha_scan = src_alpha;
    376                     }
    377                     dest_scan ++;
    378                     dst_alpha_scan ++;
    379                     src_scan += 4;
    380                     continue;
    381                 }
    382                 FX_BYTE src_alpha = src_scan[3];
    383                 if (clip_scan) {
    384                     src_alpha = clip_scan[col] * src_alpha / 255;
    385                 }
    386                 if (src_alpha == 0) {
    387                     dest_scan ++;
    388                     dst_alpha_scan ++;
    389                     src_scan += 4;
    390                     continue;
    391                 }
    392                 *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha);
    393                 int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan);
    394                 FX_BYTE gray;
    395                 if (pIccTransform) {
    396                     pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    397                 } else {
    398                     gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    399                 }
    400                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
    401                 dest_scan ++;
    402                 dst_alpha_scan++;
    403                 src_scan += 4;
    404             }
    405         return;
    406     }
    407     if (src_alpha_scan) {
    408         for (int col = 0; col < pixel_count; col ++) {
    409             FX_BYTE back_alpha = *dst_alpha_scan;
    410             if (back_alpha == 0) {
    411                 int src_alpha = *src_alpha_scan++;
    412                 if (clip_scan) {
    413                     src_alpha = clip_scan[col] * src_alpha / 255;
    414                 }
    415                 if (src_alpha) {
    416                     if (pIccTransform) {
    417                         pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
    418                     } else {
    419                         *dest_scan =  FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    420                     }
    421                     *dst_alpha_scan = src_alpha;
    422                 }
    423                 dest_scan ++;
    424                 dst_alpha_scan ++;
    425                 src_scan += 3;
    426                 continue;
    427             }
    428             FX_BYTE src_alpha = *src_alpha_scan++;
    429             if (clip_scan) {
    430                 src_alpha = clip_scan[col] * src_alpha / 255;
    431             }
    432             if (src_alpha == 0) {
    433                 dest_scan ++;
    434                 dst_alpha_scan ++;
    435                 src_scan += 3;
    436                 continue;
    437             }
    438             *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha);
    439             int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan);
    440             FX_BYTE gray;
    441             if (pIccTransform) {
    442                 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    443             } else {
    444                 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    445             }
    446             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
    447             dest_scan ++;
    448             dst_alpha_scan++;
    449             src_scan += 3;
    450         }
    451     } else
    452         for (int col = 0; col < pixel_count; col ++) {
    453             FX_BYTE back_alpha = *dst_alpha_scan;
    454             if (back_alpha == 0) {
    455                 int src_alpha = src_scan[3];
    456                 if (clip_scan) {
    457                     src_alpha = clip_scan[col] * src_alpha / 255;
    458                 }
    459                 if (src_alpha) {
    460                     if (pIccTransform) {
    461                         pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
    462                     } else {
    463                         *dest_scan =  FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    464                     }
    465                     *dst_alpha_scan = src_alpha;
    466                 }
    467                 dest_scan ++;
    468                 dst_alpha_scan ++;
    469                 src_scan += 4;
    470                 continue;
    471             }
    472             FX_BYTE src_alpha = src_scan[3];
    473             if (clip_scan) {
    474                 src_alpha = clip_scan[col] * src_alpha / 255;
    475             }
    476             if (src_alpha == 0) {
    477                 dest_scan ++;
    478                 dst_alpha_scan ++;
    479                 src_scan += 4;
    480                 continue;
    481             }
    482             *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha);
    483             int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan);
    484             FX_BYTE gray;
    485             if (pIccTransform) {
    486                 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    487             } else {
    488                 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    489             }
    490             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
    491             dest_scan ++;
    492             dst_alpha_scan++;
    493             src_scan += 4;
    494         }
    495 }
    496 inline void _CompositeRow_Argb2Gray(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int pixel_count,
    497                                     int blend_type, FX_LPCBYTE clip_scan,
    498                                     FX_LPCBYTE src_alpha_scan, void* pIccTransform)
    499 {
    500     ICodec_IccModule* pIccModule = NULL;
    501     FX_BYTE gray;
    502     if (pIccTransform) {
    503         pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
    504     }
    505     if (blend_type) {
    506         FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    507         int blended_color;
    508         if (src_alpha_scan) {
    509             for (int col = 0; col < pixel_count; col ++) {
    510                 int src_alpha = *src_alpha_scan++;
    511                 if (clip_scan) {
    512                     src_alpha = clip_scan[col] * src_alpha / 255;
    513                 }
    514                 if (src_alpha) {
    515                     if (pIccTransform) {
    516                         pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    517                     } else {
    518                         gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    519                     }
    520                     if (bNonseparableBlend) {
    521                         blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    522                     }
    523                     gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
    524                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
    525                 }
    526                 dest_scan ++;
    527                 src_scan += 3;
    528             }
    529         } else
    530             for (int col = 0; col < pixel_count; col ++) {
    531                 int src_alpha = src_scan[3];
    532                 if (clip_scan) {
    533                     src_alpha = clip_scan[col] * src_alpha / 255;
    534                 }
    535                 if (src_alpha) {
    536                     if (pIccTransform) {
    537                         pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    538                     } else {
    539                         gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    540                     }
    541                     if (bNonseparableBlend) {
    542                         blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    543                     }
    544                     gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
    545                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
    546                 }
    547                 dest_scan ++;
    548                 src_scan += 4;
    549             }
    550         return;
    551     }
    552     if (src_alpha_scan) {
    553         for (int col = 0; col < pixel_count; col ++) {
    554             int src_alpha = *src_alpha_scan++;
    555             if (clip_scan) {
    556                 src_alpha = clip_scan[col] * src_alpha / 255;
    557             }
    558             if (src_alpha) {
    559                 if (pIccTransform) {
    560                     pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    561                 } else {
    562                     gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    563                 }
    564                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
    565             }
    566             dest_scan ++;
    567             src_scan += 3;
    568         }
    569     } else
    570         for (int col = 0; col < pixel_count; col ++) {
    571             int src_alpha = src_scan[3];
    572             if (clip_scan) {
    573                 src_alpha = clip_scan[col] * src_alpha / 255;
    574             }
    575             if (src_alpha) {
    576                 if (pIccTransform) {
    577                     pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    578                 } else {
    579                     gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    580                 }
    581                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
    582             }
    583             dest_scan ++;
    584             src_scan += 4;
    585         }
    586 }
    587 inline void _CompositeRow_Rgb2Gray(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_Bpp, int pixel_count,
    588                                    int blend_type, FX_LPCBYTE clip_scan,
    589                                    void* pIccTransform)
    590 {
    591     ICodec_IccModule* pIccModule = NULL;
    592     FX_BYTE gray;
    593     if (pIccTransform) {
    594         pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
    595     }
    596     if (blend_type) {
    597         FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    598         int blended_color;
    599         for (int col = 0; col < pixel_count; col ++) {
    600             if (pIccTransform) {
    601                 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    602             } else {
    603                 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    604             }
    605             if (bNonseparableBlend) {
    606                 blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    607             }
    608             gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
    609             if (clip_scan && clip_scan[col] < 255) {
    610                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
    611             } else {
    612                 *dest_scan = gray;
    613             }
    614             dest_scan ++;
    615             src_scan += src_Bpp;
    616         }
    617         return;
    618     }
    619     for (int col = 0; col < pixel_count; col ++) {
    620         if (pIccTransform) {
    621             pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    622         } else {
    623             gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    624         }
    625         if (clip_scan && clip_scan[col] < 255) {
    626             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
    627         } else {
    628             *dest_scan = gray;
    629         }
    630         dest_scan ++;
    631         src_scan += src_Bpp;
    632     }
    633 }
    634 void _CompositeRow_Rgb2Graya(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_Bpp, int pixel_count,
    635                              int blend_type, FX_LPCBYTE clip_scan,
    636                              FX_LPBYTE dest_alpha_scan, void* pIccTransform)
    637 {
    638     ICodec_IccModule* pIccModule = NULL;
    639     if (pIccTransform) {
    640         pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
    641     }
    642     if (blend_type) {
    643         int blended_color;
    644         FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    645         for (int col = 0; col < pixel_count; col ++) {
    646             int back_alpha = *dest_alpha_scan;
    647             if (back_alpha == 0) {
    648                 if (pIccTransform) {
    649                     pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
    650                 } else {
    651                     *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    652                 }
    653                 dest_scan ++;
    654                 dest_alpha_scan++;
    655                 src_scan += src_Bpp;
    656                 continue;
    657             }
    658             int src_alpha = 255;
    659             if (clip_scan) {
    660                 src_alpha = clip_scan[col];
    661             }
    662             if (src_alpha == 0) {
    663                 dest_scan ++;
    664                 dest_alpha_scan ++;
    665                 src_scan += src_Bpp;
    666                 continue;
    667             }
    668             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    669             *dest_alpha_scan++ = dest_alpha;
    670             int alpha_ratio = src_alpha * 255 / dest_alpha;
    671             FX_BYTE gray;
    672             if (pIccTransform) {
    673                 pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    674             } else {
    675                 gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    676             }
    677             if (bNonseparableBlend) {
    678                 blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    679             }
    680             gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
    681             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
    682             dest_scan ++;
    683             src_scan += src_Bpp;
    684         }
    685         return;
    686     }
    687     for (int col = 0; col < pixel_count; col ++) {
    688         int src_alpha = 255;
    689         if (clip_scan) {
    690             src_alpha = clip_scan[col];
    691         }
    692         if (src_alpha == 255) {
    693             if (pIccTransform) {
    694                 pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
    695             } else {
    696                 *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    697             }
    698             dest_scan ++;
    699             *dest_alpha_scan++ = 255;
    700             src_scan += src_Bpp;
    701             continue;
    702         }
    703         if (src_alpha == 0) {
    704             dest_scan ++;
    705             dest_alpha_scan ++;
    706             src_scan += src_Bpp;
    707             continue;
    708         }
    709         int back_alpha = *dest_alpha_scan;
    710         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    711         *dest_alpha_scan++ = dest_alpha;
    712         int alpha_ratio = src_alpha * 255 / dest_alpha;
    713         FX_BYTE gray;
    714         if (pIccTransform) {
    715             pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
    716         } else {
    717             gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    718         }
    719         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
    720         dest_scan ++;
    721         src_scan += src_Bpp;
    722     }
    723 }
    724 void _CompositeRow_Argb2Argb(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int pixel_count, int blend_type, FX_LPCBYTE clip_scan,
    725                              FX_LPBYTE dest_alpha_scan, FX_LPCBYTE src_alpha_scan)
    726 {
    727     int blended_colors[3];
    728     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    729     if (dest_alpha_scan == NULL) {
    730         if (src_alpha_scan == NULL) {
    731             FX_BYTE back_alpha = 0;
    732             for (int col = 0; col < pixel_count; col ++) {
    733                 back_alpha = dest_scan[3];
    734                 if (back_alpha == 0) {
    735                     if (clip_scan) {
    736                         int src_alpha = clip_scan[col] * src_scan[3] / 255;
    737                         FXARGB_SETDIB(dest_scan, (FXARGB_GETDIB(src_scan) & 0xffffff) | (src_alpha << 24));
    738                     } else {
    739                         FXARGB_COPY(dest_scan, src_scan);
    740                     }
    741                     dest_scan += 4;
    742                     src_scan += 4;
    743                     continue;
    744                 }
    745                 FX_BYTE src_alpha;
    746                 if (clip_scan == NULL) {
    747                     src_alpha = src_scan[3];
    748                 } else {
    749                     src_alpha = clip_scan[col] * src_scan[3] / 255;
    750                 }
    751                 if (src_alpha == 0) {
    752                     dest_scan += 4;
    753                     src_scan += 4;
    754                     continue;
    755                 }
    756                 FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    757                 dest_scan[3] = dest_alpha;
    758                 int alpha_ratio = src_alpha * 255 / dest_alpha;
    759                 if (bNonseparableBlend) {
    760                     _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    761                 }
    762                 for (int color = 0; color < 3; color ++) {
    763                     if (blend_type) {
    764                         int blended = bNonseparableBlend ? blended_colors[color] :
    765                                       _BLEND(blend_type, *dest_scan, *src_scan);
    766                         blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
    767                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
    768                     } else {
    769                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
    770                     }
    771                     dest_scan ++;
    772                     src_scan ++;
    773                 }
    774                 dest_scan ++;
    775                 src_scan ++;
    776             }
    777         } else {
    778             for (int col = 0; col < pixel_count; col ++) {
    779                 FX_BYTE back_alpha = dest_scan[3];
    780                 if (back_alpha == 0) {
    781                     if (clip_scan) {
    782                         int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255;
    783                         FXARGB_SETDIB(dest_scan, FXARGB_MAKE((src_alpha << 24), src_scan[2], src_scan[1], *src_scan));
    784                     } else {
    785                         FXARGB_SETDIB(dest_scan, FXARGB_MAKE((*src_alpha_scan << 24), src_scan[2], src_scan[1], *src_scan));
    786                     }
    787                     dest_scan += 4;
    788                     src_scan += 3;
    789                     src_alpha_scan ++;
    790                     continue;
    791                 }
    792                 FX_BYTE src_alpha;
    793                 if (clip_scan == NULL) {
    794                     src_alpha = *src_alpha_scan ++;
    795                 } else {
    796                     src_alpha = clip_scan[col] * (*src_alpha_scan ++) / 255;
    797                 }
    798                 if (src_alpha == 0) {
    799                     dest_scan += 4;
    800                     src_scan += 3;
    801                     continue;
    802                 }
    803                 FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    804                 dest_scan[3] = dest_alpha;
    805                 int alpha_ratio = src_alpha * 255 / dest_alpha;
    806                 if (bNonseparableBlend) {
    807                     _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    808                 }
    809                 for (int color = 0; color < 3; color ++) {
    810                     if (blend_type) {
    811                         int blended = bNonseparableBlend ? blended_colors[color] :
    812                                       _BLEND(blend_type, *dest_scan, *src_scan);
    813                         blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
    814                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
    815                     } else {
    816                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
    817                     }
    818                     dest_scan ++;
    819                     src_scan ++;
    820                 }
    821                 dest_scan ++;
    822             }
    823         }
    824     } else {
    825         if (src_alpha_scan) {
    826             for (int col = 0; col < pixel_count; col ++) {
    827                 FX_BYTE back_alpha = *dest_alpha_scan;
    828                 if (back_alpha == 0) {
    829                     if (clip_scan) {
    830                         int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255;
    831                         *dest_alpha_scan = src_alpha;
    832                         *dest_scan++ = *src_scan++;
    833                         *dest_scan++ = *src_scan++;
    834                         *dest_scan++ = *src_scan++;
    835                     } else {
    836                         *dest_alpha_scan = *src_alpha_scan;
    837                         *dest_scan++ = *src_scan++;
    838                         *dest_scan++ = *src_scan++;
    839                         *dest_scan++ = *src_scan++;
    840                     }
    841                     dest_alpha_scan ++;
    842                     src_alpha_scan ++;
    843                     continue;
    844                 }
    845                 FX_BYTE src_alpha;
    846                 if (clip_scan == NULL) {
    847                     src_alpha = *src_alpha_scan ++;
    848                 } else {
    849                     src_alpha = clip_scan[col] * (*src_alpha_scan ++) / 255;
    850                 }
    851                 if (src_alpha == 0) {
    852                     dest_scan += 3;
    853                     src_scan += 3;
    854                     dest_alpha_scan ++;
    855                     continue;
    856                 }
    857                 FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    858                 *dest_alpha_scan ++ = dest_alpha;
    859                 int alpha_ratio = src_alpha * 255 / dest_alpha;
    860                 if (bNonseparableBlend) {
    861                     _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    862                 }
    863                 for (int color = 0; color < 3; color ++) {
    864                     if (blend_type) {
    865                         int blended = bNonseparableBlend ? blended_colors[color] :
    866                                       _BLEND(blend_type, *dest_scan, *src_scan);
    867                         blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
    868                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
    869                     } else {
    870                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
    871                     }
    872                     dest_scan ++;
    873                     src_scan ++;
    874                 }
    875             }
    876         } else {
    877             for (int col = 0; col < pixel_count; col ++) {
    878                 FX_BYTE back_alpha = *dest_alpha_scan;
    879                 if (back_alpha == 0) {
    880                     if (clip_scan) {
    881                         int src_alpha = clip_scan[col] * src_scan[3] / 255;
    882                         *dest_alpha_scan = src_alpha;
    883                         *dest_scan++ = *src_scan++;
    884                         *dest_scan++ = *src_scan++;
    885                         *dest_scan++ = *src_scan++;
    886                     } else {
    887                         *dest_alpha_scan = src_scan[3];
    888                         *dest_scan++ = *src_scan++;
    889                         *dest_scan++ = *src_scan++;
    890                         *dest_scan++ = *src_scan++;
    891                     }
    892                     dest_alpha_scan ++;
    893                     src_scan ++;
    894                     continue;
    895                 }
    896                 FX_BYTE src_alpha;
    897                 if (clip_scan == NULL) {
    898                     src_alpha = src_scan[3];
    899                 } else {
    900                     src_alpha = clip_scan[col] * src_scan[3] / 255;
    901                 }
    902                 if (src_alpha == 0) {
    903                     dest_scan += 3;
    904                     src_scan += 4;
    905                     dest_alpha_scan ++;
    906                     continue;
    907                 }
    908                 FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    909                 *dest_alpha_scan++ = dest_alpha;
    910                 int alpha_ratio = src_alpha * 255 / dest_alpha;
    911                 if (bNonseparableBlend) {
    912                     _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    913                 }
    914                 for (int color = 0; color < 3; color ++) {
    915                     if (blend_type) {
    916                         int blended = bNonseparableBlend ? blended_colors[color] :
    917                                       _BLEND(blend_type, *dest_scan, *src_scan);
    918                         blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
    919                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
    920                     } else {
    921                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
    922                     }
    923                     dest_scan ++;
    924                     src_scan ++;
    925                 }
    926                 src_scan ++;
    927             }
    928         }
    929     }
    930 }
    931 void _CompositeRow_Rgb2Argb_Blend_NoClip(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int src_Bpp,
    932         FX_LPBYTE dest_alpha_scan)
    933 {
    934     int blended_colors[3];
    935     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    936     int src_gap = src_Bpp - 3;
    937     if (dest_alpha_scan == NULL) {
    938         for (int col = 0; col < width; col ++) {
    939             FX_BYTE back_alpha = dest_scan[3];
    940             if (back_alpha == 0) {
    941                 if (src_Bpp == 4) {
    942                     FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
    943                 } else {
    944                     FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
    945                 }
    946                 dest_scan += 4;
    947                 src_scan += src_Bpp;
    948                 continue;
    949             }
    950             dest_scan[3] = 0xff;
    951             if (bNonseparableBlend) {
    952                 _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    953             }
    954             for (int color = 0; color < 3; color ++) {
    955                 int src_color = *src_scan;
    956                 int blended = bNonseparableBlend ? blended_colors[color] :
    957                               _BLEND(blend_type, *dest_scan, src_color);
    958                 *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
    959                 dest_scan ++;
    960                 src_scan ++;
    961             }
    962             dest_scan ++;
    963             src_scan += src_gap;
    964         }
    965     } else {
    966         for (int col = 0; col < width; col ++) {
    967             FX_BYTE back_alpha = *dest_alpha_scan;
    968             if (back_alpha == 0) {
    969                 *dest_scan++ = *src_scan++;
    970                 *dest_scan++ = *src_scan++;
    971                 *dest_scan++ = *src_scan++;
    972                 *dest_alpha_scan++ = 0xff;
    973                 src_scan += src_gap;
    974                 continue;
    975             }
    976             *dest_alpha_scan++ = 0xff;
    977             if (bNonseparableBlend) {
    978                 _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    979             }
    980             for (int color = 0; color < 3; color ++) {
    981                 int src_color = *src_scan;
    982                 int blended = bNonseparableBlend ? blended_colors[color] :
    983                               _BLEND(blend_type, *dest_scan, src_color);
    984                 *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
    985                 dest_scan ++;
    986                 src_scan ++;
    987             }
    988             src_scan += src_gap;
    989         }
    990     }
    991 }
    992 inline void _CompositeRow_Rgb2Argb_Blend_Clip(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int src_Bpp, FX_LPCBYTE clip_scan,
    993         FX_LPBYTE dest_alpha_scan)
    994 {
    995     int blended_colors[3];
    996     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    997     int src_gap = src_Bpp - 3;
    998     if (dest_alpha_scan == NULL) {
    999         for (int col = 0; col < width; col ++) {
   1000             int src_alpha = *clip_scan ++;
   1001             FX_BYTE back_alpha = dest_scan[3];
   1002             if (back_alpha == 0) {
   1003                 *dest_scan++ = *src_scan++;
   1004                 *dest_scan++ = *src_scan++;
   1005                 *dest_scan++ = *src_scan++;
   1006                 src_scan += src_gap;
   1007                 dest_scan ++;
   1008                 continue;
   1009             }
   1010             if (src_alpha == 0) {
   1011                 dest_scan += 4;
   1012                 src_scan += src_Bpp;
   1013                 continue;
   1014             }
   1015             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1016             dest_scan[3] = dest_alpha;
   1017             int alpha_ratio = src_alpha * 255 / dest_alpha;
   1018             if (bNonseparableBlend) {
   1019                 _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   1020             }
   1021             for (int color = 0; color < 3; color ++) {
   1022                 int src_color = *src_scan;
   1023                 int blended = bNonseparableBlend ? blended_colors[color] :
   1024                               _BLEND(blend_type, *dest_scan, src_color);
   1025                 blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
   1026                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1027                 dest_scan ++;
   1028                 src_scan ++;
   1029             }
   1030             dest_scan ++;
   1031             src_scan += src_gap;
   1032         }
   1033     } else {
   1034         for (int col = 0; col < width; col ++) {
   1035             int src_alpha = *clip_scan ++;
   1036             FX_BYTE back_alpha = *dest_alpha_scan;
   1037             if (back_alpha == 0) {
   1038                 *dest_scan++ = *src_scan++;
   1039                 *dest_scan++ = *src_scan++;
   1040                 *dest_scan++ = *src_scan++;
   1041                 src_scan += src_gap;
   1042                 dest_alpha_scan++;
   1043                 continue;
   1044             }
   1045             if (src_alpha == 0) {
   1046                 dest_scan += 3;
   1047                 dest_alpha_scan++;
   1048                 src_scan += src_Bpp;
   1049                 continue;
   1050             }
   1051             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1052             *dest_alpha_scan++ = dest_alpha;
   1053             int alpha_ratio = src_alpha * 255 / dest_alpha;
   1054             if (bNonseparableBlend) {
   1055                 _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   1056             }
   1057             for (int color = 0; color < 3; color ++) {
   1058                 int src_color = *src_scan;
   1059                 int blended = bNonseparableBlend ? blended_colors[color] :
   1060                               _BLEND(blend_type, *dest_scan, src_color);
   1061                 blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
   1062                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1063                 dest_scan ++;
   1064                 src_scan ++;
   1065             }
   1066             src_scan += src_gap;
   1067         }
   1068     }
   1069 }
   1070 inline void _CompositeRow_Rgb2Argb_NoBlend_Clip(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int src_Bpp, FX_LPCBYTE clip_scan,
   1071         FX_LPBYTE dest_alpha_scan)
   1072 {
   1073     int src_gap = src_Bpp - 3;
   1074     if (dest_alpha_scan == NULL) {
   1075         for (int col = 0; col < width; col ++) {
   1076             int src_alpha = clip_scan[col];
   1077             if (src_alpha == 255) {
   1078                 *dest_scan++ = *src_scan++;
   1079                 *dest_scan++ = *src_scan++;
   1080                 *dest_scan++ = *src_scan++;
   1081                 *dest_scan++ = 255;
   1082                 src_scan += src_gap;
   1083                 continue;
   1084             }
   1085             if (src_alpha == 0) {
   1086                 dest_scan += 4;
   1087                 src_scan += src_Bpp;
   1088                 continue;
   1089             }
   1090             int back_alpha = dest_scan[3];
   1091             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1092             dest_scan[3] = dest_alpha;
   1093             int alpha_ratio = src_alpha * 255 / dest_alpha;
   1094             for (int color = 0; color < 3; color ++) {
   1095                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
   1096                 dest_scan ++;
   1097                 src_scan ++;
   1098             }
   1099             dest_scan ++;
   1100             src_scan += src_gap;
   1101         }
   1102     } else {
   1103         for (int col = 0; col < width; col ++) {
   1104             int src_alpha = clip_scan[col];
   1105             if (src_alpha == 255) {
   1106                 *dest_scan++ = *src_scan++;
   1107                 *dest_scan++ = *src_scan++;
   1108                 *dest_scan++ = *src_scan++;
   1109                 *dest_alpha_scan++ = 255;
   1110                 src_scan += src_gap;
   1111                 continue;
   1112             }
   1113             if (src_alpha == 0) {
   1114                 dest_scan += 3;
   1115                 dest_alpha_scan ++;
   1116                 src_scan += src_Bpp;
   1117                 continue;
   1118             }
   1119             int back_alpha = *dest_alpha_scan;
   1120             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1121             *dest_alpha_scan ++ = dest_alpha;
   1122             int alpha_ratio = src_alpha * 255 / dest_alpha;
   1123             for (int color = 0; color < 3; color ++) {
   1124                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
   1125                 dest_scan ++;
   1126                 src_scan ++;
   1127             }
   1128             src_scan += src_gap;
   1129         }
   1130     }
   1131 }
   1132 inline void _CompositeRow_Rgb2Argb_NoBlend_NoClip(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int src_Bpp,
   1133         FX_LPBYTE dest_alpha_scan)
   1134 {
   1135     if (dest_alpha_scan == NULL) {
   1136         for (int col = 0; col < width; col ++) {
   1137             if (src_Bpp == 4) {
   1138                 FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
   1139             } else {
   1140                 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
   1141             }
   1142             dest_scan += 4;
   1143             src_scan += src_Bpp;
   1144         }
   1145     } else {
   1146         int src_gap = src_Bpp - 3;
   1147         for (int col = 0; col < width; col ++) {
   1148             *dest_scan++ = *src_scan++;
   1149             *dest_scan++ = *src_scan++;
   1150             *dest_scan++ = *src_scan++;
   1151             *dest_alpha_scan++ = 0xff;
   1152             src_scan += src_gap;
   1153         }
   1154     }
   1155 }
   1156 inline void _CompositeRow_Argb2Rgb_Blend(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int dest_Bpp, FX_LPCBYTE clip_scan,
   1157         FX_LPCBYTE src_alpha_scan)
   1158 {
   1159     int blended_colors[3];
   1160     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1161     int dest_gap = dest_Bpp - 3;
   1162     if (src_alpha_scan == NULL) {
   1163         for (int col = 0; col < width; col ++) {
   1164             FX_BYTE src_alpha;
   1165             if (clip_scan) {
   1166                 src_alpha = src_scan[3] * (*clip_scan++) / 255;
   1167             } else {
   1168                 src_alpha = src_scan[3];
   1169             }
   1170             if (src_alpha == 0) {
   1171                 dest_scan += dest_Bpp;
   1172                 src_scan += 4;
   1173                 continue;
   1174             }
   1175             if (bNonseparableBlend) {
   1176                 _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   1177             }
   1178             for (int color = 0; color < 3; color ++) {
   1179                 int back_color = *dest_scan;
   1180                 int blended = bNonseparableBlend ? blended_colors[color] :
   1181                               _BLEND(blend_type, back_color, *src_scan);
   1182                 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
   1183                 dest_scan ++;
   1184                 src_scan ++;
   1185             }
   1186             dest_scan += dest_gap;
   1187             src_scan ++;
   1188         }
   1189     } else {
   1190         for (int col = 0; col < width; col ++) {
   1191             FX_BYTE src_alpha;
   1192             if (clip_scan) {
   1193                 src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255;
   1194             } else {
   1195                 src_alpha = *src_alpha_scan++;
   1196             }
   1197             if (src_alpha == 0) {
   1198                 dest_scan += dest_Bpp;
   1199                 src_scan += 3;
   1200                 continue;
   1201             }
   1202             if (bNonseparableBlend) {
   1203                 _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   1204             }
   1205             for (int color = 0; color < 3; color ++) {
   1206                 int back_color = *dest_scan;
   1207                 int blended = bNonseparableBlend ? blended_colors[color] :
   1208                               _BLEND(blend_type, back_color, *src_scan);
   1209                 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
   1210                 dest_scan ++;
   1211                 src_scan ++;
   1212             }
   1213             dest_scan += dest_gap;
   1214         }
   1215     }
   1216 }
   1217 inline void _CompositeRow_Argb2Rgb_NoBlend(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, FX_LPCBYTE clip_scan,
   1218         FX_LPCBYTE src_alpha_scan)
   1219 {
   1220     int dest_gap = dest_Bpp - 3;
   1221     if (src_alpha_scan == NULL) {
   1222         for (int col = 0; col < width; col ++) {
   1223             FX_BYTE src_alpha;
   1224             if (clip_scan) {
   1225                 src_alpha = src_scan[3] * (*clip_scan++) / 255;
   1226             } else {
   1227                 src_alpha = src_scan[3];
   1228             }
   1229             if (src_alpha == 255) {
   1230                 *dest_scan++ = *src_scan++;
   1231                 *dest_scan++ = *src_scan++;
   1232                 *dest_scan++ = *src_scan++;
   1233                 dest_scan += dest_gap;
   1234                 src_scan ++;
   1235                 continue;
   1236             }
   1237             if (src_alpha == 0) {
   1238                 dest_scan += dest_Bpp;
   1239                 src_scan += 4;
   1240                 continue;
   1241             }
   1242             for (int color = 0; color < 3; color ++) {
   1243                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
   1244                 dest_scan ++;
   1245                 src_scan ++;
   1246             }
   1247             dest_scan += dest_gap;
   1248             src_scan ++;
   1249         }
   1250     } else {
   1251         for (int col = 0; col < width; col ++) {
   1252             FX_BYTE src_alpha;
   1253             if (clip_scan) {
   1254                 src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255;
   1255             } else {
   1256                 src_alpha = *src_alpha_scan++;
   1257             }
   1258             if (src_alpha == 255) {
   1259                 *dest_scan++ = *src_scan++;
   1260                 *dest_scan++ = *src_scan++;
   1261                 *dest_scan++ = *src_scan++;
   1262                 dest_scan += dest_gap;
   1263                 continue;
   1264             }
   1265             if (src_alpha == 0) {
   1266                 dest_scan += dest_Bpp;
   1267                 src_scan += 3;
   1268                 continue;
   1269             }
   1270             for (int color = 0; color < 3; color ++) {
   1271                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
   1272                 dest_scan ++;
   1273                 src_scan ++;
   1274             }
   1275             dest_scan += dest_gap;
   1276         }
   1277     }
   1278 }
   1279 inline void _CompositeRow_Rgb2Rgb_Blend_NoClip(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int dest_Bpp, int src_Bpp)
   1280 {
   1281     int blended_colors[3];
   1282     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1283     int dest_gap = dest_Bpp - 3;
   1284     int src_gap = src_Bpp - 3;
   1285     for (int col = 0; col < width; col ++) {
   1286         if (bNonseparableBlend) {
   1287             _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   1288         }
   1289         for (int color = 0; color < 3; color ++) {
   1290             int back_color = *dest_scan;
   1291             int src_color = *src_scan;
   1292             int blended = bNonseparableBlend ? blended_colors[color] :
   1293                           _BLEND(blend_type, back_color, src_color);
   1294             *dest_scan = blended;
   1295             dest_scan ++;
   1296             src_scan ++;
   1297         }
   1298         dest_scan += dest_gap;
   1299         src_scan += src_gap;
   1300     }
   1301 }
   1302 inline void _CompositeRow_Rgb2Rgb_Blend_Clip(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int dest_Bpp, int src_Bpp, FX_LPCBYTE clip_scan)
   1303 {
   1304     int blended_colors[3];
   1305     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1306     int dest_gap = dest_Bpp - 3;
   1307     int src_gap = src_Bpp - 3;
   1308     for (int col = 0; col < width; col ++) {
   1309         FX_BYTE src_alpha = *clip_scan ++;
   1310         if (src_alpha == 0) {
   1311             dest_scan += dest_Bpp;
   1312             src_scan += src_Bpp;
   1313             continue;
   1314         }
   1315         if (bNonseparableBlend) {
   1316             _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   1317         }
   1318         for (int color = 0; color < 3; color ++) {
   1319             int src_color = *src_scan;
   1320             int back_color = *dest_scan;
   1321             int blended = bNonseparableBlend ? blended_colors[color] :
   1322                           _BLEND(blend_type, back_color, src_color);
   1323             *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
   1324             dest_scan ++;
   1325             src_scan ++;
   1326         }
   1327         dest_scan += dest_gap;
   1328         src_scan += src_gap;
   1329     }
   1330 }
   1331 inline void _CompositeRow_Rgb2Rgb_NoBlend_NoClip(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, int src_Bpp)
   1332 {
   1333     if (dest_Bpp == src_Bpp) {
   1334         FXSYS_memcpy32(dest_scan, src_scan, width * dest_Bpp);
   1335         return;
   1336     }
   1337     for (int col = 0; col < width; col ++) {
   1338         dest_scan[0] = src_scan[0];
   1339         dest_scan[1] = src_scan[1];
   1340         dest_scan[2] = src_scan[2];
   1341         dest_scan += dest_Bpp;
   1342         src_scan += src_Bpp;
   1343     }
   1344 }
   1345 inline void _CompositeRow_Rgb2Rgb_NoBlend_Clip(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, int src_Bpp, FX_LPCBYTE clip_scan)
   1346 {
   1347     for (int col = 0; col < width; col ++) {
   1348         int src_alpha = clip_scan[col];
   1349         if (src_alpha == 255) {
   1350             dest_scan[0] = src_scan[0];
   1351             dest_scan[1] = src_scan[1];
   1352             dest_scan[2] = src_scan[2];
   1353         } else if (src_alpha) {
   1354             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
   1355             dest_scan ++;
   1356             src_scan ++;
   1357             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
   1358             dest_scan ++;
   1359             src_scan ++;
   1360             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
   1361             dest_scan += dest_Bpp - 2;
   1362             src_scan += src_Bpp - 2;
   1363             continue;
   1364         }
   1365         dest_scan += dest_Bpp;
   1366         src_scan += src_Bpp;
   1367     }
   1368 }
   1369 void _CompositeRow_Argb2Argb_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int pixel_count, int blend_type, FX_LPCBYTE clip_scan,
   1370                                        FX_LPBYTE dest_alpha_scan, FX_LPCBYTE src_alpha_scan, FX_LPBYTE src_cache_scan, void* pIccTransform)
   1371 {
   1372     FX_LPBYTE dp = src_cache_scan;
   1373     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1374     if (src_alpha_scan) {
   1375         if (dest_alpha_scan == NULL) {
   1376             for (int col = 0; col < pixel_count; col ++) {
   1377                 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1378                 dp[3] = *src_alpha_scan++;
   1379                 src_scan += 3;
   1380                 dp += 4;
   1381             }
   1382             src_alpha_scan = NULL;
   1383         } else {
   1384             pIccModule->TranslateScanline(pIccTransform, dp, src_scan, pixel_count);
   1385         }
   1386     } else {
   1387         if (dest_alpha_scan == NULL) {
   1388             for (int col = 0; col < pixel_count; col ++) {
   1389                 pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1390                 dp[3] = src_scan[3];
   1391                 src_scan += 4;
   1392                 dp += 4;
   1393             }
   1394         } else {
   1395             int blended_colors[3];
   1396             FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1397             for (int col = 0; col < pixel_count; col ++) {
   1398                 pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1);
   1399                 FX_BYTE back_alpha = *dest_alpha_scan;
   1400                 if (back_alpha == 0) {
   1401                     if (clip_scan) {
   1402                         int src_alpha = clip_scan[col] * src_scan[3] / 255;
   1403                         *dest_alpha_scan = src_alpha;
   1404                         *dest_scan++ = *src_cache_scan++;
   1405                         *dest_scan++ = *src_cache_scan++;
   1406                         *dest_scan++ = *src_cache_scan++;
   1407                     } else {
   1408                         *dest_alpha_scan = src_scan[3];
   1409                         *dest_scan++ = *src_cache_scan++;
   1410                         *dest_scan++ = *src_cache_scan++;
   1411                         *dest_scan++ = *src_cache_scan++;
   1412                     }
   1413                     dest_alpha_scan ++;
   1414                     src_scan += 4;
   1415                     continue;
   1416                 }
   1417                 FX_BYTE src_alpha;
   1418                 if (clip_scan == NULL) {
   1419                     src_alpha = src_scan[3];
   1420                 } else {
   1421                     src_alpha = clip_scan[col] * src_scan[3] / 255;
   1422                 }
   1423                 src_scan += 4;
   1424                 if (src_alpha == 0) {
   1425                     dest_scan += 3;
   1426                     src_cache_scan += 3;
   1427                     dest_alpha_scan ++;
   1428                     continue;
   1429                 }
   1430                 FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1431                 *dest_alpha_scan ++ = dest_alpha;
   1432                 int alpha_ratio = src_alpha * 255 / dest_alpha;
   1433                 if (bNonseparableBlend) {
   1434                     _RGB_Blend(blend_type, src_cache_scan, dest_scan, blended_colors);
   1435                 }
   1436                 for (int color = 0; color < 3; color ++) {
   1437                     if (blend_type) {
   1438                         int blended = bNonseparableBlend ? blended_colors[color] :
   1439                                       _BLEND(blend_type, *dest_scan, *src_cache_scan);
   1440                         blended = FXDIB_ALPHA_MERGE(*src_cache_scan, blended, back_alpha);
   1441                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1442                     } else {
   1443                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_cache_scan, alpha_ratio);
   1444                     }
   1445                     dest_scan ++;
   1446                     src_cache_scan ++;
   1447                 }
   1448             }
   1449             return;
   1450         }
   1451     }
   1452     _CompositeRow_Argb2Argb(dest_scan, src_cache_scan, pixel_count, blend_type, clip_scan, dest_alpha_scan, src_alpha_scan);
   1453 }
   1454 void _CompositeRow_Rgb2Argb_Blend_NoClip_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int src_Bpp,
   1455         FX_LPBYTE dest_alpha_scan, FX_LPBYTE src_cache_scan, void* pIccTransform)
   1456 {
   1457     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1458     if (src_Bpp == 3) {
   1459         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1460     } else {
   1461         FX_LPBYTE dp = src_cache_scan;
   1462         for (int col = 0; col < width; col ++) {
   1463             pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1464             src_scan += 4;
   1465             dp += 3;
   1466         }
   1467     }
   1468     _CompositeRow_Rgb2Argb_Blend_NoClip(dest_scan, src_cache_scan, width, blend_type, 3, dest_alpha_scan);
   1469 }
   1470 inline void _CompositeRow_Rgb2Argb_Blend_Clip_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int src_Bpp, FX_LPCBYTE clip_scan,
   1471         FX_LPBYTE dest_alpha_scan, FX_LPBYTE src_cache_scan, void* pIccTransform)
   1472 {
   1473     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1474     if (src_Bpp == 3) {
   1475         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1476     } else {
   1477         FX_LPBYTE dp = src_cache_scan;
   1478         for (int col = 0; col < width; col ++) {
   1479             pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1480             src_scan += 4;
   1481             dp += 3;
   1482         }
   1483     }
   1484     _CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_cache_scan, width, blend_type, 3, clip_scan, dest_alpha_scan);
   1485 }
   1486 inline void _CompositeRow_Rgb2Argb_NoBlend_Clip_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int src_Bpp, FX_LPCBYTE clip_scan,
   1487         FX_LPBYTE dest_alpha_scan, FX_LPBYTE src_cache_scan, void* pIccTransform)
   1488 {
   1489     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1490     if (src_Bpp == 3) {
   1491         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1492     } else {
   1493         FX_LPBYTE dp = src_cache_scan;
   1494         for (int col = 0; col < width; col ++) {
   1495             pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1496             src_scan += 4;
   1497             dp += 3;
   1498         }
   1499     }
   1500     _CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_cache_scan, width, 3, clip_scan, dest_alpha_scan);
   1501 }
   1502 inline void _CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int src_Bpp,
   1503         FX_LPBYTE dest_alpha_scan, FX_LPBYTE src_cache_scan, void* pIccTransform)
   1504 {
   1505     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1506     if (src_Bpp == 3) {
   1507         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1508     } else {
   1509         FX_LPBYTE dp = src_cache_scan;
   1510         for (int col = 0; col < width; col ++) {
   1511             pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1512             src_scan += 4;
   1513             dp += 3;
   1514         }
   1515     }
   1516     _CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_cache_scan, width, 3, dest_alpha_scan);
   1517 }
   1518 inline void _CompositeRow_Argb2Rgb_Blend_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int dest_Bpp, FX_LPCBYTE clip_scan,
   1519         FX_LPCBYTE src_alpha_scan, FX_LPBYTE src_cache_scan, void* pIccTransform)
   1520 {
   1521     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1522     if (src_alpha_scan) {
   1523         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1524     } else {
   1525         int blended_colors[3];
   1526         FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1527         int dest_gap = dest_Bpp - 3;
   1528         for (int col = 0; col < width; col ++) {
   1529             pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1);
   1530             FX_BYTE src_alpha;
   1531             if (clip_scan) {
   1532                 src_alpha = src_scan[3] * (*clip_scan++) / 255;
   1533             } else {
   1534                 src_alpha = src_scan[3];
   1535             }
   1536             src_scan += 4;
   1537             if (src_alpha == 0) {
   1538                 dest_scan += dest_Bpp;
   1539                 src_cache_scan += 3;
   1540                 continue;
   1541             }
   1542             if (bNonseparableBlend) {
   1543                 _RGB_Blend(blend_type, src_cache_scan, dest_scan, blended_colors);
   1544             }
   1545             for (int color = 0; color < 3; color ++) {
   1546                 int back_color = *dest_scan;
   1547                 int blended = bNonseparableBlend ? blended_colors[color] :
   1548                               _BLEND(blend_type, back_color, *src_cache_scan);
   1549                 *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
   1550                 dest_scan ++;
   1551                 src_cache_scan ++;
   1552             }
   1553             dest_scan += dest_gap;
   1554         }
   1555         return;
   1556     }
   1557     _CompositeRow_Argb2Rgb_Blend(dest_scan, src_cache_scan, width, blend_type, dest_Bpp, clip_scan, src_alpha_scan);
   1558 }
   1559 inline void _CompositeRow_Argb2Rgb_NoBlend_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, FX_LPCBYTE clip_scan,
   1560         FX_LPCBYTE src_alpha_scan, FX_LPBYTE src_cache_scan, void* pIccTransform)
   1561 {
   1562     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1563     if (src_alpha_scan) {
   1564         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1565     } else {
   1566         int dest_gap = dest_Bpp - 3;
   1567         for (int col = 0; col < width; col ++) {
   1568             pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1);
   1569             FX_BYTE src_alpha;
   1570             if (clip_scan) {
   1571                 src_alpha = src_scan[3] * (*clip_scan++) / 255;
   1572             } else {
   1573                 src_alpha = src_scan[3];
   1574             }
   1575             src_scan += 4;
   1576             if (src_alpha == 255) {
   1577                 *dest_scan++ = *src_cache_scan++;
   1578                 *dest_scan++ = *src_cache_scan++;
   1579                 *dest_scan++ = *src_cache_scan++;
   1580                 dest_scan += dest_gap;
   1581                 continue;
   1582             }
   1583             if (src_alpha == 0) {
   1584                 dest_scan += dest_Bpp;
   1585                 src_cache_scan += 3;
   1586                 continue;
   1587             }
   1588             for (int color = 0; color < 3; color ++) {
   1589                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_cache_scan, src_alpha);
   1590                 dest_scan ++;
   1591                 src_cache_scan ++;
   1592             }
   1593             dest_scan += dest_gap;
   1594         }
   1595         return;
   1596     }
   1597     _CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_cache_scan, width, dest_Bpp, clip_scan, src_alpha_scan);
   1598 }
   1599 inline void _CompositeRow_Rgb2Rgb_Blend_NoClip_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int dest_Bpp, int src_Bpp,
   1600         FX_LPBYTE src_cache_scan, void* pIccTransform)
   1601 {
   1602     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1603     if (src_Bpp == 3) {
   1604         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1605     } else {
   1606         FX_LPBYTE dp = src_cache_scan;
   1607         for (int col = 0; col < width; col ++) {
   1608             pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1609             src_scan += 4;
   1610             dp += 3;
   1611         }
   1612     }
   1613     _CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_cache_scan, width, blend_type, dest_Bpp, 3);
   1614 }
   1615 inline void _CompositeRow_Rgb2Rgb_Blend_Clip_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int dest_Bpp, int src_Bpp, FX_LPCBYTE clip_scan,
   1616         FX_LPBYTE src_cache_scan, void* pIccTransform)
   1617 {
   1618     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1619     if (src_Bpp == 3) {
   1620         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1621     } else {
   1622         FX_LPBYTE dp = src_cache_scan;
   1623         for (int col = 0; col < width; col ++) {
   1624             pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1625             src_scan += 4;
   1626             dp += 3;
   1627         }
   1628     }
   1629     _CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_cache_scan, width, blend_type, dest_Bpp, 3, clip_scan);
   1630 }
   1631 inline void _CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, int src_Bpp,
   1632         FX_LPBYTE src_cache_scan, void* pIccTransform)
   1633 {
   1634     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1635     if (src_Bpp == 3) {
   1636         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1637     } else {
   1638         FX_LPBYTE dp = src_cache_scan;
   1639         for (int col = 0; col < width; col ++) {
   1640             pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1641             src_scan += 4;
   1642             dp += 3;
   1643         }
   1644     }
   1645     _CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_cache_scan, width, dest_Bpp, 3);
   1646 }
   1647 inline void _CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, int src_Bpp, FX_LPCBYTE clip_scan,
   1648         FX_LPBYTE src_cache_scan, void* pIccTransform)
   1649 {
   1650     ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   1651     if (src_Bpp == 3) {
   1652         pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, width);
   1653     } else {
   1654         FX_LPBYTE dp = src_cache_scan;
   1655         for (int col = 0; col < width; col ++) {
   1656             pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
   1657             src_scan += 4;
   1658             dp += 3;
   1659         }
   1660     }
   1661     _CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_cache_scan, width, dest_Bpp, 3, clip_scan);
   1662 }
   1663 inline void _CompositeRow_8bppPal2Gray(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, FX_LPCBYTE pPalette, int pixel_count,
   1664                                        int blend_type, FX_LPCBYTE clip_scan,
   1665                                        FX_LPCBYTE src_alpha_scan)
   1666 {
   1667     if (src_alpha_scan) {
   1668         if (blend_type) {
   1669             FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1670             int blended_color;
   1671             for (int col = 0; col < pixel_count; col ++) {
   1672                 FX_BYTE gray = pPalette[*src_scan];
   1673                 int src_alpha = *src_alpha_scan++;
   1674                 if (clip_scan) {
   1675                     src_alpha = clip_scan[col] * src_alpha / 255;
   1676                 }
   1677                 if (bNonseparableBlend) {
   1678                     blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
   1679                 }
   1680                 gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
   1681                 if (src_alpha) {
   1682                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
   1683                 } else {
   1684                     *dest_scan = gray;
   1685                 }
   1686                 dest_scan ++;
   1687                 src_scan ++;
   1688             }
   1689             return;
   1690         }
   1691         for (int col = 0; col < pixel_count; col ++) {
   1692             FX_BYTE gray = pPalette[*src_scan];
   1693             int src_alpha = *src_alpha_scan++;
   1694             if (clip_scan) {
   1695                 src_alpha = clip_scan[col] * src_alpha / 255;
   1696             }
   1697             if (src_alpha) {
   1698                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
   1699             } else {
   1700                 *dest_scan = gray;
   1701             }
   1702             dest_scan ++;
   1703             src_scan ++;
   1704         }
   1705     } else {
   1706         if (blend_type) {
   1707             FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1708             int blended_color;
   1709             for (int col = 0; col < pixel_count; col ++) {
   1710                 FX_BYTE gray = pPalette[*src_scan];
   1711                 if (bNonseparableBlend) {
   1712                     blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
   1713                 }
   1714                 gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
   1715                 if (clip_scan && clip_scan[col] < 255) {
   1716                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
   1717                 } else {
   1718                     *dest_scan = gray;
   1719                 }
   1720                 dest_scan ++;
   1721                 src_scan ++;
   1722             }
   1723             return;
   1724         }
   1725         for (int col = 0; col < pixel_count; col ++) {
   1726             FX_BYTE gray = pPalette[*src_scan];
   1727             if (clip_scan && clip_scan[col] < 255) {
   1728                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
   1729             } else {
   1730                 *dest_scan = gray;
   1731             }
   1732             dest_scan ++;
   1733             src_scan ++;
   1734         }
   1735     }
   1736 }
   1737 inline void _CompositeRow_8bppPal2Graya(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, FX_LPCBYTE pPalette, int pixel_count,
   1738                                         int blend_type, FX_LPCBYTE clip_scan,
   1739                                         FX_LPBYTE dest_alpha_scan, FX_LPCBYTE src_alpha_scan)
   1740 {
   1741     if (src_alpha_scan) {
   1742         if (blend_type) {
   1743             FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1744             int blended_color;
   1745             for (int col = 0; col < pixel_count; col ++) {
   1746                 FX_BYTE gray = pPalette[*src_scan];
   1747                 src_scan ++;
   1748                 FX_BYTE back_alpha = *dest_alpha_scan;
   1749                 if (back_alpha == 0) {
   1750                     int src_alpha = *src_alpha_scan ++;
   1751                     if (clip_scan) {
   1752                         src_alpha = clip_scan[col] * src_alpha / 255;
   1753                     }
   1754                     if (src_alpha) {
   1755                         *dest_scan = gray;
   1756                         *dest_alpha_scan = src_alpha;
   1757                     }
   1758                     dest_scan ++;
   1759                     dest_alpha_scan ++;
   1760                     continue;
   1761                 }
   1762                 FX_BYTE src_alpha = *src_alpha_scan++;
   1763                 if (clip_scan) {
   1764                     src_alpha = clip_scan[col] * src_alpha / 255;
   1765                 }
   1766                 if (src_alpha == 0) {
   1767                     dest_scan ++;
   1768                     dest_alpha_scan ++;
   1769                     continue;
   1770                 }
   1771                 *dest_alpha_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1772                 int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan);
   1773                 if (bNonseparableBlend) {
   1774                     blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
   1775                 }
   1776                 gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
   1777                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1778                 dest_alpha_scan ++;
   1779                 dest_scan ++;
   1780             }
   1781             return;
   1782         }
   1783         for (int col = 0; col < pixel_count; col ++) {
   1784             FX_BYTE gray = pPalette[*src_scan];
   1785             src_scan ++;
   1786             FX_BYTE back_alpha = *dest_alpha_scan;
   1787             if (back_alpha == 0) {
   1788                 int src_alpha = *src_alpha_scan ++;
   1789                 if (clip_scan) {
   1790                     src_alpha = clip_scan[col] * src_alpha / 255;
   1791                 }
   1792                 if (src_alpha) {
   1793                     *dest_scan = gray;
   1794                     *dest_alpha_scan = src_alpha;
   1795                 }
   1796                 dest_scan ++;
   1797                 dest_alpha_scan ++;
   1798                 continue;
   1799             }
   1800             FX_BYTE src_alpha = *src_alpha_scan++;
   1801             if (clip_scan) {
   1802                 src_alpha = clip_scan[col] * src_alpha / 255;
   1803             }
   1804             if (src_alpha == 0) {
   1805                 dest_scan ++;
   1806                 dest_alpha_scan ++;
   1807                 continue;
   1808             }
   1809             *dest_alpha_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1810             int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan);
   1811             dest_alpha_scan ++;
   1812             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1813             dest_scan ++;
   1814         }
   1815     } else {
   1816         if (blend_type) {
   1817             FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1818             int blended_color;
   1819             for (int col = 0; col < pixel_count; col ++) {
   1820                 FX_BYTE gray = pPalette[*src_scan];
   1821                 src_scan ++;
   1822                 if (clip_scan == NULL || clip_scan[col] == 255) {
   1823                     *dest_scan++ = gray;
   1824                     *dest_alpha_scan++ = 255;
   1825                     continue;
   1826                 }
   1827                 int src_alpha = clip_scan[col];
   1828                 if (src_alpha == 0) {
   1829                     dest_scan ++;
   1830                     dest_alpha_scan ++;
   1831                     continue;
   1832                 }
   1833                 int back_alpha = *dest_alpha_scan;
   1834                 FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1835                 *dest_alpha_scan ++ = dest_alpha;
   1836                 int alpha_ratio = src_alpha * 255 / dest_alpha;
   1837                 if (bNonseparableBlend) {
   1838                     blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
   1839                 }
   1840                 gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
   1841                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1842                 dest_scan ++;
   1843             }
   1844             return;
   1845         }
   1846         for (int col = 0; col < pixel_count; col ++) {
   1847             FX_BYTE gray = pPalette[*src_scan];
   1848             src_scan ++;
   1849             if (clip_scan == NULL || clip_scan[col] == 255) {
   1850                 *dest_scan++ = gray;
   1851                 *dest_alpha_scan++ = 255;
   1852                 continue;
   1853             }
   1854             int src_alpha = clip_scan[col];
   1855             if (src_alpha == 0) {
   1856                 dest_scan ++;
   1857                 dest_alpha_scan ++;
   1858                 continue;
   1859             }
   1860             int back_alpha = *dest_alpha_scan;
   1861             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1862             *dest_alpha_scan ++ = dest_alpha;
   1863             int alpha_ratio = src_alpha * 255 / dest_alpha;
   1864             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1865             dest_scan ++;
   1866         }
   1867     }
   1868 }
   1869 inline void _CompositeRow_1bppPal2Gray(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left,
   1870                                        FX_LPCBYTE pPalette, int pixel_count, int blend_type, FX_LPCBYTE clip_scan)
   1871 {
   1872     int reset_gray = pPalette[0];
   1873     int set_gray = pPalette[1];
   1874     if (blend_type) {
   1875         FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1876         int blended_color;
   1877         for (int col = 0; col < pixel_count; col ++) {
   1878             FX_BYTE gray = (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) ? set_gray : reset_gray;
   1879             if (bNonseparableBlend) {
   1880                 blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
   1881             }
   1882             gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
   1883             if (clip_scan && clip_scan[col] < 255) {
   1884                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
   1885             } else {
   1886                 *dest_scan = gray;
   1887             }
   1888             dest_scan ++;
   1889         }
   1890         return;
   1891     }
   1892     for (int col = 0; col < pixel_count; col ++) {
   1893         FX_BYTE gray = (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) ? set_gray : reset_gray;
   1894         if (clip_scan && clip_scan[col] < 255) {
   1895             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
   1896         } else {
   1897             *dest_scan = gray;
   1898         }
   1899         dest_scan ++;
   1900     }
   1901 }
   1902 inline void _CompositeRow_1bppPal2Graya(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left,
   1903                                         FX_LPCBYTE pPalette, int pixel_count, int blend_type, FX_LPCBYTE clip_scan,
   1904                                         FX_LPBYTE dest_alpha_scan)
   1905 {
   1906     int reset_gray = pPalette[0];
   1907     int set_gray = pPalette[1];
   1908     if (blend_type) {
   1909         FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1910         int blended_color;
   1911         for (int col = 0; col < pixel_count; col ++) {
   1912             FX_BYTE gray = (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) ? set_gray : reset_gray;
   1913             if (clip_scan == NULL || clip_scan[col] == 255) {
   1914                 *dest_scan++ = gray;
   1915                 *dest_alpha_scan ++ = 255;
   1916                 continue;
   1917             }
   1918             int src_alpha = clip_scan[col];
   1919             if (src_alpha == 0) {
   1920                 dest_scan ++;
   1921                 dest_alpha_scan ++;
   1922                 continue;
   1923             }
   1924             int back_alpha = *dest_alpha_scan;
   1925             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1926             *dest_alpha_scan ++ = dest_alpha;
   1927             int alpha_ratio = src_alpha * 255 / dest_alpha;
   1928             if (bNonseparableBlend) {
   1929                 blended_color = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
   1930             }
   1931             gray = bNonseparableBlend ? blended_color : _BLEND(blend_type, *dest_scan, gray);
   1932             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1933             dest_scan ++;
   1934         }
   1935         return;
   1936     }
   1937     for (int col = 0; col < pixel_count; col ++) {
   1938         FX_BYTE gray = (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) ? set_gray : reset_gray;
   1939         if (clip_scan == NULL || clip_scan[col] == 255) {
   1940             *dest_scan++ = gray;
   1941             *dest_alpha_scan ++ = 255;
   1942             continue;
   1943         }
   1944         int src_alpha = clip_scan[col];
   1945         if (src_alpha == 0) {
   1946             dest_scan ++;
   1947             dest_alpha_scan ++;
   1948             continue;
   1949         }
   1950         int back_alpha = *dest_alpha_scan;
   1951         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1952         *dest_alpha_scan ++ = dest_alpha;
   1953         int alpha_ratio = src_alpha * 255 / dest_alpha;
   1954         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1955         dest_scan ++;
   1956     }
   1957 }
   1958 inline void _CompositeRow_8bppRgb2Rgb_NoBlend(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, FX_DWORD* pPalette, int pixel_count,
   1959         int DestBpp, FX_LPCBYTE clip_scan,
   1960         FX_LPCBYTE src_alpha_scan)
   1961 {
   1962     if (src_alpha_scan) {
   1963         int dest_gap = DestBpp - 3;
   1964         FX_ARGB argb = 0;
   1965         for (int col = 0; col < pixel_count; col ++) {
   1966             argb = pPalette[*src_scan];
   1967             int src_r = FXARGB_R(argb);
   1968             int src_g = FXARGB_G(argb);
   1969             int src_b = FXARGB_B(argb);
   1970             src_scan ++;
   1971             FX_BYTE src_alpha = 0;
   1972             if (clip_scan) {
   1973                 src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255;
   1974             } else {
   1975                 src_alpha = *src_alpha_scan++;
   1976             }
   1977             if (src_alpha == 255) {
   1978                 *dest_scan++ = src_b;
   1979                 *dest_scan++ = src_g;
   1980                 *dest_scan++ = src_r;
   1981                 dest_scan += dest_gap;
   1982                 continue;
   1983             }
   1984             if (src_alpha == 0) {
   1985                 dest_scan += DestBpp;
   1986                 continue;
   1987             }
   1988             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
   1989             dest_scan ++;
   1990             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
   1991             dest_scan ++;
   1992             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
   1993             dest_scan ++;
   1994             dest_scan += dest_gap;
   1995         }
   1996     } else {
   1997         FX_ARGB argb = 0;
   1998         for (int col = 0; col < pixel_count; col ++) {
   1999             argb = pPalette[*src_scan];
   2000             int src_r = FXARGB_R(argb);
   2001             int src_g = FXARGB_G(argb);
   2002             int src_b = FXARGB_B(argb);
   2003             if (clip_scan && clip_scan[col] < 255) {
   2004                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]);
   2005                 dest_scan ++;
   2006                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]);
   2007                 dest_scan ++;
   2008                 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]);
   2009                 dest_scan ++;
   2010             } else {
   2011                 *dest_scan++ = src_b;
   2012                 *dest_scan++ = src_g;
   2013                 *dest_scan++ = src_r;
   2014             }
   2015             if (DestBpp == 4) {
   2016                 dest_scan++;
   2017             }
   2018             src_scan ++;
   2019         }
   2020     }
   2021 }
   2022 inline void _CompositeRow_1bppRgb2Rgb_NoBlend(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left,
   2023         FX_DWORD* pPalette, int pixel_count, int DestBpp, FX_LPCBYTE clip_scan)
   2024 {
   2025     int reset_r, reset_g, reset_b;
   2026     int set_r, set_g, set_b;
   2027     reset_r = FXARGB_R(pPalette[0]);
   2028     reset_g = FXARGB_G(pPalette[0]);
   2029     reset_b = FXARGB_B(pPalette[0]);
   2030     set_r = FXARGB_R(pPalette[1]);
   2031     set_g = FXARGB_G(pPalette[1]);
   2032     set_b = FXARGB_B(pPalette[1]);
   2033     for (int col = 0; col < pixel_count; col ++) {
   2034         int src_r, src_g, src_b;
   2035         if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   2036             src_r = set_r;
   2037             src_g = set_g;
   2038             src_b = set_b;
   2039         } else {
   2040             src_r = reset_r;
   2041             src_g = reset_g;
   2042             src_b = reset_b;
   2043         }
   2044         if (clip_scan && clip_scan[col] < 255) {
   2045             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]);
   2046             dest_scan ++;
   2047             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]);
   2048             dest_scan ++;
   2049             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]);
   2050             dest_scan ++;
   2051         } else {
   2052             *dest_scan++ = src_b;
   2053             *dest_scan++ = src_g;
   2054             *dest_scan++ = src_r;
   2055         }
   2056         if (DestBpp == 4) {
   2057             dest_scan++;
   2058         }
   2059     }
   2060 }
   2061 inline void _CompositeRow_8bppRgb2Argb_NoBlend(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width,
   2062         FX_DWORD* pPalette, FX_LPCBYTE clip_scan,
   2063         FX_LPCBYTE src_alpha_scan)
   2064 {
   2065     if (src_alpha_scan) {
   2066         for (int col = 0; col < width; col ++) {
   2067             FX_ARGB argb = pPalette[*src_scan];
   2068             src_scan ++;
   2069             int src_r = FXARGB_R(argb);
   2070             int src_g = FXARGB_G(argb);
   2071             int src_b = FXARGB_B(argb);
   2072             FX_BYTE back_alpha = dest_scan[3];
   2073             if (back_alpha == 0) {
   2074                 if (clip_scan) {
   2075                     int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255;
   2076                     FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   2077                 } else {
   2078                     FXARGB_SETDIB(dest_scan, FXARGB_MAKE(*src_alpha_scan, src_r, src_g, src_b));
   2079                 }
   2080                 dest_scan += 4;
   2081                 src_alpha_scan ++;
   2082                 continue;
   2083             }
   2084             FX_BYTE src_alpha;
   2085             if (clip_scan == NULL) {
   2086                 src_alpha = *src_alpha_scan ++;
   2087             } else {
   2088                 src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255;
   2089             }
   2090             if (src_alpha == 0) {
   2091                 dest_scan += 4;
   2092                 continue;
   2093             }
   2094             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2095             dest_scan[3] = dest_alpha;
   2096             int alpha_ratio = src_alpha * 255 / dest_alpha;
   2097             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2098             dest_scan ++;
   2099             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2100             dest_scan ++;
   2101             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2102             dest_scan ++;
   2103             dest_scan ++;
   2104         }
   2105     } else
   2106         for (int col = 0; col < width; col ++) {
   2107             FX_ARGB argb = pPalette[*src_scan];
   2108             int src_r = FXARGB_R(argb);
   2109             int src_g = FXARGB_G(argb);
   2110             int src_b = FXARGB_B(argb);
   2111             if (clip_scan == NULL || clip_scan[col] == 255) {
   2112                 *dest_scan++ = src_b;
   2113                 *dest_scan++ = src_g;
   2114                 *dest_scan++ = src_r;
   2115                 *dest_scan++ = 255;
   2116                 src_scan ++;
   2117                 continue;
   2118             }
   2119             int src_alpha = clip_scan[col];
   2120             if (src_alpha == 0) {
   2121                 dest_scan += 4;
   2122                 src_scan ++;
   2123                 continue;
   2124             }
   2125             int back_alpha = dest_scan[3];
   2126             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2127             dest_scan[3] = dest_alpha;
   2128             int alpha_ratio = src_alpha * 255 / dest_alpha;
   2129             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2130             dest_scan ++;
   2131             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2132             dest_scan ++;
   2133             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2134             dest_scan ++;
   2135             dest_scan ++;
   2136             src_scan ++;
   2137         }
   2138 }
   2139 void _CompositeRow_8bppRgb2Rgba_NoBlend(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width,
   2140                                         FX_DWORD* pPalette, FX_LPCBYTE clip_scan,
   2141                                         FX_LPBYTE dest_alpha_scan, FX_LPCBYTE src_alpha_scan)
   2142 {
   2143     if (src_alpha_scan) {
   2144         for (int col = 0; col < width; col ++) {
   2145             FX_ARGB argb = pPalette[*src_scan];
   2146             src_scan ++;
   2147             int src_r = FXARGB_R(argb);
   2148             int src_g = FXARGB_G(argb);
   2149             int src_b = FXARGB_B(argb);
   2150             FX_BYTE back_alpha = *dest_alpha_scan;
   2151             if (back_alpha == 0) {
   2152                 if (clip_scan) {
   2153                     int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255;
   2154                     *dest_alpha_scan ++ = src_alpha;
   2155                 } else {
   2156                     *dest_alpha_scan ++ = *src_alpha_scan;
   2157                 }
   2158                 *dest_scan ++ = src_b;
   2159                 *dest_scan ++ = src_g;
   2160                 *dest_scan ++ = src_r;
   2161                 src_alpha_scan ++;
   2162                 continue;
   2163             }
   2164             FX_BYTE src_alpha;
   2165             if (clip_scan == NULL) {
   2166                 src_alpha = *src_alpha_scan++;
   2167             } else {
   2168                 src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255;
   2169             }
   2170             if (src_alpha == 0) {
   2171                 dest_scan += 3;
   2172                 dest_alpha_scan ++;
   2173                 continue;
   2174             }
   2175             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2176             *dest_alpha_scan ++ = dest_alpha;
   2177             int alpha_ratio = src_alpha * 255 / dest_alpha;
   2178             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2179             dest_scan ++;
   2180             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2181             dest_scan ++;
   2182             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2183             dest_scan ++;
   2184         }
   2185     } else
   2186         for (int col = 0; col < width; col ++) {
   2187             FX_ARGB argb = pPalette[*src_scan];
   2188             int src_r = FXARGB_R(argb);
   2189             int src_g = FXARGB_G(argb);
   2190             int src_b = FXARGB_B(argb);
   2191             if (clip_scan == NULL || clip_scan[col] == 255) {
   2192                 *dest_scan++ = src_b;
   2193                 *dest_scan++ = src_g;
   2194                 *dest_scan++ = src_r;
   2195                 *dest_alpha_scan++ = 255;
   2196                 src_scan ++;
   2197                 continue;
   2198             }
   2199             int src_alpha = clip_scan[col];
   2200             if (src_alpha == 0) {
   2201                 dest_scan += 3;
   2202                 dest_alpha_scan ++;
   2203                 src_scan ++;
   2204                 continue;
   2205             }
   2206             int back_alpha = *dest_alpha_scan;
   2207             FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2208             *dest_alpha_scan ++ = dest_alpha;
   2209             int alpha_ratio = src_alpha * 255 / dest_alpha;
   2210             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2211             dest_scan ++;
   2212             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2213             dest_scan ++;
   2214             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2215             dest_scan ++;
   2216             src_scan ++;
   2217         }
   2218 }
   2219 inline void _CompositeRow_1bppRgb2Argb_NoBlend(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width,
   2220         FX_DWORD* pPalette, FX_LPCBYTE clip_scan)
   2221 {
   2222     int reset_r, reset_g, reset_b;
   2223     int set_r, set_g, set_b;
   2224     reset_r = FXARGB_R(pPalette[0]);
   2225     reset_g = FXARGB_G(pPalette[0]);
   2226     reset_b = FXARGB_B(pPalette[0]);
   2227     set_r = FXARGB_R(pPalette[1]);
   2228     set_g = FXARGB_G(pPalette[1]);
   2229     set_b = FXARGB_B(pPalette[1]);
   2230     for (int col = 0; col < width; col ++) {
   2231         int src_r, src_g, src_b;
   2232         if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   2233             src_r = set_r;
   2234             src_g = set_g;
   2235             src_b = set_b;
   2236         } else {
   2237             src_r = reset_r;
   2238             src_g = reset_g;
   2239             src_b = reset_b;
   2240         }
   2241         if (clip_scan == NULL || clip_scan[col] == 255) {
   2242             *dest_scan++ = src_b;
   2243             *dest_scan++ = src_g;
   2244             *dest_scan++ = src_r;
   2245             *dest_scan++ = 255;
   2246             continue;
   2247         }
   2248         int src_alpha = clip_scan[col];
   2249         if (src_alpha == 0) {
   2250             dest_scan += 4;
   2251             continue;
   2252         }
   2253         int back_alpha = dest_scan[3];
   2254         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2255         dest_scan[3] = dest_alpha;
   2256         int alpha_ratio = src_alpha * 255 / dest_alpha;
   2257         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2258         dest_scan ++;
   2259         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2260         dest_scan ++;
   2261         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2262         dest_scan ++;
   2263         dest_scan ++;
   2264     }
   2265 }
   2266 void _CompositeRow_1bppRgb2Rgba_NoBlend(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width,
   2267                                         FX_DWORD* pPalette, FX_LPCBYTE clip_scan,
   2268                                         FX_LPBYTE dest_alpha_scan)
   2269 {
   2270     int reset_r, reset_g, reset_b;
   2271     int set_r, set_g, set_b;
   2272     reset_r = FXARGB_R(pPalette[0]);
   2273     reset_g = FXARGB_G(pPalette[0]);
   2274     reset_b = FXARGB_B(pPalette[0]);
   2275     set_r = FXARGB_R(pPalette[1]);
   2276     set_g = FXARGB_G(pPalette[1]);
   2277     set_b = FXARGB_B(pPalette[1]);
   2278     for (int col = 0; col < width; col ++) {
   2279         int src_r, src_g, src_b;
   2280         if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   2281             src_r = set_r;
   2282             src_g = set_g;
   2283             src_b = set_b;
   2284         } else {
   2285             src_r = reset_r;
   2286             src_g = reset_g;
   2287             src_b = reset_b;
   2288         }
   2289         if (clip_scan == NULL || clip_scan[col] == 255) {
   2290             *dest_scan++ = src_b;
   2291             *dest_scan++ = src_g;
   2292             *dest_scan++ = src_r;
   2293             *dest_alpha_scan++ = 255;
   2294             continue;
   2295         }
   2296         int src_alpha = clip_scan[col];
   2297         if (src_alpha == 0) {
   2298             dest_scan += 3;
   2299             dest_alpha_scan ++;
   2300             continue;
   2301         }
   2302         int back_alpha = *dest_alpha_scan;
   2303         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2304         *dest_alpha_scan ++ = dest_alpha;
   2305         int alpha_ratio = src_alpha * 255 / dest_alpha;
   2306         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2307         dest_scan ++;
   2308         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2309         dest_scan ++;
   2310         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2311         dest_scan ++;
   2312     }
   2313 }
   2314 void _CompositeRow_ByteMask2Argb(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b, int pixel_count,
   2315                                  int blend_type, FX_LPCBYTE clip_scan)
   2316 {
   2317     for (int col = 0; col < pixel_count; col ++) {
   2318         int src_alpha;
   2319         if (clip_scan) {
   2320             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   2321         } else {
   2322             src_alpha = mask_alpha * src_scan[col] / 255;
   2323         }
   2324         FX_BYTE back_alpha = dest_scan[3];
   2325         if (back_alpha == 0) {
   2326             FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   2327             dest_scan += 4;
   2328             continue;
   2329         }
   2330         if (src_alpha == 0) {
   2331             dest_scan += 4;
   2332             continue;
   2333         }
   2334         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2335         dest_scan[3] = dest_alpha;
   2336         int alpha_ratio = src_alpha * 255 / dest_alpha;
   2337         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2338             int blended_colors[3];
   2339             FX_BYTE src_scan[3];
   2340             src_scan[0] = src_b;
   2341             src_scan[1] = src_g;
   2342             src_scan[2] = src_r;
   2343             _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   2344             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
   2345             dest_scan ++;
   2346             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
   2347             dest_scan ++;
   2348             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
   2349         } else if (blend_type) {
   2350             int blended = _BLEND(blend_type, *dest_scan, src_b);
   2351             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   2352             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2353             dest_scan ++;
   2354             blended = _BLEND(blend_type, *dest_scan, src_g);
   2355             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   2356             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2357             dest_scan ++;
   2358             blended = _BLEND(blend_type, *dest_scan, src_r);
   2359             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   2360             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2361         } else {
   2362             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2363             dest_scan ++;
   2364             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2365             dest_scan ++;
   2366             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2367         }
   2368         dest_scan += 2;
   2369     }
   2370 }
   2371 void _CompositeRow_ByteMask2Rgba(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b, int pixel_count,
   2372                                  int blend_type, FX_LPCBYTE clip_scan,
   2373                                  FX_LPBYTE dest_alpha_scan)
   2374 {
   2375     for (int col = 0; col < pixel_count; col ++) {
   2376         int src_alpha;
   2377         if (clip_scan) {
   2378             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   2379         } else {
   2380             src_alpha = mask_alpha * src_scan[col] / 255;
   2381         }
   2382         FX_BYTE back_alpha = *dest_alpha_scan;
   2383         if (back_alpha == 0) {
   2384             *dest_scan ++ = src_b;
   2385             *dest_scan ++ = src_g;
   2386             *dest_scan ++ = src_r;
   2387             *dest_alpha_scan ++ = src_alpha;
   2388             continue;
   2389         }
   2390         if (src_alpha == 0) {
   2391             dest_scan += 3;
   2392             dest_alpha_scan ++;
   2393             continue;
   2394         }
   2395         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2396         *dest_alpha_scan ++ = dest_alpha;
   2397         int alpha_ratio = src_alpha * 255 / dest_alpha;
   2398         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2399             int blended_colors[3];
   2400             FX_BYTE src_scan[3];
   2401             src_scan[0] = src_b;
   2402             src_scan[1] = src_g;
   2403             src_scan[2] = src_r;
   2404             _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   2405             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
   2406             dest_scan ++;
   2407             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
   2408             dest_scan ++;
   2409             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
   2410             dest_scan ++;
   2411         } else if (blend_type) {
   2412             int blended = _BLEND(blend_type, *dest_scan, src_b);
   2413             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   2414             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2415             dest_scan ++;
   2416             blended = _BLEND(blend_type, *dest_scan, src_g);
   2417             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   2418             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2419             dest_scan ++;
   2420             blended = _BLEND(blend_type, *dest_scan, src_r);
   2421             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   2422             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2423             dest_scan ++;
   2424         } else {
   2425             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2426             dest_scan ++;
   2427             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2428             dest_scan ++;
   2429             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2430             dest_scan ++;
   2431         }
   2432     }
   2433 }
   2434 void _CompositeRow_ByteMask2Rgb(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b, int pixel_count,
   2435                                 int blend_type, int Bpp, FX_LPCBYTE clip_scan)
   2436 {
   2437     for (int col = 0; col < pixel_count; col ++) {
   2438         int src_alpha;
   2439         if (clip_scan) {
   2440             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   2441         } else {
   2442             src_alpha = mask_alpha * src_scan[col] / 255;
   2443         }
   2444         if (src_alpha == 0) {
   2445             dest_scan += Bpp;
   2446             continue;
   2447         }
   2448         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2449             int blended_colors[3];
   2450             FX_BYTE src_scan[3];
   2451             src_scan[0] = src_b;
   2452             src_scan[1] = src_g;
   2453             src_scan[2] = src_r;
   2454             _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   2455             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha);
   2456             dest_scan ++;
   2457             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha);
   2458             dest_scan ++;
   2459             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha);
   2460         } else if (blend_type) {
   2461             int blended = _BLEND(blend_type, *dest_scan, src_b);
   2462             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   2463             dest_scan ++;
   2464             blended = _BLEND(blend_type, *dest_scan, src_g);
   2465             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   2466             dest_scan ++;
   2467             blended = _BLEND(blend_type, *dest_scan, src_r);
   2468             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   2469         } else {
   2470             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
   2471             dest_scan ++;
   2472             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
   2473             dest_scan ++;
   2474             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
   2475         }
   2476         dest_scan += Bpp - 2;
   2477     }
   2478 }
   2479 void _CompositeRow_ByteMask2Mask(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int pixel_count,
   2480                                  FX_LPCBYTE clip_scan)
   2481 {
   2482     for (int col = 0; col < pixel_count; col ++) {
   2483         int src_alpha;
   2484         if (clip_scan) {
   2485             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   2486         } else {
   2487             src_alpha = mask_alpha * src_scan[col] / 255;
   2488         }
   2489         FX_BYTE back_alpha = *dest_scan;
   2490         if (!back_alpha) {
   2491             *dest_scan = src_alpha;
   2492         } else if (src_alpha) {
   2493             *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2494         }
   2495         dest_scan ++;
   2496     }
   2497 }
   2498 void _CompositeRow_ByteMask2Gray(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_gray,
   2499                                  int pixel_count, FX_LPCBYTE clip_scan)
   2500 {
   2501     for (int col = 0; col < pixel_count; col ++) {
   2502         int src_alpha;
   2503         if (clip_scan) {
   2504             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   2505         } else {
   2506             src_alpha = mask_alpha * src_scan[col] / 255;
   2507         }
   2508         if (src_alpha) {
   2509             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha);
   2510         }
   2511         dest_scan ++;
   2512     }
   2513 }
   2514 void _CompositeRow_ByteMask2Graya(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_gray,
   2515                                   int pixel_count, FX_LPCBYTE clip_scan,
   2516                                   FX_LPBYTE dest_alpha_scan)
   2517 {
   2518     for (int col = 0; col < pixel_count; col ++) {
   2519         int src_alpha;
   2520         if (clip_scan) {
   2521             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   2522         } else {
   2523             src_alpha = mask_alpha * src_scan[col] / 255;
   2524         }
   2525         FX_BYTE back_alpha = *dest_alpha_scan;
   2526         if (back_alpha == 0) {
   2527             *dest_scan ++ = src_gray;
   2528             *dest_alpha_scan ++ = src_alpha;
   2529             continue;
   2530         }
   2531         if (src_alpha == 0) {
   2532             dest_scan ++;
   2533             dest_alpha_scan ++;
   2534             continue;
   2535         }
   2536         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2537         *dest_alpha_scan++ = dest_alpha;
   2538         int alpha_ratio = src_alpha * 255 / dest_alpha;
   2539         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio);
   2540         dest_scan ++;
   2541     }
   2542 }
   2543 void _CompositeRow_BitMask2Argb(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b,
   2544                                 int src_left, int pixel_count, int blend_type, FX_LPCBYTE clip_scan)
   2545 {
   2546     if (blend_type == FXDIB_BLEND_NORMAL && clip_scan == NULL && mask_alpha == 255) {
   2547         FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b);
   2548         for (int col = 0; col < pixel_count; col ++) {
   2549             if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   2550                 FXARGB_SETDIB(dest_scan, argb);
   2551             }
   2552             dest_scan += 4;
   2553         }
   2554         return;
   2555     }
   2556     for (int col = 0; col < pixel_count; col ++) {
   2557         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   2558             dest_scan += 4;
   2559             continue;
   2560         }
   2561         int src_alpha;
   2562         if (clip_scan) {
   2563             src_alpha = mask_alpha * clip_scan[col] / 255;
   2564         } else {
   2565             src_alpha = mask_alpha;
   2566         }
   2567         FX_BYTE back_alpha = dest_scan[3];
   2568         if (back_alpha == 0) {
   2569             FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   2570             dest_scan += 4;
   2571             continue;
   2572         }
   2573         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2574         dest_scan[3] = dest_alpha;
   2575         int alpha_ratio = src_alpha * 255 / dest_alpha;
   2576         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2577             int blended_colors[3];
   2578             FX_BYTE src_scan[3];
   2579             src_scan[0] = src_b;
   2580             src_scan[1] = src_g;
   2581             src_scan[2] = src_r;
   2582             _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   2583             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
   2584             dest_scan ++;
   2585             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
   2586             dest_scan ++;
   2587             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
   2588         } else if (blend_type) {
   2589             int blended = _BLEND(blend_type, *dest_scan, src_b);
   2590             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   2591             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2592             dest_scan ++;
   2593             blended = _BLEND(blend_type, *dest_scan, src_g);
   2594             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   2595             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2596             dest_scan ++;
   2597             blended = _BLEND(blend_type, *dest_scan, src_r);
   2598             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   2599             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2600         } else {
   2601             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2602             dest_scan ++;
   2603             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2604             dest_scan ++;
   2605             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2606         }
   2607         dest_scan += 2;
   2608     }
   2609 }
   2610 void _CompositeRow_BitMask2Rgba(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b,
   2611                                 int src_left, int pixel_count, int blend_type, FX_LPCBYTE clip_scan,
   2612                                 FX_LPBYTE dest_alpha_scan)
   2613 {
   2614     if (blend_type == FXDIB_BLEND_NORMAL && clip_scan == NULL && mask_alpha == 255) {
   2615         for (int col = 0; col < pixel_count; col ++) {
   2616             if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   2617                 dest_scan[0] = src_b;
   2618                 dest_scan[1] = src_g;
   2619                 dest_scan[2] = src_r;
   2620                 *dest_alpha_scan = mask_alpha;
   2621             }
   2622             dest_scan += 3;
   2623             dest_alpha_scan ++;
   2624         }
   2625         return;
   2626     }
   2627     for (int col = 0; col < pixel_count; col ++) {
   2628         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   2629             dest_scan += 3;
   2630             dest_alpha_scan ++;
   2631             continue;
   2632         }
   2633         int src_alpha;
   2634         if (clip_scan) {
   2635             src_alpha = mask_alpha * clip_scan[col] / 255;
   2636         } else {
   2637             src_alpha = mask_alpha;
   2638         }
   2639         FX_BYTE back_alpha = dest_scan[3];
   2640         if (back_alpha == 0) {
   2641             *dest_scan ++ = src_b;
   2642             *dest_scan ++ = src_g;
   2643             *dest_scan ++ = src_r;
   2644             *dest_alpha_scan ++ = mask_alpha;
   2645             continue;
   2646         }
   2647         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2648         *dest_alpha_scan ++ = dest_alpha;
   2649         int alpha_ratio = src_alpha * 255 / dest_alpha;
   2650         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2651             int blended_colors[3];
   2652             FX_BYTE src_scan[3];
   2653             src_scan[0] = src_b;
   2654             src_scan[1] = src_g;
   2655             src_scan[2] = src_r;
   2656             _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   2657             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
   2658             dest_scan ++;
   2659             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
   2660             dest_scan ++;
   2661             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
   2662             dest_scan ++;
   2663         } else if (blend_type) {
   2664             int blended = _BLEND(blend_type, *dest_scan, src_b);
   2665             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   2666             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2667             dest_scan ++;
   2668             blended = _BLEND(blend_type, *dest_scan, src_g);
   2669             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   2670             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2671             dest_scan ++;
   2672             blended = _BLEND(blend_type, *dest_scan, src_r);
   2673             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   2674             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   2675             dest_scan ++;
   2676         } else {
   2677             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   2678             dest_scan ++;
   2679             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   2680             dest_scan ++;
   2681             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   2682             dest_scan ++;
   2683         }
   2684     }
   2685 }
   2686 void _CompositeRow_BitMask2Rgb(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b,
   2687                                int src_left, int pixel_count, int blend_type, int Bpp, FX_LPCBYTE clip_scan)
   2688 {
   2689     if (blend_type == FXDIB_BLEND_NORMAL && clip_scan == NULL && mask_alpha == 255) {
   2690         for (int col = 0; col < pixel_count; col ++) {
   2691             if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   2692                 dest_scan[2] = src_r;
   2693                 dest_scan[1] = src_g;
   2694                 dest_scan[0] = src_b;
   2695             }
   2696             dest_scan += Bpp;
   2697         }
   2698         return;
   2699     }
   2700     for (int col = 0; col < pixel_count; col ++) {
   2701         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   2702             dest_scan += Bpp;
   2703             continue;
   2704         }
   2705         int src_alpha;
   2706         if (clip_scan) {
   2707             src_alpha = mask_alpha * clip_scan[col] / 255;
   2708         } else {
   2709             src_alpha = mask_alpha;
   2710         }
   2711         if (src_alpha == 0) {
   2712             dest_scan += Bpp;
   2713             continue;
   2714         }
   2715         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2716             int blended_colors[3];
   2717             FX_BYTE src_scan[3];
   2718             src_scan[0] = src_b;
   2719             src_scan[1] = src_g;
   2720             src_scan[2] = src_r;
   2721             _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
   2722             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha);
   2723             dest_scan ++;
   2724             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha);
   2725             dest_scan ++;
   2726             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha);
   2727         } else if (blend_type) {
   2728             int blended = _BLEND(blend_type, *dest_scan, src_b);
   2729             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   2730             dest_scan++;
   2731             blended = _BLEND(blend_type, *dest_scan, src_g);
   2732             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   2733             dest_scan++;
   2734             blended = _BLEND(blend_type, *dest_scan, src_r);
   2735             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   2736         } else {
   2737             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
   2738             dest_scan ++;
   2739             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
   2740             dest_scan ++;
   2741             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
   2742         }
   2743         dest_scan += Bpp - 2;
   2744     }
   2745 }
   2746 void _CompositeRow_BitMask2Mask(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_left,
   2747                                 int pixel_count, FX_LPCBYTE clip_scan)
   2748 {
   2749     for (int col = 0; col < pixel_count; col ++) {
   2750         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   2751             dest_scan ++;
   2752             continue;
   2753         }
   2754         int src_alpha;
   2755         if (clip_scan) {
   2756             src_alpha = mask_alpha * clip_scan[col] / 255;
   2757         } else {
   2758             src_alpha = mask_alpha;
   2759         }
   2760         FX_BYTE back_alpha = *dest_scan;
   2761         if (!back_alpha) {
   2762             *dest_scan = src_alpha;
   2763         } else if (src_alpha) {
   2764             *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2765         }
   2766         dest_scan ++;
   2767     }
   2768 }
   2769 void _CompositeRow_BitMask2Gray(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_gray,
   2770                                 int src_left, int pixel_count, FX_LPCBYTE clip_scan)
   2771 {
   2772     for (int col = 0; col < pixel_count; col ++) {
   2773         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   2774             dest_scan ++;
   2775             continue;
   2776         }
   2777         int src_alpha;
   2778         if (clip_scan) {
   2779             src_alpha = mask_alpha * clip_scan[col] / 255;
   2780         } else {
   2781             src_alpha = mask_alpha;
   2782         }
   2783         if (src_alpha) {
   2784             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha);
   2785         }
   2786         dest_scan ++;
   2787     }
   2788 }
   2789 void _CompositeRow_BitMask2Graya(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_gray,
   2790                                  int src_left, int pixel_count, FX_LPCBYTE clip_scan,
   2791                                  FX_LPBYTE dest_alpha_scan)
   2792 {
   2793     for (int col = 0; col < pixel_count; col ++) {
   2794         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   2795             dest_scan ++;
   2796             dest_alpha_scan ++;
   2797             continue;
   2798         }
   2799         int src_alpha;
   2800         if (clip_scan) {
   2801             src_alpha = mask_alpha * clip_scan[col] / 255;
   2802         } else {
   2803             src_alpha = mask_alpha;
   2804         }
   2805         FX_BYTE back_alpha = *dest_alpha_scan;
   2806         if (back_alpha == 0) {
   2807             *dest_scan ++ = src_gray;
   2808             *dest_alpha_scan ++ = src_alpha;
   2809             continue;
   2810         }
   2811         if (src_alpha == 0) {
   2812             dest_scan ++;
   2813             dest_alpha_scan ++;
   2814             continue;
   2815         }
   2816         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2817         *dest_alpha_scan++ = dest_alpha;
   2818         int alpha_ratio = src_alpha * 255 / dest_alpha;
   2819         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio);
   2820         dest_scan ++;
   2821     }
   2822 }
   2823 void _CompositeRow_Argb2Argb_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int pixel_count, int blend_type, FX_LPCBYTE clip_scan)
   2824 {
   2825     int blended_colors[3];
   2826     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2827     for (int col = 0; col < pixel_count; col ++) {
   2828         FX_BYTE back_alpha = dest_scan[3];
   2829         if (back_alpha == 0) {
   2830             if (clip_scan) {
   2831                 int src_alpha = clip_scan[col] * src_scan[3] / 255;
   2832                 dest_scan[3] = src_alpha;
   2833                 dest_scan[0] = src_scan[2];
   2834                 dest_scan[1] = src_scan[1];
   2835                 dest_scan[2] = src_scan[0];
   2836             } else {
   2837                 FXARGB_RGBORDERCOPY(dest_scan, src_scan);
   2838             }
   2839             dest_scan += 4;
   2840             src_scan += 4;
   2841             continue;
   2842         }
   2843         FX_BYTE src_alpha;
   2844         if (clip_scan == NULL) {
   2845             src_alpha = src_scan[3];
   2846         } else {
   2847             src_alpha = clip_scan[col] * src_scan[3] / 255;
   2848         }
   2849         if (src_alpha == 0) {
   2850             dest_scan += 4;
   2851             src_scan += 4;
   2852             continue;
   2853         }
   2854         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2855         dest_scan[3] = dest_alpha;
   2856         int alpha_ratio = src_alpha * 255 / dest_alpha;
   2857         if (bNonseparableBlend) {
   2858             FX_BYTE dest_scan_o[3];
   2859             dest_scan_o[0] = dest_scan[2];
   2860             dest_scan_o[1] = dest_scan[1];
   2861             dest_scan_o[2] = dest_scan[0];
   2862             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2863         }
   2864         for (int color = 0; color < 3; color ++) {
   2865             int index = 2 - color;
   2866             if (blend_type) {
   2867                 int blended = bNonseparableBlend ? blended_colors[color] :
   2868                               _BLEND(blend_type, dest_scan[index], *src_scan);
   2869                 blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
   2870                 dest_scan[index] = FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
   2871             } else {
   2872                 dest_scan[index] = FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio);
   2873             }
   2874             src_scan ++;
   2875         }
   2876         dest_scan += 4;
   2877         src_scan++;
   2878     }
   2879 }
   2880 void _CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int src_Bpp)
   2881 {
   2882     int blended_colors[3];
   2883     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2884     int src_gap = src_Bpp - 3;
   2885     for (int col = 0; col < width; col ++) {
   2886         FX_BYTE back_alpha = dest_scan[3];
   2887         if (back_alpha == 0) {
   2888             if (src_Bpp == 4) {
   2889                 FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
   2890             } else {
   2891                 FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
   2892             }
   2893             dest_scan += 4;
   2894             src_scan += src_Bpp;
   2895             continue;
   2896         }
   2897         dest_scan[3] = 0xff;
   2898         if (bNonseparableBlend)	{
   2899             FX_BYTE dest_scan_o[3];
   2900             dest_scan_o[0] = dest_scan[2];
   2901             dest_scan_o[1] = dest_scan[1];
   2902             dest_scan_o[2] = dest_scan[0];
   2903             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2904         }
   2905         for (int color = 0; color < 3; color ++) {
   2906             int index = 2 - color;
   2907             int src_color = FX_GAMMA(*src_scan);
   2908             int blended = bNonseparableBlend ? blended_colors[color] :
   2909                           _BLEND(blend_type, dest_scan[index], src_color);
   2910             dest_scan[index] = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
   2911             src_scan ++;
   2912         }
   2913         dest_scan += 4;
   2914         src_scan += src_gap;
   2915     }
   2916 }
   2917 inline void _CompositeRow_Argb2Rgb_Blend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int dest_Bpp, FX_LPCBYTE clip_scan)
   2918 {
   2919     int blended_colors[3];
   2920     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2921     for (int col = 0; col < width; col ++) {
   2922         FX_BYTE src_alpha;
   2923         if (clip_scan) {
   2924             src_alpha = src_scan[3] * (*clip_scan++) / 255;
   2925         } else {
   2926             src_alpha = src_scan[3];
   2927         }
   2928         if (src_alpha == 0) {
   2929             dest_scan += dest_Bpp;
   2930             src_scan += 4;
   2931             continue;
   2932         }
   2933         if (bNonseparableBlend) {
   2934             FX_BYTE dest_scan_o[3];
   2935             dest_scan_o[0] = dest_scan[2];
   2936             dest_scan_o[1] = dest_scan[1];
   2937             dest_scan_o[2] = dest_scan[0];
   2938             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2939         }
   2940         for (int color = 0; color < 3; color ++) {
   2941             int index = 2 - color;
   2942             int back_color = FX_GAMMA(dest_scan[index]);
   2943             int blended = bNonseparableBlend ? blended_colors[color] :
   2944                           _BLEND(blend_type, back_color, *src_scan);
   2945             dest_scan[index] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
   2946             src_scan ++;
   2947         }
   2948         dest_scan += dest_Bpp;
   2949         src_scan ++;
   2950     }
   2951 }
   2952 inline void _CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int src_Bpp)
   2953 {
   2954     int src_gap = src_Bpp - 3;
   2955     for (int col = 0; col < width; col ++) {
   2956         if (src_Bpp == 4) {
   2957             FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
   2958         } else {
   2959             FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
   2960         }
   2961         dest_scan += 4;
   2962         src_scan += src_Bpp;
   2963     }
   2964 }
   2965 inline void _CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int dest_Bpp, int src_Bpp)
   2966 {
   2967     int blended_colors[3];
   2968     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2969     int src_gap = src_Bpp - 3;
   2970     for (int col = 0; col < width; col ++) {
   2971         if (bNonseparableBlend) {
   2972             FX_BYTE dest_scan_o[3];
   2973             dest_scan_o[0] = dest_scan[2];
   2974             dest_scan_o[1] = dest_scan[1];
   2975             dest_scan_o[2] = dest_scan[0];
   2976             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2977         }
   2978         for (int color = 0; color < 3; color ++) {
   2979             int index = 2 - color;
   2980             int back_color = FX_GAMMA(dest_scan[index]);
   2981             int src_color = FX_GAMMA(*src_scan);
   2982             int blended = bNonseparableBlend ? blended_colors[color] :
   2983                           _BLEND(blend_type, back_color, src_color);
   2984             dest_scan[index] = FX_GAMMA_INVERSE(blended);
   2985             src_scan ++;
   2986         }
   2987         dest_scan += dest_Bpp;
   2988         src_scan += src_gap;
   2989     }
   2990 }
   2991 inline void _CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, FX_LPCBYTE clip_scan)
   2992 {
   2993     for (int col = 0; col < width; col ++) {
   2994         FX_BYTE src_alpha;
   2995         if (clip_scan) {
   2996             src_alpha = src_scan[3] * (*clip_scan++) / 255;
   2997         } else {
   2998             src_alpha = src_scan[3];
   2999         }
   3000         if (src_alpha == 255) {
   3001             dest_scan[2] = FX_GAMMA_INVERSE(*src_scan++);
   3002             dest_scan[1] = FX_GAMMA_INVERSE(*src_scan++);
   3003             dest_scan[0] = FX_GAMMA_INVERSE(*src_scan++);
   3004             dest_scan += dest_Bpp;
   3005             src_scan ++;
   3006             continue;
   3007         }
   3008         if (src_alpha == 0) {
   3009             dest_scan += dest_Bpp;
   3010             src_scan += 4;
   3011             continue;
   3012         }
   3013         for (int color = 0; color < 3; color ++) {
   3014             int index = 2 - color;
   3015             dest_scan[index] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[index]), *src_scan, src_alpha));
   3016             src_scan ++;
   3017         }
   3018         dest_scan += dest_Bpp;
   3019         src_scan ++;
   3020     }
   3021 }
   3022 inline void _CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, int src_Bpp)
   3023 {
   3024     for (int col = 0; col < width; col ++) {
   3025         dest_scan[2] = src_scan[0];
   3026         dest_scan[1] = src_scan[1];
   3027         dest_scan[0] = src_scan[2];
   3028         dest_scan += dest_Bpp;
   3029         src_scan += src_Bpp;
   3030     }
   3031 }
   3032 inline void _CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int src_Bpp, FX_LPCBYTE clip_scan)
   3033 {
   3034     int blended_colors[3];
   3035     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   3036     int src_gap = src_Bpp - 3;
   3037     for (int col = 0; col < width; col ++) {
   3038         int src_alpha = *clip_scan ++;
   3039         FX_BYTE back_alpha = dest_scan[3];
   3040         if (back_alpha == 0) {
   3041             dest_scan[2] = FX_GAMMA(*src_scan++);
   3042             dest_scan[1] = FX_GAMMA(*src_scan++);
   3043             dest_scan[0] = FX_GAMMA(*src_scan++);
   3044             src_scan += src_gap;
   3045             dest_scan += 4;
   3046             continue;
   3047         }
   3048         if (src_alpha == 0) {
   3049             dest_scan += 4;
   3050             src_scan += src_Bpp;
   3051             continue;
   3052         }
   3053         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3054         dest_scan[3] = dest_alpha;
   3055         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3056         if (bNonseparableBlend) {
   3057             FX_BYTE dest_scan_o[3];
   3058             dest_scan_o[0] = dest_scan[2];
   3059             dest_scan_o[1] = dest_scan[1];
   3060             dest_scan_o[2] = dest_scan[0];
   3061             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3062         }
   3063         for (int color = 0; color < 3; color ++) {
   3064             int index = 2 - color;
   3065             int src_color = FX_GAMMA(*src_scan);
   3066             int blended = bNonseparableBlend ? blended_colors[color] :
   3067                           _BLEND(blend_type, dest_scan[index], src_color);
   3068             blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
   3069             dest_scan[index] = FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
   3070             src_scan ++;
   3071         }
   3072         dest_scan += 4;
   3073         src_scan += src_gap;
   3074     }
   3075 }
   3076 inline void _CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int blend_type, int dest_Bpp, int src_Bpp, FX_LPCBYTE clip_scan)
   3077 {
   3078     int blended_colors[3];
   3079     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   3080     int src_gap = src_Bpp - 3;
   3081     for (int col = 0; col < width; col ++) {
   3082         FX_BYTE src_alpha = *clip_scan ++;
   3083         if (src_alpha == 0) {
   3084             dest_scan += dest_Bpp;
   3085             src_scan += src_Bpp;
   3086             continue;
   3087         }
   3088         if (bNonseparableBlend) {
   3089             FX_BYTE dest_scan_o[3];
   3090             dest_scan_o[0] = dest_scan[2];
   3091             dest_scan_o[1] = dest_scan[1];
   3092             dest_scan_o[2] = dest_scan[0];
   3093             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3094         }
   3095         for (int color = 0; color < 3; color ++) {
   3096             int index = 2 - color;
   3097             int src_color = FX_GAMMA(*src_scan);
   3098             int back_color = FX_GAMMA(dest_scan[index]);
   3099             int blended = bNonseparableBlend ? blended_colors[color] :
   3100                           _BLEND(blend_type, back_color, src_color);
   3101             dest_scan[index] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
   3102             src_scan ++;
   3103         }
   3104         dest_scan += dest_Bpp;
   3105         src_scan += src_gap;
   3106     }
   3107 }
   3108 inline void _CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int src_Bpp, FX_LPCBYTE clip_scan)
   3109 {
   3110     int src_gap = src_Bpp - 3;
   3111     for (int col = 0; col < width; col ++) {
   3112         int src_alpha = clip_scan[col];
   3113         if (src_alpha == 255) {
   3114             dest_scan[2] = FX_GAMMA(*src_scan++);
   3115             dest_scan[1] = FX_GAMMA(*src_scan++);
   3116             dest_scan[0] = FX_GAMMA(*src_scan++);
   3117             dest_scan[3] = 255;
   3118             dest_scan += 4;
   3119             src_scan  += src_gap;
   3120             continue;
   3121         }
   3122         if (src_alpha == 0) {
   3123             dest_scan += 4;
   3124             src_scan += src_Bpp;
   3125             continue;
   3126         }
   3127         int back_alpha = dest_scan[3];
   3128         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3129         dest_scan[3] = dest_alpha;
   3130         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3131         for (int color = 0; color < 3; color ++) {
   3132             int index = 2 - color;
   3133             dest_scan[index] = FXDIB_ALPHA_MERGE(dest_scan[index], FX_GAMMA(*src_scan), alpha_ratio);
   3134             src_scan ++;
   3135         }
   3136         dest_scan += 4;
   3137         src_scan += src_gap;
   3138     }
   3139 }
   3140 inline void _CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, int src_Bpp, FX_LPCBYTE clip_scan)
   3141 {
   3142     for (int col = 0; col < width; col ++) {
   3143         int src_alpha = clip_scan[col];
   3144         if (src_alpha == 255) {
   3145             dest_scan[2] = src_scan[0];
   3146             dest_scan[1] = src_scan[1];
   3147             dest_scan[0] = src_scan[2];
   3148         } else if (src_alpha) {
   3149             dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), FX_GAMMA(*src_scan), src_alpha));
   3150             src_scan ++;
   3151             dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), FX_GAMMA(*src_scan), src_alpha));
   3152             src_scan ++;
   3153             dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), FX_GAMMA(*src_scan), src_alpha));
   3154             dest_scan += dest_Bpp;
   3155             src_scan += src_Bpp - 2;
   3156             continue;
   3157         }
   3158         dest_scan += dest_Bpp;
   3159         src_scan += src_Bpp;
   3160     }
   3161 }
   3162 inline void _CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, FX_ARGB* pPalette, int pixel_count,
   3163         int DestBpp, FX_LPCBYTE clip_scan)
   3164 {
   3165     for (int col = 0; col < pixel_count; col ++) {
   3166         FX_ARGB argb = pPalette ? pPalette[*src_scan] : (*src_scan) * 0x010101;
   3167         int src_r = FXARGB_R(argb);
   3168         int src_g = FXARGB_G(argb);
   3169         int src_b = FXARGB_B(argb);
   3170         if (clip_scan && clip_scan[col] < 255) {
   3171             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
   3172             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
   3173             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
   3174         } else {
   3175             dest_scan[2] = src_b;
   3176             dest_scan[1] = src_g;
   3177             dest_scan[0] = src_r;
   3178         }
   3179         dest_scan += DestBpp;
   3180         src_scan ++;
   3181     }
   3182 }
   3183 inline void _CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left,
   3184         FX_ARGB* pPalette, int pixel_count, int DestBpp, FX_LPCBYTE clip_scan)
   3185 {
   3186     int reset_r, reset_g, reset_b;
   3187     int set_r, set_g, set_b;
   3188     if (pPalette) {
   3189         reset_r = FXARGB_R(pPalette[0]);
   3190         reset_g = FXARGB_G(pPalette[0]);
   3191         reset_b = FXARGB_B(pPalette[0]);
   3192         set_r = FXARGB_R(pPalette[1]);
   3193         set_g = FXARGB_G(pPalette[1]);
   3194         set_b = FXARGB_B(pPalette[1]);
   3195     } else {
   3196         reset_r = reset_g = reset_b = 0;
   3197         set_r = set_g = set_b = 255;
   3198     }
   3199     for (int col = 0; col < pixel_count; col ++) {
   3200         int src_r, src_g, src_b;
   3201         if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   3202             src_r = set_r;
   3203             src_g = set_g;
   3204             src_b = set_b;
   3205         } else {
   3206             src_r = reset_r;
   3207             src_g = reset_g;
   3208             src_b = reset_b;
   3209         }
   3210         if (clip_scan && clip_scan[col] < 255) {
   3211             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
   3212             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
   3213             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
   3214         } else {
   3215             dest_scan[2] = src_b;
   3216             dest_scan[1] = src_g;
   3217             dest_scan[0] = src_r;
   3218         }
   3219         dest_scan += DestBpp;
   3220     }
   3221 }
   3222 inline void _CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width,
   3223         FX_ARGB* pPalette, FX_LPCBYTE clip_scan)
   3224 {
   3225     for (int col = 0; col < width; col ++) {
   3226         int src_r, src_g, src_b;
   3227         if (pPalette) {
   3228             FX_ARGB argb = pPalette[*src_scan];
   3229             src_r = FXARGB_R(argb);
   3230             src_g = FXARGB_G(argb);
   3231             src_b = FXARGB_B(argb);
   3232         } else {
   3233             src_r = src_g = src_b = *src_scan;
   3234         }
   3235         if (clip_scan == NULL || clip_scan[col] == 255) {
   3236             dest_scan[2] = FX_GAMMA(src_b);
   3237             dest_scan[1] = FX_GAMMA(src_g);
   3238             dest_scan[0] = FX_GAMMA(src_r);
   3239             dest_scan[3] = 255;
   3240             src_scan ++;
   3241             dest_scan += 4;
   3242             continue;
   3243         }
   3244         int src_alpha = clip_scan[col];
   3245         if (src_alpha == 0) {
   3246             dest_scan += 4;
   3247             src_scan ++;
   3248             continue;
   3249         }
   3250         int back_alpha = dest_scan[3];
   3251         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3252         dest_scan[3] = dest_alpha;
   3253         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3254         dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], FX_GAMMA(src_b), alpha_ratio);
   3255         dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], FX_GAMMA(src_g), alpha_ratio);
   3256         dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], FX_GAMMA(src_r), alpha_ratio);
   3257         dest_scan += 4;
   3258         src_scan ++;
   3259     }
   3260 }
   3261 inline void _CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width,
   3262         FX_ARGB* pPalette, FX_LPCBYTE clip_scan)
   3263 {
   3264     int reset_r, reset_g, reset_b;
   3265     int set_r, set_g, set_b;
   3266     if (pPalette) {
   3267         reset_r = FXARGB_R(pPalette[0]);
   3268         reset_g = FXARGB_G(pPalette[0]);
   3269         reset_b = FXARGB_B(pPalette[0]);
   3270         set_r = FXARGB_R(pPalette[1]);
   3271         set_g = FXARGB_G(pPalette[1]);
   3272         set_b = FXARGB_B(pPalette[1]);
   3273     } else {
   3274         reset_r = reset_g = reset_b = 0;
   3275         set_r = set_g = set_b = 255;
   3276     }
   3277     for (int col = 0; col < width; col ++) {
   3278         int src_r, src_g, src_b;
   3279         if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   3280             src_r = set_r;
   3281             src_g = set_g;
   3282             src_b = set_b;
   3283         } else {
   3284             src_r = reset_r;
   3285             src_g = reset_g;
   3286             src_b = reset_b;
   3287         }
   3288         if (clip_scan == NULL || clip_scan[col] == 255) {
   3289             dest_scan[2] = FX_GAMMA(src_b);
   3290             dest_scan[1] = FX_GAMMA(src_g);
   3291             dest_scan[0] = FX_GAMMA(src_r);
   3292             dest_scan[3] = 255;
   3293             dest_scan += 4;
   3294             continue;
   3295         }
   3296         int src_alpha = clip_scan[col];
   3297         if (src_alpha == 0) {
   3298             dest_scan += 4;
   3299             continue;
   3300         }
   3301         int back_alpha = dest_scan[3];
   3302         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3303         dest_scan[3] = dest_alpha;
   3304         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3305         dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], FX_GAMMA(src_b), alpha_ratio);
   3306         dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], FX_GAMMA(src_g), alpha_ratio);
   3307         dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], FX_GAMMA(src_r), alpha_ratio);
   3308         dest_scan += 4;
   3309     }
   3310 }
   3311 void _CompositeRow_ByteMask2Argb_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b, int pixel_count,
   3312         int blend_type, FX_LPCBYTE clip_scan)
   3313 {
   3314     for (int col = 0; col < pixel_count; col ++) {
   3315         int src_alpha;
   3316         if (clip_scan) {
   3317             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   3318         } else {
   3319             src_alpha = mask_alpha * src_scan[col] / 255;
   3320         }
   3321         FX_BYTE back_alpha = dest_scan[3];
   3322         if (back_alpha == 0) {
   3323             FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   3324             dest_scan += 4;
   3325             continue;
   3326         }
   3327         if (src_alpha == 0) {
   3328             dest_scan += 4;
   3329             continue;
   3330         }
   3331         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3332         dest_scan[3] = dest_alpha;
   3333         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3334         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   3335             int blended_colors[3];
   3336             FX_BYTE src_scan[3];
   3337             FX_BYTE dest_scan_o[3];
   3338             src_scan[0] = src_b;
   3339             src_scan[1] = src_g;
   3340             src_scan[2] = src_r;
   3341             dest_scan_o[0] = dest_scan[2];
   3342             dest_scan_o[1] = dest_scan[1];
   3343             dest_scan_o[2] = dest_scan[0];
   3344             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3345             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
   3346             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
   3347             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
   3348         } else if (blend_type) {
   3349             int blended = _BLEND(blend_type, dest_scan[2], src_b);
   3350             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   3351             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
   3352             blended = _BLEND(blend_type, dest_scan[1], src_g);
   3353             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   3354             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
   3355             blended = _BLEND(blend_type, dest_scan[0], src_r);
   3356             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   3357             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
   3358         } else {
   3359             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
   3360             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
   3361             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
   3362         }
   3363         dest_scan += 4;
   3364     }
   3365 }
   3366 void _CompositeRow_ByteMask2Rgb_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b, int pixel_count,
   3367         int blend_type, int Bpp, FX_LPCBYTE clip_scan)
   3368 {
   3369     for (int col = 0; col < pixel_count; col ++) {
   3370         int src_alpha;
   3371         if (clip_scan) {
   3372             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   3373         } else {
   3374             src_alpha = mask_alpha * src_scan[col] / 255;
   3375         }
   3376         if (src_alpha == 0) {
   3377             dest_scan += Bpp;
   3378             continue;
   3379         }
   3380         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   3381             int blended_colors[3];
   3382             FX_BYTE src_scan[3];
   3383             FX_BYTE dest_scan_o[3];
   3384             src_scan[0] = src_b;
   3385             src_scan[1] = src_g;
   3386             src_scan[2] = src_r;
   3387             dest_scan_o[0] = dest_scan[2];
   3388             dest_scan_o[1] = dest_scan[1];
   3389             dest_scan_o[2] = dest_scan[0];
   3390             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3391             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
   3392             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
   3393             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
   3394         } else if (blend_type) {
   3395             int blended = _BLEND(blend_type, dest_scan[2], src_b);
   3396             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha);
   3397             blended = _BLEND(blend_type, dest_scan[1], src_g);
   3398             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha);
   3399             blended = _BLEND(blend_type, dest_scan[0], src_r);
   3400             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha);
   3401         } else {
   3402             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha);
   3403             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha);
   3404             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha);
   3405         }
   3406         dest_scan += Bpp;
   3407     }
   3408 }
   3409 void _CompositeRow_BitMask2Argb_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b,
   3410         int src_left, int pixel_count, int blend_type, FX_LPCBYTE clip_scan)
   3411 {
   3412     if (blend_type == FXDIB_BLEND_NORMAL && clip_scan == NULL && mask_alpha == 255) {
   3413         FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b);
   3414         for (int col = 0; col < pixel_count; col ++) {
   3415             if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   3416                 FXARGB_SETRGBORDERDIB(dest_scan, argb);
   3417             }
   3418             dest_scan += 4;
   3419         }
   3420         return;
   3421     }
   3422     for (int col = 0; col < pixel_count; col ++) {
   3423         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   3424             dest_scan += 4;
   3425             continue;
   3426         }
   3427         int src_alpha;
   3428         if (clip_scan) {
   3429             src_alpha = mask_alpha * clip_scan[col] / 255;
   3430         } else {
   3431             src_alpha = mask_alpha;
   3432         }
   3433         FX_BYTE back_alpha = dest_scan[3];
   3434         if (back_alpha == 0) {
   3435             FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   3436             dest_scan += 4;
   3437             continue;
   3438         }
   3439         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3440         dest_scan[3] = dest_alpha;
   3441         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3442         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   3443             int blended_colors[3];
   3444             FX_BYTE src_scan[3];
   3445             FX_BYTE dest_scan_o[3];
   3446             src_scan[0] = src_b;
   3447             src_scan[1] = src_g;
   3448             src_scan[2] = src_r;
   3449             dest_scan_o[0] = dest_scan[2];
   3450             dest_scan_o[1] = dest_scan[1];
   3451             dest_scan_o[2] = dest_scan[0];
   3452             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3453             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
   3454             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
   3455             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
   3456         } else if (blend_type) {
   3457             int blended = _BLEND(blend_type, dest_scan[2], src_b);
   3458             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   3459             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
   3460             blended = _BLEND(blend_type, dest_scan[1], src_g);
   3461             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   3462             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
   3463             blended = _BLEND(blend_type, dest_scan[0], src_r);
   3464             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   3465             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
   3466         } else {
   3467             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
   3468             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
   3469             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
   3470         }
   3471         dest_scan += 4;
   3472     }
   3473 }
   3474 void _CompositeRow_BitMask2Rgb_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b,
   3475         int src_left, int pixel_count, int blend_type, int Bpp, FX_LPCBYTE clip_scan)
   3476 {
   3477     if (blend_type == FXDIB_BLEND_NORMAL && clip_scan == NULL && mask_alpha == 255) {
   3478         for (int col = 0; col < pixel_count; col ++) {
   3479             if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   3480                 dest_scan[2] = src_b;
   3481                 dest_scan[1] = src_g;
   3482                 dest_scan[0] = src_r;
   3483             }
   3484             dest_scan += Bpp;
   3485         }
   3486         return;
   3487     }
   3488     for (int col = 0; col < pixel_count; col ++) {
   3489         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   3490             dest_scan += Bpp;
   3491             continue;
   3492         }
   3493         int src_alpha;
   3494         if (clip_scan) {
   3495             src_alpha = mask_alpha * clip_scan[col] / 255;
   3496         } else {
   3497             src_alpha = mask_alpha;
   3498         }
   3499         if (src_alpha == 0) {
   3500             dest_scan += Bpp;
   3501             continue;
   3502         }
   3503         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   3504             int blended_colors[3];
   3505             FX_BYTE src_scan[3];
   3506             FX_BYTE dest_scan_o[3];
   3507             src_scan[0] = src_b;
   3508             src_scan[1] = src_g;
   3509             src_scan[2] = src_r;
   3510             dest_scan_o[0] = dest_scan[2];
   3511             dest_scan_o[1] = dest_scan[1];
   3512             dest_scan_o[2] = dest_scan[0];
   3513             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3514             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
   3515             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
   3516             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
   3517         } else if (blend_type) {
   3518             int back_color = FX_GAMMA(dest_scan[2]);
   3519             int blended = _BLEND(blend_type, back_color, src_b);
   3520             dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
   3521             back_color = FX_GAMMA(dest_scan[1]);
   3522             blended = _BLEND(blend_type, back_color, src_g);
   3523             dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
   3524             back_color = FX_GAMMA(dest_scan[0]);
   3525             blended = _BLEND(blend_type, back_color, src_r);
   3526             dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
   3527         } else {
   3528             dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), src_b, src_alpha));
   3529             dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), src_g, src_alpha));
   3530             dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), src_r, src_alpha));
   3531         }
   3532         dest_scan += Bpp;
   3533     }
   3534 }
   3535 inline FX_BOOL _ScanlineCompositor_InitSourceMask(FXDIB_Format dest_format, int alpha_flag, FX_DWORD mask_color, int& mask_alpha,
   3536         int& mask_red, int& mask_green, int& mask_blue, int& mask_black,
   3537         void* icc_module, void* pIccTransform)
   3538 {
   3539     ICodec_IccModule* pIccModule = (ICodec_IccModule*)icc_module;
   3540     if (alpha_flag >> 8) {
   3541         mask_alpha = alpha_flag & 0xff;
   3542         mask_red = FXSYS_GetCValue(mask_color);
   3543         mask_green = FXSYS_GetMValue(mask_color);
   3544         mask_blue = FXSYS_GetYValue(mask_color);
   3545         mask_black = FXSYS_GetKValue(mask_color);
   3546     } else {
   3547         mask_alpha = FXARGB_A(mask_color);
   3548         mask_red = FXARGB_R(mask_color);
   3549         mask_green = FXARGB_G(mask_color);
   3550         mask_blue = FXARGB_B(mask_color);
   3551     }
   3552     if (dest_format == FXDIB_8bppMask) {
   3553         return TRUE;
   3554     }
   3555     if ((dest_format & 0xff) == 8) {
   3556         if (pIccTransform) {
   3557             mask_color = (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color);
   3558             FX_LPBYTE gray_p = (FX_LPBYTE)&mask_color;
   3559             pIccModule->TranslateScanline(pIccTransform, gray_p, gray_p, 1);
   3560             mask_red = dest_format & 0x0400 ? FX_CCOLOR(gray_p[0]) : gray_p[0];
   3561         } else {
   3562             if (alpha_flag >> 8) {
   3563                 FX_BYTE r, g, b;
   3564                 AdobeCMYK_to_sRGB1(mask_red, mask_green, mask_blue, mask_black,
   3565                                    r, g, b);
   3566                 mask_red = FXRGB2GRAY(r, g, b);
   3567             } else {
   3568                 mask_red = FXRGB2GRAY(mask_red, mask_green, mask_blue);
   3569             }
   3570             if (dest_format & 0x0400) {
   3571                 mask_red = FX_CCOLOR(mask_red);
   3572             }
   3573         }
   3574     } else {
   3575         FX_LPBYTE mask_color_p = (FX_LPBYTE)&mask_color;
   3576         mask_color = (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color);
   3577         if (pIccTransform) {
   3578             pIccModule->TranslateScanline(pIccTransform, mask_color_p, mask_color_p, 1);
   3579             mask_red = mask_color_p[2];
   3580             mask_green = mask_color_p[1];
   3581             mask_blue = mask_color_p[0];
   3582         } else if (alpha_flag >> 8) {
   3583             AdobeCMYK_to_sRGB1(mask_color_p[0], mask_color_p[1], mask_color_p[2], mask_color_p[3],
   3584                                mask_color_p[2], mask_color_p[1], mask_color_p[0]);
   3585             mask_red = mask_color_p[2];
   3586             mask_green = mask_color_p[1];
   3587             mask_blue = mask_color_p[0];
   3588         }
   3589     }
   3590     return TRUE;
   3591 }
   3592 inline void _ScanlineCompositor_InitSourcePalette(FXDIB_Format src_format, FXDIB_Format dest_format,
   3593         FX_DWORD*& pDestPalette, FX_DWORD* pSrcPalette,
   3594         void* icc_module, void* pIccTransform)
   3595 {
   3596     ICodec_IccModule* pIccModule = (ICodec_IccModule*)icc_module;
   3597     FX_BOOL isSrcCmyk = src_format & 0x0400 ? TRUE : FALSE;
   3598     FX_BOOL isDstCmyk = dest_format & 0x0400 ? TRUE : FALSE;
   3599     pDestPalette = NULL;
   3600     if (pIccTransform) {
   3601         if (pSrcPalette) {
   3602             if ((dest_format & 0xff) == 8) {
   3603                 int pal_count = 1 << (src_format & 0xff);
   3604                 FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
   3605                 if (!gray_pal) {
   3606                     return;
   3607                 }
   3608                 pDestPalette = (FX_DWORD*)gray_pal;
   3609                 for (int i = 0; i < pal_count; i ++) {
   3610                     FX_DWORD color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) : FXARGB_TODIB(pSrcPalette[i]);
   3611                     pIccModule->TranslateScanline(pIccTransform, gray_pal, (FX_LPCBYTE)&color, 1);
   3612                     gray_pal ++;
   3613                 }
   3614             } else {
   3615                 int palsize = 1 << (src_format & 0xff);
   3616                 pDestPalette = FX_Alloc(FX_DWORD, palsize);
   3617                 if (!pDestPalette) {
   3618                     return;
   3619                 }
   3620                 for (int i = 0; i < palsize; i ++) {
   3621                     FX_DWORD color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) : FXARGB_TODIB(pSrcPalette[i]);
   3622                     pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&color, (FX_LPCBYTE)&color, 1);
   3623                     pDestPalette[i] = isDstCmyk ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
   3624                 }
   3625             }
   3626         } else {
   3627             int pal_count = 1 << (src_format & 0xff);
   3628             FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
   3629             if (!gray_pal) {
   3630                 return;
   3631             }
   3632             if (pal_count == 2) {
   3633                 gray_pal[0] = 0;
   3634                 gray_pal[1] = 255;
   3635             } else {
   3636                 for (int i = 0; i < pal_count; i++) {
   3637                     gray_pal[i] = i;
   3638                 }
   3639             }
   3640             if ((dest_format & 0xff) == 8) {
   3641                 pIccModule->TranslateScanline(pIccTransform, gray_pal, gray_pal, pal_count);
   3642                 pDestPalette = (FX_DWORD*)gray_pal;
   3643             } else {
   3644                 pDestPalette = FX_Alloc(FX_DWORD, pal_count);
   3645                 if (!pDestPalette) {
   3646                     FX_Free(gray_pal);
   3647                     return;
   3648                 }
   3649                 for (int i = 0; i < pal_count; i ++) {
   3650                     pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&pDestPalette[i], &gray_pal[i], 1);
   3651                     pDestPalette[i] = isDstCmyk ? FXCMYK_TODIB(pDestPalette[i]) : FXARGB_TODIB(pDestPalette[i]);
   3652                 }
   3653                 FX_Free(gray_pal);
   3654             }
   3655         }
   3656     } else {
   3657         if (pSrcPalette) {
   3658             if ((dest_format & 0xff) == 8) {
   3659                 int pal_count = 1 << (src_format & 0xff);
   3660                 FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
   3661                 if (!gray_pal) {
   3662                     return;
   3663                 }
   3664                 pDestPalette = (FX_DWORD*)gray_pal;
   3665                 if (isSrcCmyk) {
   3666                     for (int i = 0; i < pal_count; i ++) {
   3667                         FX_CMYK cmyk = pSrcPalette[i];
   3668                         FX_BYTE r, g, b;
   3669                         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
   3670                                            r, g, b);
   3671                         *gray_pal ++ = FXRGB2GRAY(r, g, b);
   3672                     }
   3673                 } else
   3674                     for (int i = 0; i < pal_count; i ++) {
   3675                         FX_ARGB argb = pSrcPalette[i];
   3676                         *gray_pal ++ = FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
   3677                     }
   3678             } else {
   3679                 int palsize = 1 << (src_format & 0xff);
   3680                 pDestPalette = FX_Alloc(FX_DWORD, palsize);
   3681                 if (!pDestPalette) {
   3682                     return;
   3683                 }
   3684                 if (isDstCmyk == isSrcCmyk) {
   3685                     FXSYS_memcpy32(pDestPalette, pSrcPalette, palsize * sizeof(FX_DWORD));
   3686                 } else {
   3687                     for (int i = 0; i < palsize; i ++) {
   3688                         FX_CMYK cmyk = pSrcPalette[i];
   3689                         FX_BYTE r, g, b;
   3690                         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
   3691                                            r, g, b);
   3692                         pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b);
   3693                     }
   3694                 }
   3695             }
   3696         } else {
   3697             if ((dest_format & 0xff) == 8) {
   3698                 int pal_count = 1 << (src_format & 0xff);
   3699                 FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
   3700                 if (!gray_pal) {
   3701                     return;
   3702                 }
   3703                 if (pal_count == 2) {
   3704                     gray_pal[0] = 0;
   3705                     gray_pal[1] = 255;
   3706                 } else {
   3707                     for (int i = 0; i < pal_count; i++) {
   3708                         gray_pal[i] = i;
   3709                     }
   3710                 }
   3711                 pDestPalette = (FX_DWORD*)gray_pal;
   3712             } else {
   3713                 int palsize = 1 << (src_format & 0xff);
   3714                 pDestPalette = FX_Alloc(FX_DWORD, palsize);
   3715                 if (!pDestPalette) {
   3716                     return;
   3717                 }
   3718                 if (palsize == 2) {
   3719                     pDestPalette[0] = isSrcCmyk ? 255 : 0xff000000;
   3720                     pDestPalette[1] = isSrcCmyk ? 0 : 0xffffffff;
   3721                 } else {
   3722                     for (int i = 0; i < palsize; i++) {
   3723                         pDestPalette[i] = isSrcCmyk ? FX_CCOLOR(i) : (i * 0x10101);
   3724                     }
   3725                 }
   3726                 if (isSrcCmyk != isDstCmyk) {
   3727                     for (int i = 0; i < palsize; i ++) {
   3728                         FX_CMYK cmyk = pDestPalette[i];
   3729                         FX_BYTE r, g, b;
   3730                         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
   3731                                            r, g, b);
   3732                         pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b);
   3733                     }
   3734                 }
   3735             }
   3736         }
   3737     }
   3738 }
   3739 CFX_ScanlineCompositor::CFX_ScanlineCompositor()
   3740 {
   3741     m_pSrcPalette = NULL;
   3742     m_pCacheScanline = NULL;
   3743     m_CacheSize = 0;
   3744     m_bRgbByteOrder = FALSE;
   3745     m_BlendType = FXDIB_BLEND_NORMAL;
   3746 }
   3747 CFX_ScanlineCompositor::~CFX_ScanlineCompositor()
   3748 {
   3749     if (m_pSrcPalette) {
   3750         FX_Free(m_pSrcPalette);
   3751     }
   3752     if (m_pCacheScanline) {
   3753         FX_Free(m_pCacheScanline);
   3754     }
   3755 }
   3756 FX_BOOL CFX_ScanlineCompositor::Init(FXDIB_Format dest_format, FXDIB_Format src_format, FX_INT32 width, FX_DWORD* pSrcPalette,
   3757                                      FX_DWORD mask_color, int blend_type, FX_BOOL bClip, FX_BOOL bRgbByteOrder, int alpha_flag, void* pIccTransform)
   3758 {
   3759     m_SrcFormat = src_format;
   3760     m_DestFormat = dest_format;
   3761     m_BlendType = blend_type;
   3762     m_bRgbByteOrder = bRgbByteOrder;
   3763     ICodec_IccModule* pIccModule = NULL;
   3764     if (CFX_GEModule::Get()->GetCodecModule()) {
   3765         pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   3766     }
   3767     if (pIccModule == NULL) {
   3768         pIccTransform = NULL;
   3769     }
   3770     m_pIccTransform = pIccTransform;
   3771     if ((dest_format & 0xff) == 1) {
   3772         return FALSE;
   3773     }
   3774     if (m_SrcFormat == FXDIB_1bppMask || m_SrcFormat == FXDIB_8bppMask) {
   3775         return _ScanlineCompositor_InitSourceMask(dest_format, alpha_flag, mask_color,
   3776                 m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, m_MaskBlack,
   3777                 pIccModule, pIccTransform);
   3778     }
   3779     if (pIccTransform == NULL && (~src_format & 0x0400) && (dest_format & 0x0400)) {
   3780         return FALSE;
   3781     }
   3782     if ((m_SrcFormat & 0xff) <= 8) {
   3783         if (dest_format == FXDIB_8bppMask) {
   3784             return TRUE;
   3785         }
   3786         _ScanlineCompositor_InitSourcePalette(src_format, dest_format, m_pSrcPalette, pSrcPalette,
   3787                                               pIccModule, pIccTransform);
   3788         m_Transparency = (dest_format == FXDIB_Argb ? 1 : 0)
   3789                          + (dest_format & 0x0200 ? 2 : 0)
   3790                          + (dest_format & 0x0400 ? 4 : 0)
   3791                          + ((src_format & 0xff) == 1 ? 8 : 0);
   3792         return TRUE;
   3793     }
   3794     m_Transparency = (src_format & 0x0200 ? 0 : 1)
   3795                      + (dest_format & 0x0200 ? 0 : 2)
   3796                      + (blend_type == FXDIB_BLEND_NORMAL ? 4 : 0)
   3797                      + (bClip ? 8 : 0)
   3798                      + (src_format & 0x0400 ? 16 : 0)
   3799                      + (dest_format & 0x0400 ? 32 : 0)
   3800                      + (pIccTransform ? 64 : 0);
   3801     return TRUE;
   3802 }
   3803 void CFX_ScanlineCompositor::CompositeRgbBitmapLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, FX_LPCBYTE clip_scan,
   3804         FX_LPCBYTE src_extra_alpha, FX_LPBYTE dst_extra_alpha)
   3805 {
   3806     int src_Bpp = (m_SrcFormat & 0xff) >> 3;
   3807     int dest_Bpp = (m_DestFormat & 0xff) >> 3;
   3808     int dest_Size = width * dest_Bpp + 4;
   3809     if (m_bRgbByteOrder) {
   3810         switch (m_Transparency) {
   3811             case 0:
   3812             case 4:
   3813             case 8:
   3814             case 12:
   3815                 _CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, clip_scan);
   3816                 break;
   3817             case 1:
   3818                 _CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, src_Bpp);
   3819                 break;
   3820             case 2:
   3821             case 10:
   3822                 _CompositeRow_Argb2Rgb_Blend_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan);
   3823                 break;
   3824             case 3:
   3825                 _CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp);
   3826                 break;
   3827             case 5:
   3828                 _CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, width, src_Bpp);
   3829                 break;
   3830             case 6:
   3831             case 14:
   3832                 _CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, dest_Bpp, clip_scan);
   3833                 break;
   3834             case 7:
   3835                 _CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, width, dest_Bpp, src_Bpp);
   3836                 break;
   3837             case 9:
   3838                 _CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan);
   3839                 break;
   3840             case 11:
   3841                 _CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, clip_scan);
   3842                 break;
   3843             case 13:
   3844                 _CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(dest_scan, src_scan, width, src_Bpp, clip_scan);
   3845                 break;
   3846             case 15:
   3847                 _CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan);
   3848                 break;
   3849         }
   3850         return;
   3851     }
   3852     if (m_DestFormat == FXDIB_8bppMask) {
   3853         if (m_SrcFormat & 0x0200) {
   3854             if (m_SrcFormat == FXDIB_Argb) {
   3855                 _CompositeRow_Argb2Mask(dest_scan, src_scan, width, clip_scan);
   3856             } else {
   3857                 _CompositeRow_Rgba2Mask(dest_scan, src_extra_alpha, width, clip_scan);
   3858             }
   3859         } else {
   3860             _CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
   3861         }
   3862     } else if ((m_DestFormat & 0xff) == 8) {
   3863         if (m_DestFormat & 0x0400) {
   3864             for (int i = 0; i < width; i ++) {
   3865                 *dest_scan = ~*dest_scan;
   3866                 dest_scan++;
   3867             }
   3868         }
   3869         if (m_SrcFormat & 0x0200) {
   3870             if (m_DestFormat & 0x0200) {
   3871                 _CompositeRow_Argb2Graya(dest_scan, src_scan, width, m_BlendType, clip_scan, src_extra_alpha, dst_extra_alpha, m_pIccTransform);
   3872             } else {
   3873                 _CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType, clip_scan, src_extra_alpha, m_pIccTransform);
   3874             }
   3875         } else {
   3876             if (m_DestFormat & 0x0200) {
   3877                 _CompositeRow_Rgb2Graya(dest_scan, src_scan, src_Bpp, width, m_BlendType, clip_scan, dst_extra_alpha, m_pIccTransform);
   3878             } else {
   3879                 _CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType, clip_scan, m_pIccTransform);
   3880             }
   3881         }
   3882         if (m_DestFormat & 0x0400) {
   3883             for (int i = 0; i < width; i ++) {
   3884                 *dest_scan = ~*dest_scan;
   3885                 dest_scan++;
   3886             }
   3887         }
   3888     } else {
   3889         if (dest_Size > m_CacheSize) {
   3890             m_pCacheScanline = FX_Realloc(FX_BYTE, m_pCacheScanline, dest_Size);
   3891             if (!m_pCacheScanline) {
   3892                 return;
   3893             }
   3894             m_CacheSize = dest_Size;
   3895         }
   3896         switch (m_Transparency) {
   3897             case 0:
   3898             case 4:
   3899             case 8:
   3900             case 4+8: {
   3901                     _CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType, clip_scan,
   3902                                             dst_extra_alpha, src_extra_alpha);
   3903                 }
   3904                 break;
   3905             case 64:
   3906             case 4+64:
   3907             case 8+64:
   3908             case 4+8+64: {
   3909                     _CompositeRow_Argb2Argb_Transform(dest_scan, src_scan, width, m_BlendType, clip_scan,
   3910                                                       dst_extra_alpha, src_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3911                 }
   3912                 break;
   3913             case 1:
   3914                 _CompositeRow_Rgb2Argb_Blend_NoClip(dest_scan, src_scan, width, m_BlendType, src_Bpp,
   3915                                                     dst_extra_alpha);
   3916                 break;
   3917             case 1+64:
   3918                 _CompositeRow_Rgb2Argb_Blend_NoClip_Transform(dest_scan, src_scan, width, m_BlendType, src_Bpp,
   3919                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3920                 break;
   3921             case 1+8:
   3922                 _CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan,
   3923                                                   dst_extra_alpha);
   3924                 break;
   3925             case 1+8+64:
   3926                 _CompositeRow_Rgb2Argb_Blend_Clip_Transform(dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan,
   3927                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3928                 break;
   3929             case 1+4:
   3930                 _CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width, src_Bpp,
   3931                                                       dst_extra_alpha);
   3932                 break;
   3933             case 1+4+64:
   3934                 _CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform(dest_scan, src_scan, width, src_Bpp,
   3935                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3936                 break;
   3937             case 1+4+8:
   3938                 _CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp, clip_scan,
   3939                                                     dst_extra_alpha);
   3940                 break;
   3941             case 1+4+8+64:
   3942                 _CompositeRow_Rgb2Argb_NoBlend_Clip_Transform(dest_scan, src_scan, width, src_Bpp, clip_scan,
   3943                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3944                 break;
   3945             case 2:
   3946             case 2+8:
   3947                 _CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan,
   3948                                              src_extra_alpha);
   3949                 break;
   3950             case 2+64:
   3951             case 2+8+64:
   3952                 _CompositeRow_Argb2Rgb_Blend_Transform(dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan,
   3953                                                        src_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3954                 break;
   3955             case 2+4:
   3956             case 2+4+8:
   3957                 _CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp, clip_scan,
   3958                                                src_extra_alpha);
   3959                 break;
   3960             case 2+4+64:
   3961             case 2+4+8+64:
   3962                 _CompositeRow_Argb2Rgb_NoBlend_Transform(dest_scan, src_scan, width, dest_Bpp, clip_scan,
   3963                         src_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3964                 break;
   3965             case 1+2:
   3966                 _CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp);
   3967                 break;
   3968             case 1+2+64:
   3969                 _CompositeRow_Rgb2Rgb_Blend_NoClip_Transform(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp,
   3970                         m_pCacheScanline, m_pIccTransform);
   3971                 break;
   3972             case 1+2+8:
   3973                 _CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, clip_scan);
   3974                 break;
   3975             case 1+2+8+64:
   3976                 _CompositeRow_Rgb2Rgb_Blend_Clip_Transform(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, clip_scan,
   3977                         m_pCacheScanline, m_pIccTransform);
   3978                 break;
   3979             case 1+2+4:
   3980                 _CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width, dest_Bpp, src_Bpp);
   3981                 break;
   3982             case 1+2+4+64:
   3983                 _CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform(dest_scan, src_scan, width, dest_Bpp, src_Bpp,
   3984                         m_pCacheScanline, m_pIccTransform);
   3985                 break;
   3986             case 1+2+4+8:
   3987                 _CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan);
   3988                 break;
   3989             case 1+2+4+8+64:
   3990                 _CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform(dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan,
   3991                         m_pCacheScanline, m_pIccTransform);
   3992                 break;
   3993         }
   3994     }
   3995 }
   3996 void CFX_ScanlineCompositor::CompositePalBitmapLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width, FX_LPCBYTE clip_scan,
   3997         FX_LPCBYTE src_extra_alpha, FX_LPBYTE dst_extra_alpha)
   3998 {
   3999     if (m_bRgbByteOrder) {
   4000         if (m_SrcFormat == FXDIB_1bppRgb) {
   4001             if (m_DestFormat == FXDIB_8bppRgb) {
   4002                 return;
   4003             } else if(m_DestFormat == FXDIB_Argb) {
   4004                 _CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan);
   4005             } else {
   4006                 _CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, src_left, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan);
   4007             }
   4008         } else {
   4009             if (m_DestFormat == FXDIB_8bppRgb) {
   4010                 return;
   4011             } else if (m_DestFormat == FXDIB_Argb) {
   4012                 _CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, m_pSrcPalette, clip_scan);
   4013             } else {
   4014                 _CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan);
   4015             }
   4016         }
   4017         return;
   4018     }
   4019     if (m_DestFormat == FXDIB_8bppMask) {
   4020         _CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
   4021         return;
   4022     } else if ((m_DestFormat & 0xff) == 8) {
   4023         if (m_Transparency & 8) {
   4024             if (m_DestFormat & 0x0200) {
   4025                 _CompositeRow_1bppPal2Graya(dest_scan, src_scan, src_left, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan, dst_extra_alpha);
   4026             } else {
   4027                 _CompositeRow_1bppPal2Gray(dest_scan, src_scan, src_left, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan);
   4028             }
   4029         } else {
   4030             if (m_DestFormat & 0x0200)
   4031                 _CompositeRow_8bppPal2Graya(dest_scan, src_scan, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan,
   4032                                             dst_extra_alpha, src_extra_alpha);
   4033             else
   4034                 _CompositeRow_8bppPal2Gray(dest_scan, src_scan, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan,
   4035                                            src_extra_alpha);
   4036         }
   4037     } else {
   4038         switch (m_Transparency) {
   4039             case 1+2:
   4040                 _CompositeRow_8bppRgb2Argb_NoBlend(dest_scan, src_scan, width, m_pSrcPalette, clip_scan,
   4041                                                    src_extra_alpha);
   4042                 break;
   4043             case 1+2+8:
   4044                 _CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan);
   4045                 break;
   4046             case 0:
   4047                 _CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan,
   4048                                                   src_extra_alpha);
   4049                 break;
   4050             case 0+8:
   4051                 _CompositeRow_1bppRgb2Rgb_NoBlend(dest_scan, src_scan, src_left, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan);
   4052                 break;
   4053             case 0+2:
   4054                 _CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan,
   4055                                                   src_extra_alpha);
   4056                 break;
   4057             case 0+2+8:
   4058                 _CompositeRow_1bppRgb2Rgba_NoBlend(dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan,
   4059                                                    dst_extra_alpha);
   4060                 break;
   4061                 break;
   4062         }
   4063     }
   4064 }
   4065 void CFX_ScanlineCompositor::CompositeByteMaskLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, FX_LPCBYTE clip_scan,
   4066         FX_LPBYTE dst_extra_alpha)
   4067 {
   4068     if (m_DestFormat == FXDIB_8bppMask) {
   4069         _CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width, clip_scan);
   4070     } else if ((m_DestFormat & 0xff) == 8) {
   4071         if (m_DestFormat & 0x0200) {
   4072             _CompositeRow_ByteMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, width, clip_scan, dst_extra_alpha);
   4073         } else {
   4074             _CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, width, clip_scan);
   4075         }
   4076     } else if (m_bRgbByteOrder) {
   4077         if (m_DestFormat == FXDIB_Argb)
   4078             _CompositeRow_ByteMask2Argb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4079                     width, m_BlendType, clip_scan);
   4080         else
   4081             _CompositeRow_ByteMask2Rgb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4082                                                     width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   4083         return;
   4084     } else if (m_DestFormat == FXDIB_Argb)
   4085         _CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4086                                     width, m_BlendType, clip_scan);
   4087     else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32)
   4088         _CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4089                                    width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   4090     else if (m_DestFormat == FXDIB_Rgba)
   4091         _CompositeRow_ByteMask2Rgba(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4092                                     width, m_BlendType, clip_scan, dst_extra_alpha);
   4093 }
   4094 void CFX_ScanlineCompositor::CompositeBitMaskLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width, FX_LPCBYTE clip_scan,
   4095         FX_LPBYTE dst_extra_alpha)
   4096 {
   4097     if (m_DestFormat == FXDIB_8bppMask) {
   4098         _CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left, width, clip_scan);
   4099     } else if ((m_DestFormat & 0xff) == 8) {
   4100         if (m_DestFormat & 0x0200)
   4101             _CompositeRow_BitMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, src_left, width, clip_scan,
   4102                                         dst_extra_alpha);
   4103         else {
   4104             _CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, src_left, width, clip_scan);
   4105         }
   4106     } else if (m_bRgbByteOrder) {
   4107         if (m_DestFormat == FXDIB_Argb)
   4108             _CompositeRow_BitMask2Argb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4109                                                     src_left, width, m_BlendType, clip_scan);
   4110         else
   4111             _CompositeRow_BitMask2Rgb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4112                                                    src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   4113         return;
   4114     } else if (m_DestFormat == FXDIB_Argb)
   4115         _CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4116                                    src_left, width, m_BlendType, clip_scan);
   4117     else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32)
   4118         _CompositeRow_BitMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4119                                   src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   4120 }
   4121 FX_BOOL CFX_DIBitmap::CompositeBitmap(int dest_left, int dest_top, int width, int height,
   4122                                       const CFX_DIBSource* pSrcBitmap, int src_left, int src_top,
   4123                                       int blend_type, const CFX_ClipRgn* pClipRgn, FX_BOOL bRgbByteOrder, void* pIccTransform)
   4124 {
   4125     if (m_pBuffer == NULL) {
   4126         return FALSE;
   4127     }
   4128     ASSERT(!pSrcBitmap->IsAlphaMask());
   4129     ASSERT(m_bpp >= 8);
   4130     if (pSrcBitmap->IsAlphaMask() || m_bpp < 8) {
   4131         return FALSE;
   4132     }
   4133     GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(),
   4134                    src_left, src_top, pClipRgn);
   4135     if (width == 0 || height == 0) {
   4136         return TRUE;
   4137     }
   4138     const CFX_DIBitmap* pClipMask = NULL;
   4139     FX_RECT clip_box;
   4140     if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
   4141         ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF);
   4142         pClipMask = pClipRgn->GetMask();
   4143         clip_box = pClipRgn->GetBox();
   4144     }
   4145     CFX_ScanlineCompositor compositor;
   4146     if (!compositor.Init(GetFormat(), pSrcBitmap->GetFormat(), width, pSrcBitmap->GetPalette(), 0, blend_type,
   4147                          pClipMask != NULL, bRgbByteOrder, 0, pIccTransform)) {
   4148         return FALSE;
   4149     }
   4150     int dest_Bpp = m_bpp / 8;
   4151     int src_Bpp = pSrcBitmap->GetBPP() / 8;
   4152     FX_BOOL bRgb = FALSE;
   4153     FX_BOOL bCmyk = FALSE;
   4154     if (src_Bpp > 1) {
   4155         if (pSrcBitmap->IsCmykImage()) {
   4156             bCmyk = TRUE;
   4157         } else {
   4158             bRgb = TRUE;
   4159         }
   4160     }
   4161     CFX_DIBitmap* pSrcAlphaMask = pSrcBitmap->m_pAlphaMask;
   4162     for (int row = 0; row < height; row ++) {
   4163         FX_LPBYTE dest_scan = m_pBuffer + (dest_top + row) * m_Pitch + dest_left * dest_Bpp;
   4164         FX_LPCBYTE src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left * src_Bpp;
   4165         FX_LPCBYTE src_scan_extra_alpha = pSrcAlphaMask ? pSrcAlphaMask->GetScanline(src_top + row) + src_left : NULL;
   4166         FX_LPBYTE dst_scan_extra_alpha = m_pAlphaMask ? (FX_LPBYTE)m_pAlphaMask->GetScanline(dest_top + row) + dest_left : NULL;
   4167         FX_LPCBYTE clip_scan = NULL;
   4168         if (pClipMask) {
   4169             clip_scan = pClipMask->m_pBuffer + (dest_top + row - clip_box.top) * pClipMask->m_Pitch + (dest_left - clip_box.left);
   4170         }
   4171         if (bRgb) {
   4172             compositor.CompositeRgbBitmapLine(dest_scan, src_scan, width, clip_scan, src_scan_extra_alpha, dst_scan_extra_alpha);
   4173         } else {
   4174             compositor.CompositePalBitmapLine(dest_scan, src_scan, src_left, width, clip_scan, src_scan_extra_alpha, dst_scan_extra_alpha);
   4175         }
   4176     }
   4177     return TRUE;
   4178 }
   4179 FX_BOOL CFX_DIBitmap::CompositeMask(int dest_left, int dest_top, int width, int height,
   4180                                     const CFX_DIBSource* pMask, FX_DWORD color, int src_left, int src_top,
   4181                                     int blend_type, const CFX_ClipRgn* pClipRgn, FX_BOOL bRgbByteOrder, int alpha_flag, void* pIccTransform)
   4182 {
   4183     if (m_pBuffer == NULL) {
   4184         return FALSE;
   4185     }
   4186     ASSERT(pMask->IsAlphaMask());
   4187     ASSERT(m_bpp >= 8);
   4188     if (!pMask->IsAlphaMask() || m_bpp < 8) {
   4189         return FALSE;
   4190     }
   4191     GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(), pMask->GetHeight(), src_left, src_top, pClipRgn);
   4192     if (width == 0 || height == 0) {
   4193         return TRUE;
   4194     }
   4195     int src_alpha = (FX_BYTE)(alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color);
   4196     if (src_alpha == 0) {
   4197         return TRUE;
   4198     }
   4199     const CFX_DIBitmap* pClipMask = NULL;
   4200     FX_RECT clip_box;
   4201     if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
   4202         ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF);
   4203         pClipMask = pClipRgn->GetMask();
   4204         clip_box = pClipRgn->GetBox();
   4205     }
   4206     int src_bpp = pMask->GetBPP();
   4207     int Bpp = GetBPP() / 8;
   4208     CFX_ScanlineCompositor compositor;
   4209     if (!compositor.Init(GetFormat(), pMask->GetFormat(), width, NULL, color, blend_type, pClipMask != NULL, bRgbByteOrder, alpha_flag, pIccTransform)) {
   4210         return FALSE;
   4211     }
   4212     for (int row = 0; row < height; row ++) {
   4213         FX_LPBYTE dest_scan = m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp;
   4214         FX_LPCBYTE src_scan = pMask->GetScanline(src_top + row);
   4215         FX_LPBYTE dst_scan_extra_alpha = m_pAlphaMask ? (FX_LPBYTE)m_pAlphaMask->GetScanline(dest_top + row) + dest_left : NULL;
   4216         FX_LPCBYTE clip_scan = NULL;
   4217         if (pClipMask) {
   4218             clip_scan = pClipMask->m_pBuffer + (dest_top + row - clip_box.top) * pClipMask->m_Pitch + (dest_left - clip_box.left);
   4219         }
   4220         if (src_bpp == 1) {
   4221             compositor.CompositeBitMaskLine(dest_scan, src_scan, src_left, width, clip_scan, dst_scan_extra_alpha);
   4222         } else {
   4223             compositor.CompositeByteMaskLine(dest_scan, src_scan + src_left, width, clip_scan, dst_scan_extra_alpha);
   4224         }
   4225     }
   4226     return TRUE;
   4227 }
   4228 FX_BOOL CFX_DIBitmap::CompositeRect(int left, int top, int width, int height, FX_DWORD color, int alpha_flag, void* pIccTransform)
   4229 {
   4230     if (m_pBuffer == NULL) {
   4231         return FALSE;
   4232     }
   4233     int src_alpha = (alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color);
   4234     if (src_alpha == 0) {
   4235         return TRUE;
   4236     }
   4237     FX_RECT rect(left, top, left + width, top + height);
   4238     rect.Intersect(0, 0, m_Width, m_Height);
   4239     if (rect.IsEmpty()) {
   4240         return TRUE;
   4241     }
   4242     width = rect.Width();
   4243     FX_DWORD dst_color;
   4244     if (alpha_flag >> 8) {
   4245         dst_color = FXCMYK_TODIB(color);
   4246     } else {
   4247         dst_color = FXARGB_TODIB(color);
   4248     }
   4249     FX_LPBYTE color_p = (FX_LPBYTE)&dst_color;
   4250     if (m_bpp == 8) {
   4251         FX_BYTE gray = 255;
   4252         if (!IsAlphaMask()) {
   4253             if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() && CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
   4254                 ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   4255                 pIccModule->TranslateScanline(pIccTransform, &gray, color_p, 1);
   4256             } else {
   4257                 if (alpha_flag >> 8) {
   4258                     FX_BYTE r, g, b;
   4259                     AdobeCMYK_to_sRGB1(color_p[0], color_p[1], color_p[2], color_p[3],
   4260                                        r, g, b);
   4261                     gray = FXRGB2GRAY(r, g, b);
   4262                 } else {
   4263                     gray = (FX_BYTE)FXRGB2GRAY((int)color_p[2], color_p[1], color_p[0]);
   4264                 }
   4265             }
   4266             if (IsCmykImage()) {
   4267                 gray = ~gray;
   4268             }
   4269         }
   4270         for (int row = rect.top; row < rect.bottom; row ++) {
   4271             FX_LPBYTE dest_scan = m_pBuffer + row * m_Pitch + rect.left;
   4272             if (src_alpha == 255) {
   4273                 FXSYS_memset8(dest_scan, gray, width);
   4274             } else
   4275                 for (int col = 0; col < width; col ++) {
   4276                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
   4277                     dest_scan ++;
   4278                 }
   4279         }
   4280         return TRUE;
   4281     } else if (m_bpp == 1) {
   4282         ASSERT(!IsCmykImage() && (FX_BYTE)(alpha_flag >> 8) == 0);
   4283         int left_shift = rect.left % 8;
   4284         int right_shift = rect.right % 8;
   4285         int width = rect.right / 8 - rect.left / 8;
   4286         int index = 0;
   4287         if (m_pPalette == NULL) {
   4288             index = ((FX_BYTE)color == 0xff) ? 1 : 0;
   4289         } else {
   4290             for (int i = 0; i < 2; i ++)
   4291                 if (m_pPalette[i] == color) {
   4292                     index = i;
   4293                 }
   4294         }
   4295         for (int row = rect.top; row < rect.bottom; row ++) {
   4296             FX_BYTE* dest_scan_top = (FX_BYTE*)GetScanline(row) + rect.left / 8;
   4297             FX_BYTE* dest_scan_top_r = (FX_BYTE*)GetScanline(row) + rect.right / 8;
   4298             FX_BYTE left_flag =  *dest_scan_top & (255 << (8 - left_shift));
   4299             FX_BYTE right_flag = *dest_scan_top_r & (255 >> right_shift);
   4300             if (width) {
   4301                 FXSYS_memset8(dest_scan_top + 1, index ? 255 : 0, width - 1);
   4302                 if (!index) {
   4303                     *dest_scan_top &= left_flag;
   4304                     *dest_scan_top_r &= right_flag;
   4305                 } else {
   4306                     *dest_scan_top |= ~left_flag;
   4307                     *dest_scan_top_r |= ~right_flag;
   4308                 }
   4309             } else {
   4310                 if (!index) {
   4311                     *dest_scan_top &= left_flag | right_flag;
   4312                 } else {
   4313                     *dest_scan_top |= ~(left_flag | right_flag);
   4314                 }
   4315             }
   4316         }
   4317         return TRUE;
   4318     }
   4319     ASSERT(m_bpp >= 24);
   4320     if (m_bpp < 24) {
   4321         return FALSE;
   4322     }
   4323     if (pIccTransform && CFX_GEModule::Get()->GetCodecModule()) {
   4324         ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   4325         pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1);
   4326     } else {
   4327         if (alpha_flag >> 8 && !IsCmykImage())
   4328             AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), FXSYS_GetYValue(color), FXSYS_GetKValue(color),
   4329                                color_p[2], color_p[1], color_p[0]);
   4330         else if (!(alpha_flag >> 8) && IsCmykImage()) {
   4331             return FALSE;
   4332         }
   4333     }
   4334     if(!IsCmykImage()) {
   4335         color_p[3] = (FX_BYTE)src_alpha;
   4336     }
   4337     int Bpp = m_bpp / 8;
   4338     FX_BOOL bAlpha = HasAlpha();
   4339     FX_BOOL bArgb = GetFormat() == FXDIB_Argb ? TRUE : FALSE;
   4340     if (src_alpha == 255) {
   4341         for (int row = rect.top; row < rect.bottom; row ++) {
   4342             FX_LPBYTE dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp;
   4343             FX_LPBYTE dest_scan_alpha = m_pAlphaMask ? (FX_LPBYTE)m_pAlphaMask->GetScanline(row) + rect.left : NULL;
   4344             if (dest_scan_alpha) {
   4345                 FXSYS_memset8(dest_scan_alpha, 0xff, width);
   4346             }
   4347             if (Bpp == 4) {
   4348                 FX_DWORD* scan = (FX_DWORD*)dest_scan;
   4349                 for (int col = 0; col < width; col ++) {
   4350                     *scan ++ = dst_color;
   4351                 }
   4352             } else {
   4353                 for (int col = 0; col < width; col ++) {
   4354                     *dest_scan ++ = color_p[0];
   4355                     *dest_scan ++ = color_p[1];
   4356                     *dest_scan ++ = color_p[2];
   4357                 }
   4358             }
   4359         }
   4360         return TRUE;
   4361     }
   4362     for (int row = rect.top; row < rect.bottom; row ++) {
   4363         FX_LPBYTE dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp;
   4364         if (bAlpha) {
   4365             if (bArgb) {
   4366                 for (int col = 0; col < width; col ++) {
   4367                     FX_BYTE back_alpha = dest_scan[3];
   4368                     if (back_alpha == 0) {
   4369                         FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, color_p[2], color_p[1], color_p[0]));
   4370                         dest_scan += 4;
   4371                         continue;
   4372                     }
   4373                     FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   4374                     int alpha_ratio = src_alpha * 255 / dest_alpha;
   4375                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[0], alpha_ratio);
   4376                     dest_scan ++;
   4377                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[1], alpha_ratio);
   4378                     dest_scan ++;
   4379                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[2], alpha_ratio);
   4380                     dest_scan ++;
   4381                     *dest_scan++ = dest_alpha;
   4382                 }
   4383             } else {
   4384                 FX_LPBYTE dest_scan_alpha = (FX_LPBYTE)m_pAlphaMask->GetScanline(row) + rect.left;
   4385                 for (int col = 0; col < width; col ++) {
   4386                     FX_BYTE back_alpha = *dest_scan_alpha;
   4387                     if (back_alpha == 0) {
   4388                         *dest_scan_alpha++ = src_alpha;
   4389                         FXSYS_memcpy32(dest_scan, color_p, Bpp);
   4390                         dest_scan += Bpp;
   4391                         continue;
   4392                     }
   4393                     FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   4394                     *dest_scan_alpha ++ = dest_alpha;
   4395                     int alpha_ratio = src_alpha * 255 / dest_alpha;
   4396                     for(int comps = 0; comps < Bpp; comps ++) {
   4397                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], alpha_ratio);
   4398                         dest_scan ++;
   4399                     }
   4400                 }
   4401             }
   4402         } else {
   4403             for (int col = 0; col < width; col ++) {
   4404                 for(int comps = 0; comps < Bpp; comps ++) {
   4405                     if (comps == 3) {
   4406                         *dest_scan ++ = 255;
   4407                         continue;
   4408                     }
   4409                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], src_alpha);
   4410                     dest_scan ++;
   4411                 }
   4412             }
   4413         }
   4414     }
   4415     return TRUE;
   4416 }
   4417 CFX_BitmapComposer::CFX_BitmapComposer()
   4418 {
   4419     m_pScanlineV = NULL;
   4420     m_pScanlineAlphaV = NULL;
   4421     m_pClipScanV = NULL;
   4422     m_pAddClipScan = NULL;
   4423     m_bRgbByteOrder = FALSE;
   4424     m_BlendType = FXDIB_BLEND_NORMAL;
   4425 }
   4426 CFX_BitmapComposer::~CFX_BitmapComposer()
   4427 {
   4428     if (m_pScanlineV) {
   4429         FX_Free(m_pScanlineV);
   4430     }
   4431     if (m_pScanlineAlphaV) {
   4432         FX_Free(m_pScanlineAlphaV);
   4433     }
   4434     if (m_pClipScanV) {
   4435         FX_Free(m_pClipScanV);
   4436     }
   4437     if (m_pAddClipScan) {
   4438         FX_Free(m_pAddClipScan);
   4439     }
   4440 }
   4441 void CFX_BitmapComposer::Compose(CFX_DIBitmap* pDest, const CFX_ClipRgn* pClipRgn, int bitmap_alpha,
   4442                                  FX_DWORD mask_color, FX_RECT& dest_rect, FX_BOOL bVertical,
   4443                                  FX_BOOL bFlipX, FX_BOOL bFlipY, FX_BOOL bRgbByteOrder,
   4444                                  int alpha_flag, void* pIccTransform, int blend_type)
   4445 {
   4446     m_pBitmap = pDest;
   4447     m_pClipRgn = pClipRgn;
   4448     m_DestLeft = dest_rect.left;
   4449     m_DestTop = dest_rect.top;
   4450     m_DestWidth = dest_rect.Width();
   4451     m_DestHeight = dest_rect.Height();
   4452     m_BitmapAlpha = bitmap_alpha;
   4453     m_MaskColor = mask_color;
   4454     m_pClipMask = NULL;
   4455     if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
   4456         m_pClipMask = pClipRgn->GetMask();
   4457     }
   4458     m_bVertical = bVertical;
   4459     m_bFlipX = bFlipX;
   4460     m_bFlipY = bFlipY;
   4461     m_AlphaFlag = alpha_flag;
   4462     m_pIccTransform = pIccTransform;
   4463     m_bRgbByteOrder = bRgbByteOrder;
   4464     m_BlendType = blend_type;
   4465 }
   4466 FX_BOOL CFX_BitmapComposer::SetInfo(int width, int height, FXDIB_Format src_format, FX_DWORD* pSrcPalette)
   4467 {
   4468     m_SrcFormat = src_format;
   4469     if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, pSrcPalette, m_MaskColor, FXDIB_BLEND_NORMAL,
   4470                            m_pClipMask != NULL || (m_BitmapAlpha < 255), m_bRgbByteOrder, m_AlphaFlag, m_pIccTransform)) {
   4471         return FALSE;
   4472     }
   4473     if (m_bVertical) {
   4474         m_pScanlineV = FX_Alloc(FX_BYTE, m_pBitmap->GetBPP() / 8 * width + 4);
   4475         if (!m_pScanlineV) {
   4476             return FALSE;
   4477         }
   4478         m_pClipScanV = FX_Alloc(FX_BYTE, m_pBitmap->GetHeight());
   4479         if (!m_pClipScanV) {
   4480             return FALSE;
   4481         }
   4482         if (m_pBitmap->m_pAlphaMask) {
   4483             m_pScanlineAlphaV = FX_Alloc(FX_BYTE, width + 4);
   4484             if (!m_pScanlineAlphaV) {
   4485                 return FALSE;
   4486             }
   4487         }
   4488     }
   4489     if (m_BitmapAlpha < 255) {
   4490         m_pAddClipScan = FX_Alloc(FX_BYTE, m_bVertical ? m_pBitmap->GetHeight() : m_pBitmap->GetWidth());
   4491         if (!m_pAddClipScan) {
   4492             return FALSE;
   4493         }
   4494     }
   4495     return TRUE;
   4496 }
   4497 void CFX_BitmapComposer::DoCompose(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int dest_width, FX_LPCBYTE clip_scan,
   4498                                    FX_LPCBYTE src_extra_alpha, FX_LPBYTE dst_extra_alpha)
   4499 {
   4500     if (m_BitmapAlpha < 255) {
   4501         if (clip_scan) {
   4502             for (int i = 0; i < dest_width; i ++) {
   4503                 m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255;
   4504             }
   4505         } else {
   4506             FXSYS_memset8(m_pAddClipScan, m_BitmapAlpha, dest_width);
   4507         }
   4508         clip_scan = m_pAddClipScan;
   4509     }
   4510     if (m_SrcFormat == FXDIB_8bppMask) {
   4511         m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width, clip_scan, dst_extra_alpha);
   4512     } else if ((m_SrcFormat & 0xff) == 8) {
   4513         m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width, clip_scan, src_extra_alpha, dst_extra_alpha);
   4514     } else {
   4515         m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width, clip_scan, src_extra_alpha, dst_extra_alpha);
   4516     }
   4517 }
   4518 void CFX_BitmapComposer::ComposeScanline(int line, FX_LPCBYTE scanline, FX_LPCBYTE scan_extra_alpha)
   4519 {
   4520     if (m_bVertical) {
   4521         ComposeScanlineV(line, scanline, scan_extra_alpha);
   4522         return;
   4523     }
   4524     FX_LPCBYTE clip_scan = NULL;
   4525     if (m_pClipMask)
   4526         clip_scan = m_pClipMask->GetBuffer() + (m_DestTop + line - m_pClipRgn->GetBox().top) *
   4527                     m_pClipMask->GetPitch() + (m_DestLeft - m_pClipRgn->GetBox().left);
   4528     FX_LPBYTE dest_scan = (FX_LPBYTE)m_pBitmap->GetScanline(line + m_DestTop) +
   4529                           m_DestLeft * m_pBitmap->GetBPP() / 8;
   4530     FX_LPBYTE dest_alpha_scan = m_pBitmap->m_pAlphaMask ?
   4531                                 (FX_LPBYTE)m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop) + m_DestLeft : NULL;
   4532     DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha, dest_alpha_scan);
   4533 }
   4534 void CFX_BitmapComposer::ComposeScanlineV(int line, FX_LPCBYTE scanline, FX_LPCBYTE scan_extra_alpha)
   4535 {
   4536     int i;
   4537     int Bpp = m_pBitmap->GetBPP() / 8;
   4538     int dest_pitch = m_pBitmap->GetPitch();
   4539     int dest_alpha_pitch = m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetPitch() : 0;
   4540     int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
   4541     FX_LPBYTE dest_buf = m_pBitmap->GetBuffer() + dest_x * Bpp + m_DestTop * dest_pitch;
   4542     FX_LPBYTE dest_alpha_buf = m_pBitmap->m_pAlphaMask ?
   4543                                m_pBitmap->m_pAlphaMask->GetBuffer() + dest_x + m_DestTop * dest_alpha_pitch : NULL;
   4544     if (m_bFlipY) {
   4545         dest_buf += dest_pitch * (m_DestHeight - 1);
   4546         dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1);
   4547     }
   4548     int y_step = dest_pitch;
   4549     int y_alpha_step = dest_alpha_pitch;
   4550     if (m_bFlipY) {
   4551         y_step = -y_step;
   4552         y_alpha_step = -y_alpha_step;
   4553     }
   4554     FX_LPBYTE src_scan = m_pScanlineV;
   4555     FX_LPBYTE dest_scan = dest_buf;
   4556     for (i = 0; i < m_DestHeight; i ++) {
   4557         for (int j = 0; j < Bpp; j ++) {
   4558             *src_scan++ = dest_scan[j];
   4559         }
   4560         dest_scan += y_step;
   4561     }
   4562     FX_LPBYTE src_alpha_scan = m_pScanlineAlphaV;
   4563     FX_LPBYTE dest_alpha_scan = dest_alpha_buf;
   4564     if (dest_alpha_scan) {
   4565         for (i = 0; i < m_DestHeight; i ++) {
   4566             *src_alpha_scan++ = *dest_alpha_scan;
   4567             dest_alpha_scan += y_alpha_step;
   4568         }
   4569     }
   4570     FX_LPBYTE clip_scan = NULL;
   4571     if (m_pClipMask) {
   4572         clip_scan = m_pClipScanV;
   4573         int clip_pitch = m_pClipMask->GetPitch();
   4574         FX_LPCBYTE src_clip = m_pClipMask->GetBuffer() + (m_DestTop - m_pClipRgn->GetBox().top) *
   4575                               clip_pitch + (dest_x - m_pClipRgn->GetBox().left);
   4576         if (m_bFlipY) {
   4577             src_clip += clip_pitch * (m_DestHeight - 1);
   4578             clip_pitch = -clip_pitch;
   4579         }
   4580         for (i = 0; i < m_DestHeight; i ++) {
   4581             clip_scan[i] = *src_clip;
   4582             src_clip += clip_pitch;
   4583         }
   4584     }
   4585     DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan, scan_extra_alpha, m_pScanlineAlphaV);
   4586     src_scan = m_pScanlineV;
   4587     dest_scan = dest_buf;
   4588     for (i = 0; i < m_DestHeight; i ++) {
   4589         for (int j = 0; j < Bpp; j ++) {
   4590             dest_scan[j] = *src_scan++;
   4591         }
   4592         dest_scan += y_step;
   4593     }
   4594     src_alpha_scan = m_pScanlineAlphaV;
   4595     dest_alpha_scan = dest_alpha_buf;
   4596     if (dest_alpha_scan) {
   4597         for (i = 0; i < m_DestHeight; i ++) {
   4598             *dest_alpha_scan = *src_alpha_scan++;
   4599             dest_alpha_scan += y_alpha_step;
   4600         }
   4601     }
   4602 }
   4603