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     for (int col = 0; col < width; col ++) {
   2955         if (src_Bpp == 4) {
   2956             FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
   2957         } else {
   2958             FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
   2959         }
   2960         dest_scan += 4;
   2961         src_scan += src_Bpp;
   2962     }
   2963 }
   2964 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)
   2965 {
   2966     int blended_colors[3];
   2967     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2968     int src_gap = src_Bpp - 3;
   2969     for (int col = 0; col < width; col ++) {
   2970         if (bNonseparableBlend) {
   2971             FX_BYTE dest_scan_o[3];
   2972             dest_scan_o[0] = dest_scan[2];
   2973             dest_scan_o[1] = dest_scan[1];
   2974             dest_scan_o[2] = dest_scan[0];
   2975             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2976         }
   2977         for (int color = 0; color < 3; color ++) {
   2978             int index = 2 - color;
   2979             int back_color = FX_GAMMA(dest_scan[index]);
   2980             int src_color = FX_GAMMA(*src_scan);
   2981             int blended = bNonseparableBlend ? blended_colors[color] :
   2982                           _BLEND(blend_type, back_color, src_color);
   2983             dest_scan[index] = FX_GAMMA_INVERSE(blended);
   2984             src_scan ++;
   2985         }
   2986         dest_scan += dest_Bpp;
   2987         src_scan += src_gap;
   2988     }
   2989 }
   2990 inline void _CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, FX_LPCBYTE clip_scan)
   2991 {
   2992     for (int col = 0; col < width; col ++) {
   2993         FX_BYTE src_alpha;
   2994         if (clip_scan) {
   2995             src_alpha = src_scan[3] * (*clip_scan++) / 255;
   2996         } else {
   2997             src_alpha = src_scan[3];
   2998         }
   2999         if (src_alpha == 255) {
   3000             dest_scan[2] = FX_GAMMA_INVERSE(*src_scan++);
   3001             dest_scan[1] = FX_GAMMA_INVERSE(*src_scan++);
   3002             dest_scan[0] = FX_GAMMA_INVERSE(*src_scan++);
   3003             dest_scan += dest_Bpp;
   3004             src_scan ++;
   3005             continue;
   3006         }
   3007         if (src_alpha == 0) {
   3008             dest_scan += dest_Bpp;
   3009             src_scan += 4;
   3010             continue;
   3011         }
   3012         for (int color = 0; color < 3; color ++) {
   3013             int index = 2 - color;
   3014             dest_scan[index] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[index]), *src_scan, src_alpha));
   3015             src_scan ++;
   3016         }
   3017         dest_scan += dest_Bpp;
   3018         src_scan ++;
   3019     }
   3020 }
   3021 inline void _CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, int src_Bpp)
   3022 {
   3023     for (int col = 0; col < width; col ++) {
   3024         dest_scan[2] = src_scan[0];
   3025         dest_scan[1] = src_scan[1];
   3026         dest_scan[0] = src_scan[2];
   3027         dest_scan += dest_Bpp;
   3028         src_scan += src_Bpp;
   3029     }
   3030 }
   3031 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)
   3032 {
   3033     int blended_colors[3];
   3034     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   3035     int src_gap = src_Bpp - 3;
   3036     for (int col = 0; col < width; col ++) {
   3037         int src_alpha = *clip_scan ++;
   3038         FX_BYTE back_alpha = dest_scan[3];
   3039         if (back_alpha == 0) {
   3040             dest_scan[2] = FX_GAMMA(*src_scan++);
   3041             dest_scan[1] = FX_GAMMA(*src_scan++);
   3042             dest_scan[0] = FX_GAMMA(*src_scan++);
   3043             src_scan += src_gap;
   3044             dest_scan += 4;
   3045             continue;
   3046         }
   3047         if (src_alpha == 0) {
   3048             dest_scan += 4;
   3049             src_scan += src_Bpp;
   3050             continue;
   3051         }
   3052         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3053         dest_scan[3] = dest_alpha;
   3054         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3055         if (bNonseparableBlend) {
   3056             FX_BYTE dest_scan_o[3];
   3057             dest_scan_o[0] = dest_scan[2];
   3058             dest_scan_o[1] = dest_scan[1];
   3059             dest_scan_o[2] = dest_scan[0];
   3060             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3061         }
   3062         for (int color = 0; color < 3; color ++) {
   3063             int index = 2 - color;
   3064             int src_color = FX_GAMMA(*src_scan);
   3065             int blended = bNonseparableBlend ? blended_colors[color] :
   3066                           _BLEND(blend_type, dest_scan[index], src_color);
   3067             blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
   3068             dest_scan[index] = FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
   3069             src_scan ++;
   3070         }
   3071         dest_scan += 4;
   3072         src_scan += src_gap;
   3073     }
   3074 }
   3075 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)
   3076 {
   3077     int blended_colors[3];
   3078     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   3079     int src_gap = src_Bpp - 3;
   3080     for (int col = 0; col < width; col ++) {
   3081         FX_BYTE src_alpha = *clip_scan ++;
   3082         if (src_alpha == 0) {
   3083             dest_scan += dest_Bpp;
   3084             src_scan += src_Bpp;
   3085             continue;
   3086         }
   3087         if (bNonseparableBlend) {
   3088             FX_BYTE dest_scan_o[3];
   3089             dest_scan_o[0] = dest_scan[2];
   3090             dest_scan_o[1] = dest_scan[1];
   3091             dest_scan_o[2] = dest_scan[0];
   3092             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3093         }
   3094         for (int color = 0; color < 3; color ++) {
   3095             int index = 2 - color;
   3096             int src_color = FX_GAMMA(*src_scan);
   3097             int back_color = FX_GAMMA(dest_scan[index]);
   3098             int blended = bNonseparableBlend ? blended_colors[color] :
   3099                           _BLEND(blend_type, back_color, src_color);
   3100             dest_scan[index] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
   3101             src_scan ++;
   3102         }
   3103         dest_scan += dest_Bpp;
   3104         src_scan += src_gap;
   3105     }
   3106 }
   3107 inline void _CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int src_Bpp, FX_LPCBYTE clip_scan)
   3108 {
   3109     int src_gap = src_Bpp - 3;
   3110     for (int col = 0; col < width; col ++) {
   3111         int src_alpha = clip_scan[col];
   3112         if (src_alpha == 255) {
   3113             dest_scan[2] = FX_GAMMA(*src_scan++);
   3114             dest_scan[1] = FX_GAMMA(*src_scan++);
   3115             dest_scan[0] = FX_GAMMA(*src_scan++);
   3116             dest_scan[3] = 255;
   3117             dest_scan += 4;
   3118             src_scan  += src_gap;
   3119             continue;
   3120         }
   3121         if (src_alpha == 0) {
   3122             dest_scan += 4;
   3123             src_scan += src_Bpp;
   3124             continue;
   3125         }
   3126         int back_alpha = dest_scan[3];
   3127         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3128         dest_scan[3] = dest_alpha;
   3129         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3130         for (int color = 0; color < 3; color ++) {
   3131             int index = 2 - color;
   3132             dest_scan[index] = FXDIB_ALPHA_MERGE(dest_scan[index], FX_GAMMA(*src_scan), alpha_ratio);
   3133             src_scan ++;
   3134         }
   3135         dest_scan += 4;
   3136         src_scan += src_gap;
   3137     }
   3138 }
   3139 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)
   3140 {
   3141     for (int col = 0; col < width; col ++) {
   3142         int src_alpha = clip_scan[col];
   3143         if (src_alpha == 255) {
   3144             dest_scan[2] = src_scan[0];
   3145             dest_scan[1] = src_scan[1];
   3146             dest_scan[0] = src_scan[2];
   3147         } else if (src_alpha) {
   3148             dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), FX_GAMMA(*src_scan), src_alpha));
   3149             src_scan ++;
   3150             dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), FX_GAMMA(*src_scan), src_alpha));
   3151             src_scan ++;
   3152             dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), FX_GAMMA(*src_scan), src_alpha));
   3153             dest_scan += dest_Bpp;
   3154             src_scan += src_Bpp - 2;
   3155             continue;
   3156         }
   3157         dest_scan += dest_Bpp;
   3158         src_scan += src_Bpp;
   3159     }
   3160 }
   3161 inline void _CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, FX_ARGB* pPalette, int pixel_count,
   3162         int DestBpp, FX_LPCBYTE clip_scan)
   3163 {
   3164     for (int col = 0; col < pixel_count; col ++) {
   3165         FX_ARGB argb = pPalette ? pPalette[*src_scan] : (*src_scan) * 0x010101;
   3166         int src_r = FXARGB_R(argb);
   3167         int src_g = FXARGB_G(argb);
   3168         int src_b = FXARGB_B(argb);
   3169         if (clip_scan && clip_scan[col] < 255) {
   3170             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
   3171             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
   3172             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
   3173         } else {
   3174             dest_scan[2] = src_b;
   3175             dest_scan[1] = src_g;
   3176             dest_scan[0] = src_r;
   3177         }
   3178         dest_scan += DestBpp;
   3179         src_scan ++;
   3180     }
   3181 }
   3182 inline void _CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left,
   3183         FX_ARGB* pPalette, int pixel_count, int DestBpp, FX_LPCBYTE clip_scan)
   3184 {
   3185     int reset_r, reset_g, reset_b;
   3186     int set_r, set_g, set_b;
   3187     if (pPalette) {
   3188         reset_r = FXARGB_R(pPalette[0]);
   3189         reset_g = FXARGB_G(pPalette[0]);
   3190         reset_b = FXARGB_B(pPalette[0]);
   3191         set_r = FXARGB_R(pPalette[1]);
   3192         set_g = FXARGB_G(pPalette[1]);
   3193         set_b = FXARGB_B(pPalette[1]);
   3194     } else {
   3195         reset_r = reset_g = reset_b = 0;
   3196         set_r = set_g = set_b = 255;
   3197     }
   3198     for (int col = 0; col < pixel_count; col ++) {
   3199         int src_r, src_g, src_b;
   3200         if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   3201             src_r = set_r;
   3202             src_g = set_g;
   3203             src_b = set_b;
   3204         } else {
   3205             src_r = reset_r;
   3206             src_g = reset_g;
   3207             src_b = reset_b;
   3208         }
   3209         if (clip_scan && clip_scan[col] < 255) {
   3210             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
   3211             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
   3212             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
   3213         } else {
   3214             dest_scan[2] = src_b;
   3215             dest_scan[1] = src_g;
   3216             dest_scan[0] = src_r;
   3217         }
   3218         dest_scan += DestBpp;
   3219     }
   3220 }
   3221 inline void _CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width,
   3222         FX_ARGB* pPalette, FX_LPCBYTE clip_scan)
   3223 {
   3224     for (int col = 0; col < width; col ++) {
   3225         int src_r, src_g, src_b;
   3226         if (pPalette) {
   3227             FX_ARGB argb = pPalette[*src_scan];
   3228             src_r = FXARGB_R(argb);
   3229             src_g = FXARGB_G(argb);
   3230             src_b = FXARGB_B(argb);
   3231         } else {
   3232             src_r = src_g = src_b = *src_scan;
   3233         }
   3234         if (clip_scan == NULL || clip_scan[col] == 255) {
   3235             dest_scan[2] = FX_GAMMA(src_b);
   3236             dest_scan[1] = FX_GAMMA(src_g);
   3237             dest_scan[0] = FX_GAMMA(src_r);
   3238             dest_scan[3] = 255;
   3239             src_scan ++;
   3240             dest_scan += 4;
   3241             continue;
   3242         }
   3243         int src_alpha = clip_scan[col];
   3244         if (src_alpha == 0) {
   3245             dest_scan += 4;
   3246             src_scan ++;
   3247             continue;
   3248         }
   3249         int back_alpha = dest_scan[3];
   3250         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3251         dest_scan[3] = dest_alpha;
   3252         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3253         dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], FX_GAMMA(src_b), alpha_ratio);
   3254         dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], FX_GAMMA(src_g), alpha_ratio);
   3255         dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], FX_GAMMA(src_r), alpha_ratio);
   3256         dest_scan += 4;
   3257         src_scan ++;
   3258     }
   3259 }
   3260 inline void _CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width,
   3261         FX_ARGB* pPalette, FX_LPCBYTE clip_scan)
   3262 {
   3263     int reset_r, reset_g, reset_b;
   3264     int set_r, set_g, set_b;
   3265     if (pPalette) {
   3266         reset_r = FXARGB_R(pPalette[0]);
   3267         reset_g = FXARGB_G(pPalette[0]);
   3268         reset_b = FXARGB_B(pPalette[0]);
   3269         set_r = FXARGB_R(pPalette[1]);
   3270         set_g = FXARGB_G(pPalette[1]);
   3271         set_b = FXARGB_B(pPalette[1]);
   3272     } else {
   3273         reset_r = reset_g = reset_b = 0;
   3274         set_r = set_g = set_b = 255;
   3275     }
   3276     for (int col = 0; col < width; col ++) {
   3277         int src_r, src_g, src_b;
   3278         if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   3279             src_r = set_r;
   3280             src_g = set_g;
   3281             src_b = set_b;
   3282         } else {
   3283             src_r = reset_r;
   3284             src_g = reset_g;
   3285             src_b = reset_b;
   3286         }
   3287         if (clip_scan == NULL || clip_scan[col] == 255) {
   3288             dest_scan[2] = FX_GAMMA(src_b);
   3289             dest_scan[1] = FX_GAMMA(src_g);
   3290             dest_scan[0] = FX_GAMMA(src_r);
   3291             dest_scan[3] = 255;
   3292             dest_scan += 4;
   3293             continue;
   3294         }
   3295         int src_alpha = clip_scan[col];
   3296         if (src_alpha == 0) {
   3297             dest_scan += 4;
   3298             continue;
   3299         }
   3300         int back_alpha = dest_scan[3];
   3301         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3302         dest_scan[3] = dest_alpha;
   3303         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3304         dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], FX_GAMMA(src_b), alpha_ratio);
   3305         dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], FX_GAMMA(src_g), alpha_ratio);
   3306         dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], FX_GAMMA(src_r), alpha_ratio);
   3307         dest_scan += 4;
   3308     }
   3309 }
   3310 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,
   3311         int blend_type, FX_LPCBYTE clip_scan)
   3312 {
   3313     for (int col = 0; col < pixel_count; col ++) {
   3314         int src_alpha;
   3315         if (clip_scan) {
   3316             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   3317         } else {
   3318             src_alpha = mask_alpha * src_scan[col] / 255;
   3319         }
   3320         FX_BYTE back_alpha = dest_scan[3];
   3321         if (back_alpha == 0) {
   3322             FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   3323             dest_scan += 4;
   3324             continue;
   3325         }
   3326         if (src_alpha == 0) {
   3327             dest_scan += 4;
   3328             continue;
   3329         }
   3330         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3331         dest_scan[3] = dest_alpha;
   3332         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3333         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   3334             int blended_colors[3];
   3335             FX_BYTE src_scan[3];
   3336             FX_BYTE dest_scan_o[3];
   3337             src_scan[0] = src_b;
   3338             src_scan[1] = src_g;
   3339             src_scan[2] = src_r;
   3340             dest_scan_o[0] = dest_scan[2];
   3341             dest_scan_o[1] = dest_scan[1];
   3342             dest_scan_o[2] = dest_scan[0];
   3343             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3344             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
   3345             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
   3346             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
   3347         } else if (blend_type) {
   3348             int blended = _BLEND(blend_type, dest_scan[2], src_b);
   3349             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   3350             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
   3351             blended = _BLEND(blend_type, dest_scan[1], src_g);
   3352             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   3353             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
   3354             blended = _BLEND(blend_type, dest_scan[0], src_r);
   3355             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   3356             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
   3357         } else {
   3358             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
   3359             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
   3360             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
   3361         }
   3362         dest_scan += 4;
   3363     }
   3364 }
   3365 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,
   3366         int blend_type, int Bpp, FX_LPCBYTE clip_scan)
   3367 {
   3368     for (int col = 0; col < pixel_count; col ++) {
   3369         int src_alpha;
   3370         if (clip_scan) {
   3371             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   3372         } else {
   3373             src_alpha = mask_alpha * src_scan[col] / 255;
   3374         }
   3375         if (src_alpha == 0) {
   3376             dest_scan += Bpp;
   3377             continue;
   3378         }
   3379         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   3380             int blended_colors[3];
   3381             FX_BYTE src_scan[3];
   3382             FX_BYTE dest_scan_o[3];
   3383             src_scan[0] = src_b;
   3384             src_scan[1] = src_g;
   3385             src_scan[2] = src_r;
   3386             dest_scan_o[0] = dest_scan[2];
   3387             dest_scan_o[1] = dest_scan[1];
   3388             dest_scan_o[2] = dest_scan[0];
   3389             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3390             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
   3391             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
   3392             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
   3393         } else if (blend_type) {
   3394             int blended = _BLEND(blend_type, dest_scan[2], src_b);
   3395             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha);
   3396             blended = _BLEND(blend_type, dest_scan[1], src_g);
   3397             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha);
   3398             blended = _BLEND(blend_type, dest_scan[0], src_r);
   3399             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha);
   3400         } else {
   3401             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha);
   3402             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha);
   3403             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha);
   3404         }
   3405         dest_scan += Bpp;
   3406     }
   3407 }
   3408 void _CompositeRow_BitMask2Argb_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b,
   3409         int src_left, int pixel_count, int blend_type, FX_LPCBYTE clip_scan)
   3410 {
   3411     if (blend_type == FXDIB_BLEND_NORMAL && clip_scan == NULL && mask_alpha == 255) {
   3412         FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b);
   3413         for (int col = 0; col < pixel_count; col ++) {
   3414             if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   3415                 FXARGB_SETRGBORDERDIB(dest_scan, argb);
   3416             }
   3417             dest_scan += 4;
   3418         }
   3419         return;
   3420     }
   3421     for (int col = 0; col < pixel_count; col ++) {
   3422         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   3423             dest_scan += 4;
   3424             continue;
   3425         }
   3426         int src_alpha;
   3427         if (clip_scan) {
   3428             src_alpha = mask_alpha * clip_scan[col] / 255;
   3429         } else {
   3430             src_alpha = mask_alpha;
   3431         }
   3432         FX_BYTE back_alpha = dest_scan[3];
   3433         if (back_alpha == 0) {
   3434             FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   3435             dest_scan += 4;
   3436             continue;
   3437         }
   3438         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   3439         dest_scan[3] = dest_alpha;
   3440         int alpha_ratio = src_alpha * 255 / dest_alpha;
   3441         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   3442             int blended_colors[3];
   3443             FX_BYTE src_scan[3];
   3444             FX_BYTE dest_scan_o[3];
   3445             src_scan[0] = src_b;
   3446             src_scan[1] = src_g;
   3447             src_scan[2] = src_r;
   3448             dest_scan_o[0] = dest_scan[2];
   3449             dest_scan_o[1] = dest_scan[1];
   3450             dest_scan_o[2] = dest_scan[0];
   3451             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3452             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
   3453             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
   3454             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
   3455         } else if (blend_type) {
   3456             int blended = _BLEND(blend_type, dest_scan[2], src_b);
   3457             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   3458             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
   3459             blended = _BLEND(blend_type, dest_scan[1], src_g);
   3460             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   3461             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
   3462             blended = _BLEND(blend_type, dest_scan[0], src_r);
   3463             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   3464             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
   3465         } else {
   3466             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
   3467             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
   3468             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
   3469         }
   3470         dest_scan += 4;
   3471     }
   3472 }
   3473 void _CompositeRow_BitMask2Rgb_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b,
   3474         int src_left, int pixel_count, int blend_type, int Bpp, FX_LPCBYTE clip_scan)
   3475 {
   3476     if (blend_type == FXDIB_BLEND_NORMAL && clip_scan == NULL && mask_alpha == 255) {
   3477         for (int col = 0; col < pixel_count; col ++) {
   3478             if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   3479                 dest_scan[2] = src_b;
   3480                 dest_scan[1] = src_g;
   3481                 dest_scan[0] = src_r;
   3482             }
   3483             dest_scan += Bpp;
   3484         }
   3485         return;
   3486     }
   3487     for (int col = 0; col < pixel_count; col ++) {
   3488         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   3489             dest_scan += Bpp;
   3490             continue;
   3491         }
   3492         int src_alpha;
   3493         if (clip_scan) {
   3494             src_alpha = mask_alpha * clip_scan[col] / 255;
   3495         } else {
   3496             src_alpha = mask_alpha;
   3497         }
   3498         if (src_alpha == 0) {
   3499             dest_scan += Bpp;
   3500             continue;
   3501         }
   3502         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   3503             int blended_colors[3];
   3504             FX_BYTE src_scan[3];
   3505             FX_BYTE dest_scan_o[3];
   3506             src_scan[0] = src_b;
   3507             src_scan[1] = src_g;
   3508             src_scan[2] = src_r;
   3509             dest_scan_o[0] = dest_scan[2];
   3510             dest_scan_o[1] = dest_scan[1];
   3511             dest_scan_o[2] = dest_scan[0];
   3512             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   3513             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
   3514             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
   3515             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
   3516         } else if (blend_type) {
   3517             int back_color = FX_GAMMA(dest_scan[2]);
   3518             int blended = _BLEND(blend_type, back_color, src_b);
   3519             dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
   3520             back_color = FX_GAMMA(dest_scan[1]);
   3521             blended = _BLEND(blend_type, back_color, src_g);
   3522             dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
   3523             back_color = FX_GAMMA(dest_scan[0]);
   3524             blended = _BLEND(blend_type, back_color, src_r);
   3525             dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
   3526         } else {
   3527             dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), src_b, src_alpha));
   3528             dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), src_g, src_alpha));
   3529             dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), src_r, src_alpha));
   3530         }
   3531         dest_scan += Bpp;
   3532     }
   3533 }
   3534 inline FX_BOOL _ScanlineCompositor_InitSourceMask(FXDIB_Format dest_format, int alpha_flag, FX_DWORD mask_color, int& mask_alpha,
   3535         int& mask_red, int& mask_green, int& mask_blue, int& mask_black,
   3536         void* icc_module, void* pIccTransform)
   3537 {
   3538     ICodec_IccModule* pIccModule = (ICodec_IccModule*)icc_module;
   3539     if (alpha_flag >> 8) {
   3540         mask_alpha = alpha_flag & 0xff;
   3541         mask_red = FXSYS_GetCValue(mask_color);
   3542         mask_green = FXSYS_GetMValue(mask_color);
   3543         mask_blue = FXSYS_GetYValue(mask_color);
   3544         mask_black = FXSYS_GetKValue(mask_color);
   3545     } else {
   3546         mask_alpha = FXARGB_A(mask_color);
   3547         mask_red = FXARGB_R(mask_color);
   3548         mask_green = FXARGB_G(mask_color);
   3549         mask_blue = FXARGB_B(mask_color);
   3550     }
   3551     if (dest_format == FXDIB_8bppMask) {
   3552         return TRUE;
   3553     }
   3554     if ((dest_format & 0xff) == 8) {
   3555         if (pIccTransform) {
   3556             mask_color = (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color);
   3557             FX_LPBYTE gray_p = (FX_LPBYTE)&mask_color;
   3558             pIccModule->TranslateScanline(pIccTransform, gray_p, gray_p, 1);
   3559             mask_red = dest_format & 0x0400 ? FX_CCOLOR(gray_p[0]) : gray_p[0];
   3560         } else {
   3561             if (alpha_flag >> 8) {
   3562                 FX_BYTE r, g, b;
   3563                 AdobeCMYK_to_sRGB1(mask_red, mask_green, mask_blue, mask_black,
   3564                                    r, g, b);
   3565                 mask_red = FXRGB2GRAY(r, g, b);
   3566             } else {
   3567                 mask_red = FXRGB2GRAY(mask_red, mask_green, mask_blue);
   3568             }
   3569             if (dest_format & 0x0400) {
   3570                 mask_red = FX_CCOLOR(mask_red);
   3571             }
   3572         }
   3573     } else {
   3574         FX_LPBYTE mask_color_p = (FX_LPBYTE)&mask_color;
   3575         mask_color = (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color);
   3576         if (pIccTransform) {
   3577             pIccModule->TranslateScanline(pIccTransform, mask_color_p, mask_color_p, 1);
   3578             mask_red = mask_color_p[2];
   3579             mask_green = mask_color_p[1];
   3580             mask_blue = mask_color_p[0];
   3581         } else if (alpha_flag >> 8) {
   3582             AdobeCMYK_to_sRGB1(mask_color_p[0], mask_color_p[1], mask_color_p[2], mask_color_p[3],
   3583                                mask_color_p[2], mask_color_p[1], mask_color_p[0]);
   3584             mask_red = mask_color_p[2];
   3585             mask_green = mask_color_p[1];
   3586             mask_blue = mask_color_p[0];
   3587         }
   3588     }
   3589     return TRUE;
   3590 }
   3591 inline void _ScanlineCompositor_InitSourcePalette(FXDIB_Format src_format, FXDIB_Format dest_format,
   3592         FX_DWORD*& pDestPalette, FX_DWORD* pSrcPalette,
   3593         void* icc_module, void* pIccTransform)
   3594 {
   3595     ICodec_IccModule* pIccModule = (ICodec_IccModule*)icc_module;
   3596     FX_BOOL isSrcCmyk = src_format & 0x0400 ? TRUE : FALSE;
   3597     FX_BOOL isDstCmyk = dest_format & 0x0400 ? TRUE : FALSE;
   3598     pDestPalette = NULL;
   3599     if (pIccTransform) {
   3600         if (pSrcPalette) {
   3601             if ((dest_format & 0xff) == 8) {
   3602                 int pal_count = 1 << (src_format & 0xff);
   3603                 FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
   3604                 pDestPalette = (FX_DWORD*)gray_pal;
   3605                 for (int i = 0; i < pal_count; i ++) {
   3606                     FX_DWORD color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) : FXARGB_TODIB(pSrcPalette[i]);
   3607                     pIccModule->TranslateScanline(pIccTransform, gray_pal, (FX_LPCBYTE)&color, 1);
   3608                     gray_pal ++;
   3609                 }
   3610             } else {
   3611                 int palsize = 1 << (src_format & 0xff);
   3612                 pDestPalette = FX_Alloc(FX_DWORD, palsize);
   3613                 for (int i = 0; i < palsize; i ++) {
   3614                     FX_DWORD color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) : FXARGB_TODIB(pSrcPalette[i]);
   3615                     pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&color, (FX_LPCBYTE)&color, 1);
   3616                     pDestPalette[i] = isDstCmyk ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
   3617                 }
   3618             }
   3619         } else {
   3620             int pal_count = 1 << (src_format & 0xff);
   3621             FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
   3622             if (pal_count == 2) {
   3623                 gray_pal[0] = 0;
   3624                 gray_pal[1] = 255;
   3625             } else {
   3626                 for (int i = 0; i < pal_count; i++) {
   3627                     gray_pal[i] = i;
   3628                 }
   3629             }
   3630             if ((dest_format & 0xff) == 8) {
   3631                 pIccModule->TranslateScanline(pIccTransform, gray_pal, gray_pal, pal_count);
   3632                 pDestPalette = (FX_DWORD*)gray_pal;
   3633             } else {
   3634                 pDestPalette = FX_Alloc(FX_DWORD, pal_count);
   3635                 for (int i = 0; i < pal_count; i ++) {
   3636                     pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&pDestPalette[i], &gray_pal[i], 1);
   3637                     pDestPalette[i] = isDstCmyk ? FXCMYK_TODIB(pDestPalette[i]) : FXARGB_TODIB(pDestPalette[i]);
   3638                 }
   3639                 FX_Free(gray_pal);
   3640             }
   3641         }
   3642     } else {
   3643         if (pSrcPalette) {
   3644             if ((dest_format & 0xff) == 8) {
   3645                 int pal_count = 1 << (src_format & 0xff);
   3646                 FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
   3647                 pDestPalette = (FX_DWORD*)gray_pal;
   3648                 if (isSrcCmyk) {
   3649                     for (int i = 0; i < pal_count; i ++) {
   3650                         FX_CMYK cmyk = pSrcPalette[i];
   3651                         FX_BYTE r, g, b;
   3652                         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
   3653                                            r, g, b);
   3654                         *gray_pal ++ = FXRGB2GRAY(r, g, b);
   3655                     }
   3656                 } else
   3657                     for (int i = 0; i < pal_count; i ++) {
   3658                         FX_ARGB argb = pSrcPalette[i];
   3659                         *gray_pal ++ = FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
   3660                     }
   3661             } else {
   3662                 int palsize = 1 << (src_format & 0xff);
   3663                 pDestPalette = FX_Alloc(FX_DWORD, palsize);
   3664                 if (isDstCmyk == isSrcCmyk) {
   3665                     FXSYS_memcpy32(pDestPalette, pSrcPalette, palsize * sizeof(FX_DWORD));
   3666                 } else {
   3667                     for (int i = 0; i < palsize; i ++) {
   3668                         FX_CMYK cmyk = pSrcPalette[i];
   3669                         FX_BYTE r, g, b;
   3670                         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
   3671                                            r, g, b);
   3672                         pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b);
   3673                     }
   3674                 }
   3675             }
   3676         } else {
   3677             if ((dest_format & 0xff) == 8) {
   3678                 int pal_count = 1 << (src_format & 0xff);
   3679                 FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
   3680                 if (pal_count == 2) {
   3681                     gray_pal[0] = 0;
   3682                     gray_pal[1] = 255;
   3683                 } else {
   3684                     for (int i = 0; i < pal_count; i++) {
   3685                         gray_pal[i] = i;
   3686                     }
   3687                 }
   3688                 pDestPalette = (FX_DWORD*)gray_pal;
   3689             } else {
   3690                 int palsize = 1 << (src_format & 0xff);
   3691                 pDestPalette = FX_Alloc(FX_DWORD, palsize);
   3692                 if (palsize == 2) {
   3693                     pDestPalette[0] = isSrcCmyk ? 255 : 0xff000000;
   3694                     pDestPalette[1] = isSrcCmyk ? 0 : 0xffffffff;
   3695                 } else {
   3696                     for (int i = 0; i < palsize; i++) {
   3697                         pDestPalette[i] = isSrcCmyk ? FX_CCOLOR(i) : (i * 0x10101);
   3698                     }
   3699                 }
   3700                 if (isSrcCmyk != isDstCmyk) {
   3701                     for (int i = 0; i < palsize; i ++) {
   3702                         FX_CMYK cmyk = pDestPalette[i];
   3703                         FX_BYTE r, g, b;
   3704                         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
   3705                                            r, g, b);
   3706                         pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b);
   3707                     }
   3708                 }
   3709             }
   3710         }
   3711     }
   3712 }
   3713 CFX_ScanlineCompositor::CFX_ScanlineCompositor()
   3714 {
   3715     m_pSrcPalette = NULL;
   3716     m_pCacheScanline = NULL;
   3717     m_CacheSize = 0;
   3718     m_bRgbByteOrder = FALSE;
   3719     m_BlendType = FXDIB_BLEND_NORMAL;
   3720 }
   3721 CFX_ScanlineCompositor::~CFX_ScanlineCompositor()
   3722 {
   3723     if (m_pSrcPalette) {
   3724         FX_Free(m_pSrcPalette);
   3725     }
   3726     if (m_pCacheScanline) {
   3727         FX_Free(m_pCacheScanline);
   3728     }
   3729 }
   3730 FX_BOOL CFX_ScanlineCompositor::Init(FXDIB_Format dest_format, FXDIB_Format src_format, FX_INT32 width, FX_DWORD* pSrcPalette,
   3731                                      FX_DWORD mask_color, int blend_type, FX_BOOL bClip, FX_BOOL bRgbByteOrder, int alpha_flag, void* pIccTransform)
   3732 {
   3733     m_SrcFormat = src_format;
   3734     m_DestFormat = dest_format;
   3735     m_BlendType = blend_type;
   3736     m_bRgbByteOrder = bRgbByteOrder;
   3737     ICodec_IccModule* pIccModule = NULL;
   3738     if (CFX_GEModule::Get()->GetCodecModule()) {
   3739         pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   3740     }
   3741     if (pIccModule == NULL) {
   3742         pIccTransform = NULL;
   3743     }
   3744     m_pIccTransform = pIccTransform;
   3745     if ((dest_format & 0xff) == 1) {
   3746         return FALSE;
   3747     }
   3748     if (m_SrcFormat == FXDIB_1bppMask || m_SrcFormat == FXDIB_8bppMask) {
   3749         return _ScanlineCompositor_InitSourceMask(dest_format, alpha_flag, mask_color,
   3750                 m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, m_MaskBlack,
   3751                 pIccModule, pIccTransform);
   3752     }
   3753     if (pIccTransform == NULL && (~src_format & 0x0400) && (dest_format & 0x0400)) {
   3754         return FALSE;
   3755     }
   3756     if ((m_SrcFormat & 0xff) <= 8) {
   3757         if (dest_format == FXDIB_8bppMask) {
   3758             return TRUE;
   3759         }
   3760         _ScanlineCompositor_InitSourcePalette(src_format, dest_format, m_pSrcPalette, pSrcPalette,
   3761                                               pIccModule, pIccTransform);
   3762         m_Transparency = (dest_format == FXDIB_Argb ? 1 : 0)
   3763                          + (dest_format & 0x0200 ? 2 : 0)
   3764                          + (dest_format & 0x0400 ? 4 : 0)
   3765                          + ((src_format & 0xff) == 1 ? 8 : 0);
   3766         return TRUE;
   3767     }
   3768     m_Transparency = (src_format & 0x0200 ? 0 : 1)
   3769                      + (dest_format & 0x0200 ? 0 : 2)
   3770                      + (blend_type == FXDIB_BLEND_NORMAL ? 4 : 0)
   3771                      + (bClip ? 8 : 0)
   3772                      + (src_format & 0x0400 ? 16 : 0)
   3773                      + (dest_format & 0x0400 ? 32 : 0)
   3774                      + (pIccTransform ? 64 : 0);
   3775     return TRUE;
   3776 }
   3777 void CFX_ScanlineCompositor::CompositeRgbBitmapLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, FX_LPCBYTE clip_scan,
   3778         FX_LPCBYTE src_extra_alpha, FX_LPBYTE dst_extra_alpha)
   3779 {
   3780     int src_Bpp = (m_SrcFormat & 0xff) >> 3;
   3781     int dest_Bpp = (m_DestFormat & 0xff) >> 3;
   3782     if (m_bRgbByteOrder) {
   3783         switch (m_Transparency) {
   3784             case 0:
   3785             case 4:
   3786             case 8:
   3787             case 12:
   3788                 _CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, clip_scan);
   3789                 break;
   3790             case 1:
   3791                 _CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, src_Bpp);
   3792                 break;
   3793             case 2:
   3794             case 10:
   3795                 _CompositeRow_Argb2Rgb_Blend_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan);
   3796                 break;
   3797             case 3:
   3798                 _CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp);
   3799                 break;
   3800             case 5:
   3801                 _CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, width, src_Bpp);
   3802                 break;
   3803             case 6:
   3804             case 14:
   3805                 _CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, dest_Bpp, clip_scan);
   3806                 break;
   3807             case 7:
   3808                 _CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, width, dest_Bpp, src_Bpp);
   3809                 break;
   3810             case 9:
   3811                 _CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan);
   3812                 break;
   3813             case 11:
   3814                 _CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, clip_scan);
   3815                 break;
   3816             case 13:
   3817                 _CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(dest_scan, src_scan, width, src_Bpp, clip_scan);
   3818                 break;
   3819             case 15:
   3820                 _CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan);
   3821                 break;
   3822         }
   3823         return;
   3824     }
   3825     if (m_DestFormat == FXDIB_8bppMask) {
   3826         if (m_SrcFormat & 0x0200) {
   3827             if (m_SrcFormat == FXDIB_Argb) {
   3828                 _CompositeRow_Argb2Mask(dest_scan, src_scan, width, clip_scan);
   3829             } else {
   3830                 _CompositeRow_Rgba2Mask(dest_scan, src_extra_alpha, width, clip_scan);
   3831             }
   3832         } else {
   3833             _CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
   3834         }
   3835     } else if ((m_DestFormat & 0xff) == 8) {
   3836         if (m_DestFormat & 0x0400) {
   3837             for (int i = 0; i < width; i ++) {
   3838                 *dest_scan = ~*dest_scan;
   3839                 dest_scan++;
   3840             }
   3841         }
   3842         if (m_SrcFormat & 0x0200) {
   3843             if (m_DestFormat & 0x0200) {
   3844                 _CompositeRow_Argb2Graya(dest_scan, src_scan, width, m_BlendType, clip_scan, src_extra_alpha, dst_extra_alpha, m_pIccTransform);
   3845             } else {
   3846                 _CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType, clip_scan, src_extra_alpha, m_pIccTransform);
   3847             }
   3848         } else {
   3849             if (m_DestFormat & 0x0200) {
   3850                 _CompositeRow_Rgb2Graya(dest_scan, src_scan, src_Bpp, width, m_BlendType, clip_scan, dst_extra_alpha, m_pIccTransform);
   3851             } else {
   3852                 _CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType, clip_scan, m_pIccTransform);
   3853             }
   3854         }
   3855         if (m_DestFormat & 0x0400) {
   3856             for (int i = 0; i < width; i ++) {
   3857                 *dest_scan = ~*dest_scan;
   3858                 dest_scan++;
   3859             }
   3860         }
   3861     } else {
   3862         int dest_Size = width * dest_Bpp + 4;
   3863         if (dest_Size > m_CacheSize) {
   3864             m_pCacheScanline = FX_Realloc(FX_BYTE, m_pCacheScanline, dest_Size);
   3865             if (!m_pCacheScanline) {
   3866                 return;
   3867             }
   3868             m_CacheSize = dest_Size;
   3869         }
   3870         switch (m_Transparency) {
   3871             case 0:
   3872             case 4:
   3873             case 8:
   3874             case 4+8: {
   3875                     _CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType, clip_scan,
   3876                                             dst_extra_alpha, src_extra_alpha);
   3877                 }
   3878                 break;
   3879             case 64:
   3880             case 4+64:
   3881             case 8+64:
   3882             case 4+8+64: {
   3883                     _CompositeRow_Argb2Argb_Transform(dest_scan, src_scan, width, m_BlendType, clip_scan,
   3884                                                       dst_extra_alpha, src_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3885                 }
   3886                 break;
   3887             case 1:
   3888                 _CompositeRow_Rgb2Argb_Blend_NoClip(dest_scan, src_scan, width, m_BlendType, src_Bpp,
   3889                                                     dst_extra_alpha);
   3890                 break;
   3891             case 1+64:
   3892                 _CompositeRow_Rgb2Argb_Blend_NoClip_Transform(dest_scan, src_scan, width, m_BlendType, src_Bpp,
   3893                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3894                 break;
   3895             case 1+8:
   3896                 _CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan,
   3897                                                   dst_extra_alpha);
   3898                 break;
   3899             case 1+8+64:
   3900                 _CompositeRow_Rgb2Argb_Blend_Clip_Transform(dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan,
   3901                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3902                 break;
   3903             case 1+4:
   3904                 _CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width, src_Bpp,
   3905                                                       dst_extra_alpha);
   3906                 break;
   3907             case 1+4+64:
   3908                 _CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform(dest_scan, src_scan, width, src_Bpp,
   3909                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3910                 break;
   3911             case 1+4+8:
   3912                 _CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp, clip_scan,
   3913                                                     dst_extra_alpha);
   3914                 break;
   3915             case 1+4+8+64:
   3916                 _CompositeRow_Rgb2Argb_NoBlend_Clip_Transform(dest_scan, src_scan, width, src_Bpp, clip_scan,
   3917                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3918                 break;
   3919             case 2:
   3920             case 2+8:
   3921                 _CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan,
   3922                                              src_extra_alpha);
   3923                 break;
   3924             case 2+64:
   3925             case 2+8+64:
   3926                 _CompositeRow_Argb2Rgb_Blend_Transform(dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan,
   3927                                                        src_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3928                 break;
   3929             case 2+4:
   3930             case 2+4+8:
   3931                 _CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp, clip_scan,
   3932                                                src_extra_alpha);
   3933                 break;
   3934             case 2+4+64:
   3935             case 2+4+8+64:
   3936                 _CompositeRow_Argb2Rgb_NoBlend_Transform(dest_scan, src_scan, width, dest_Bpp, clip_scan,
   3937                         src_extra_alpha, m_pCacheScanline, m_pIccTransform);
   3938                 break;
   3939             case 1+2:
   3940                 _CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp);
   3941                 break;
   3942             case 1+2+64:
   3943                 _CompositeRow_Rgb2Rgb_Blend_NoClip_Transform(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp,
   3944                         m_pCacheScanline, m_pIccTransform);
   3945                 break;
   3946             case 1+2+8:
   3947                 _CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, clip_scan);
   3948                 break;
   3949             case 1+2+8+64:
   3950                 _CompositeRow_Rgb2Rgb_Blend_Clip_Transform(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, clip_scan,
   3951                         m_pCacheScanline, m_pIccTransform);
   3952                 break;
   3953             case 1+2+4:
   3954                 _CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width, dest_Bpp, src_Bpp);
   3955                 break;
   3956             case 1+2+4+64:
   3957                 _CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform(dest_scan, src_scan, width, dest_Bpp, src_Bpp,
   3958                         m_pCacheScanline, m_pIccTransform);
   3959                 break;
   3960             case 1+2+4+8:
   3961                 _CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan);
   3962                 break;
   3963             case 1+2+4+8+64:
   3964                 _CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform(dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan,
   3965                         m_pCacheScanline, m_pIccTransform);
   3966                 break;
   3967         }
   3968     }
   3969 }
   3970 void CFX_ScanlineCompositor::CompositePalBitmapLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width, FX_LPCBYTE clip_scan,
   3971         FX_LPCBYTE src_extra_alpha, FX_LPBYTE dst_extra_alpha)
   3972 {
   3973     if (m_bRgbByteOrder) {
   3974         if (m_SrcFormat == FXDIB_1bppRgb) {
   3975             if (m_DestFormat == FXDIB_8bppRgb) {
   3976                 return;
   3977             } else if(m_DestFormat == FXDIB_Argb) {
   3978                 _CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan);
   3979             } else {
   3980                 _CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, src_left, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan);
   3981             }
   3982         } else {
   3983             if (m_DestFormat == FXDIB_8bppRgb) {
   3984                 return;
   3985             } else if (m_DestFormat == FXDIB_Argb) {
   3986                 _CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, m_pSrcPalette, clip_scan);
   3987             } else {
   3988                 _CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan);
   3989             }
   3990         }
   3991         return;
   3992     }
   3993     if (m_DestFormat == FXDIB_8bppMask) {
   3994         _CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
   3995         return;
   3996     } else if ((m_DestFormat & 0xff) == 8) {
   3997         if (m_Transparency & 8) {
   3998             if (m_DestFormat & 0x0200) {
   3999                 _CompositeRow_1bppPal2Graya(dest_scan, src_scan, src_left, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan, dst_extra_alpha);
   4000             } else {
   4001                 _CompositeRow_1bppPal2Gray(dest_scan, src_scan, src_left, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan);
   4002             }
   4003         } else {
   4004             if (m_DestFormat & 0x0200)
   4005                 _CompositeRow_8bppPal2Graya(dest_scan, src_scan, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan,
   4006                                             dst_extra_alpha, src_extra_alpha);
   4007             else
   4008                 _CompositeRow_8bppPal2Gray(dest_scan, src_scan, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan,
   4009                                            src_extra_alpha);
   4010         }
   4011     } else {
   4012         switch (m_Transparency) {
   4013             case 1+2:
   4014                 _CompositeRow_8bppRgb2Argb_NoBlend(dest_scan, src_scan, width, m_pSrcPalette, clip_scan,
   4015                                                    src_extra_alpha);
   4016                 break;
   4017             case 1+2+8:
   4018                 _CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan);
   4019                 break;
   4020             case 0:
   4021                 _CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan,
   4022                                                   src_extra_alpha);
   4023                 break;
   4024             case 0+8:
   4025                 _CompositeRow_1bppRgb2Rgb_NoBlend(dest_scan, src_scan, src_left, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan);
   4026                 break;
   4027             case 0+2:
   4028                 _CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan,
   4029                                                   src_extra_alpha);
   4030                 break;
   4031             case 0+2+8:
   4032                 _CompositeRow_1bppRgb2Rgba_NoBlend(dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan,
   4033                                                    dst_extra_alpha);
   4034                 break;
   4035                 break;
   4036         }
   4037     }
   4038 }
   4039 void CFX_ScanlineCompositor::CompositeByteMaskLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, FX_LPCBYTE clip_scan,
   4040         FX_LPBYTE dst_extra_alpha)
   4041 {
   4042     if (m_DestFormat == FXDIB_8bppMask) {
   4043         _CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width, clip_scan);
   4044     } else if ((m_DestFormat & 0xff) == 8) {
   4045         if (m_DestFormat & 0x0200) {
   4046             _CompositeRow_ByteMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, width, clip_scan, dst_extra_alpha);
   4047         } else {
   4048             _CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, width, clip_scan);
   4049         }
   4050     } else if (m_bRgbByteOrder) {
   4051         if (m_DestFormat == FXDIB_Argb)
   4052             _CompositeRow_ByteMask2Argb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4053                     width, m_BlendType, clip_scan);
   4054         else
   4055             _CompositeRow_ByteMask2Rgb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4056                                                     width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   4057         return;
   4058     } else if (m_DestFormat == FXDIB_Argb)
   4059         _CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4060                                     width, m_BlendType, clip_scan);
   4061     else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32)
   4062         _CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4063                                    width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   4064     else if (m_DestFormat == FXDIB_Rgba)
   4065         _CompositeRow_ByteMask2Rgba(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4066                                     width, m_BlendType, clip_scan, dst_extra_alpha);
   4067 }
   4068 void CFX_ScanlineCompositor::CompositeBitMaskLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width, FX_LPCBYTE clip_scan,
   4069         FX_LPBYTE dst_extra_alpha)
   4070 {
   4071     if (m_DestFormat == FXDIB_8bppMask) {
   4072         _CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left, width, clip_scan);
   4073     } else if ((m_DestFormat & 0xff) == 8) {
   4074         if (m_DestFormat & 0x0200)
   4075             _CompositeRow_BitMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, src_left, width, clip_scan,
   4076                                         dst_extra_alpha);
   4077         else {
   4078             _CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, src_left, width, clip_scan);
   4079         }
   4080     } else if (m_bRgbByteOrder) {
   4081         if (m_DestFormat == FXDIB_Argb)
   4082             _CompositeRow_BitMask2Argb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4083                                                     src_left, width, m_BlendType, clip_scan);
   4084         else
   4085             _CompositeRow_BitMask2Rgb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4086                                                    src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   4087         return;
   4088     } else if (m_DestFormat == FXDIB_Argb)
   4089         _CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4090                                    src_left, width, m_BlendType, clip_scan);
   4091     else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32)
   4092         _CompositeRow_BitMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   4093                                   src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   4094 }
   4095 FX_BOOL CFX_DIBitmap::CompositeBitmap(int dest_left, int dest_top, int width, int height,
   4096                                       const CFX_DIBSource* pSrcBitmap, int src_left, int src_top,
   4097                                       int blend_type, const CFX_ClipRgn* pClipRgn, FX_BOOL bRgbByteOrder, void* pIccTransform)
   4098 {
   4099     if (m_pBuffer == NULL) {
   4100         return FALSE;
   4101     }
   4102     ASSERT(!pSrcBitmap->IsAlphaMask());
   4103     ASSERT(m_bpp >= 8);
   4104     if (pSrcBitmap->IsAlphaMask() || m_bpp < 8) {
   4105         return FALSE;
   4106     }
   4107     GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(),
   4108                    src_left, src_top, pClipRgn);
   4109     if (width == 0 || height == 0) {
   4110         return TRUE;
   4111     }
   4112     const CFX_DIBitmap* pClipMask = NULL;
   4113     FX_RECT clip_box;
   4114     if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
   4115         ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF);
   4116         pClipMask = pClipRgn->GetMask();
   4117         clip_box = pClipRgn->GetBox();
   4118     }
   4119     CFX_ScanlineCompositor compositor;
   4120     if (!compositor.Init(GetFormat(), pSrcBitmap->GetFormat(), width, pSrcBitmap->GetPalette(), 0, blend_type,
   4121                          pClipMask != NULL, bRgbByteOrder, 0, pIccTransform)) {
   4122         return FALSE;
   4123     }
   4124     int dest_Bpp = m_bpp / 8;
   4125     int src_Bpp = pSrcBitmap->GetBPP() / 8;
   4126     FX_BOOL bRgb = src_Bpp > 1 && !pSrcBitmap->IsCmykImage();
   4127     CFX_DIBitmap* pSrcAlphaMask = pSrcBitmap->m_pAlphaMask;
   4128     for (int row = 0; row < height; row ++) {
   4129         FX_LPBYTE dest_scan = m_pBuffer + (dest_top + row) * m_Pitch + dest_left * dest_Bpp;
   4130         FX_LPCBYTE src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left * src_Bpp;
   4131         FX_LPCBYTE src_scan_extra_alpha = pSrcAlphaMask ? pSrcAlphaMask->GetScanline(src_top + row) + src_left : NULL;
   4132         FX_LPBYTE dst_scan_extra_alpha = m_pAlphaMask ? (FX_LPBYTE)m_pAlphaMask->GetScanline(dest_top + row) + dest_left : NULL;
   4133         FX_LPCBYTE clip_scan = NULL;
   4134         if (pClipMask) {
   4135             clip_scan = pClipMask->m_pBuffer + (dest_top + row - clip_box.top) * pClipMask->m_Pitch + (dest_left - clip_box.left);
   4136         }
   4137         if (bRgb) {
   4138             compositor.CompositeRgbBitmapLine(dest_scan, src_scan, width, clip_scan, src_scan_extra_alpha, dst_scan_extra_alpha);
   4139         } else {
   4140             compositor.CompositePalBitmapLine(dest_scan, src_scan, src_left, width, clip_scan, src_scan_extra_alpha, dst_scan_extra_alpha);
   4141         }
   4142     }
   4143     return TRUE;
   4144 }
   4145 FX_BOOL CFX_DIBitmap::CompositeMask(int dest_left, int dest_top, int width, int height,
   4146                                     const CFX_DIBSource* pMask, FX_DWORD color, int src_left, int src_top,
   4147                                     int blend_type, const CFX_ClipRgn* pClipRgn, FX_BOOL bRgbByteOrder, int alpha_flag, void* pIccTransform)
   4148 {
   4149     if (m_pBuffer == NULL) {
   4150         return FALSE;
   4151     }
   4152     ASSERT(pMask->IsAlphaMask());
   4153     ASSERT(m_bpp >= 8);
   4154     if (!pMask->IsAlphaMask() || m_bpp < 8) {
   4155         return FALSE;
   4156     }
   4157     GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(), pMask->GetHeight(), src_left, src_top, pClipRgn);
   4158     if (width == 0 || height == 0) {
   4159         return TRUE;
   4160     }
   4161     int src_alpha = (FX_BYTE)(alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color);
   4162     if (src_alpha == 0) {
   4163         return TRUE;
   4164     }
   4165     const CFX_DIBitmap* pClipMask = NULL;
   4166     FX_RECT clip_box;
   4167     if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
   4168         ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF);
   4169         pClipMask = pClipRgn->GetMask();
   4170         clip_box = pClipRgn->GetBox();
   4171     }
   4172     int src_bpp = pMask->GetBPP();
   4173     int Bpp = GetBPP() / 8;
   4174     CFX_ScanlineCompositor compositor;
   4175     if (!compositor.Init(GetFormat(), pMask->GetFormat(), width, NULL, color, blend_type, pClipMask != NULL, bRgbByteOrder, alpha_flag, pIccTransform)) {
   4176         return FALSE;
   4177     }
   4178     for (int row = 0; row < height; row ++) {
   4179         FX_LPBYTE dest_scan = m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp;
   4180         FX_LPCBYTE src_scan = pMask->GetScanline(src_top + row);
   4181         FX_LPBYTE dst_scan_extra_alpha = m_pAlphaMask ? (FX_LPBYTE)m_pAlphaMask->GetScanline(dest_top + row) + dest_left : NULL;
   4182         FX_LPCBYTE clip_scan = NULL;
   4183         if (pClipMask) {
   4184             clip_scan = pClipMask->m_pBuffer + (dest_top + row - clip_box.top) * pClipMask->m_Pitch + (dest_left - clip_box.left);
   4185         }
   4186         if (src_bpp == 1) {
   4187             compositor.CompositeBitMaskLine(dest_scan, src_scan, src_left, width, clip_scan, dst_scan_extra_alpha);
   4188         } else {
   4189             compositor.CompositeByteMaskLine(dest_scan, src_scan + src_left, width, clip_scan, dst_scan_extra_alpha);
   4190         }
   4191     }
   4192     return TRUE;
   4193 }
   4194 FX_BOOL CFX_DIBitmap::CompositeRect(int left, int top, int width, int height, FX_DWORD color, int alpha_flag, void* pIccTransform)
   4195 {
   4196     if (m_pBuffer == NULL) {
   4197         return FALSE;
   4198     }
   4199     int src_alpha = (alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color);
   4200     if (src_alpha == 0) {
   4201         return TRUE;
   4202     }
   4203     FX_RECT rect(left, top, left + width, top + height);
   4204     rect.Intersect(0, 0, m_Width, m_Height);
   4205     if (rect.IsEmpty()) {
   4206         return TRUE;
   4207     }
   4208     width = rect.Width();
   4209     FX_DWORD dst_color;
   4210     if (alpha_flag >> 8) {
   4211         dst_color = FXCMYK_TODIB(color);
   4212     } else {
   4213         dst_color = FXARGB_TODIB(color);
   4214     }
   4215     FX_LPBYTE color_p = (FX_LPBYTE)&dst_color;
   4216     if (m_bpp == 8) {
   4217         FX_BYTE gray = 255;
   4218         if (!IsAlphaMask()) {
   4219             if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() && CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
   4220                 ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   4221                 pIccModule->TranslateScanline(pIccTransform, &gray, color_p, 1);
   4222             } else {
   4223                 if (alpha_flag >> 8) {
   4224                     FX_BYTE r, g, b;
   4225                     AdobeCMYK_to_sRGB1(color_p[0], color_p[1], color_p[2], color_p[3],
   4226                                        r, g, b);
   4227                     gray = FXRGB2GRAY(r, g, b);
   4228                 } else {
   4229                     gray = (FX_BYTE)FXRGB2GRAY((int)color_p[2], color_p[1], color_p[0]);
   4230                 }
   4231             }
   4232             if (IsCmykImage()) {
   4233                 gray = ~gray;
   4234             }
   4235         }
   4236         for (int row = rect.top; row < rect.bottom; row ++) {
   4237             FX_LPBYTE dest_scan = m_pBuffer + row * m_Pitch + rect.left;
   4238             if (src_alpha == 255) {
   4239                 FXSYS_memset8(dest_scan, gray, width);
   4240             } else
   4241                 for (int col = 0; col < width; col ++) {
   4242                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
   4243                     dest_scan ++;
   4244                 }
   4245         }
   4246         return TRUE;
   4247     } else if (m_bpp == 1) {
   4248         ASSERT(!IsCmykImage() && (FX_BYTE)(alpha_flag >> 8) == 0);
   4249         int left_shift = rect.left % 8;
   4250         int right_shift = rect.right % 8;
   4251         int width = rect.right / 8 - rect.left / 8;
   4252         int index = 0;
   4253         if (m_pPalette == NULL) {
   4254             index = ((FX_BYTE)color == 0xff) ? 1 : 0;
   4255         } else {
   4256             for (int i = 0; i < 2; i ++)
   4257                 if (m_pPalette[i] == color) {
   4258                     index = i;
   4259                 }
   4260         }
   4261         for (int row = rect.top; row < rect.bottom; row ++) {
   4262             FX_BYTE* dest_scan_top = (FX_BYTE*)GetScanline(row) + rect.left / 8;
   4263             FX_BYTE* dest_scan_top_r = (FX_BYTE*)GetScanline(row) + rect.right / 8;
   4264             FX_BYTE left_flag =  *dest_scan_top & (255 << (8 - left_shift));
   4265             FX_BYTE right_flag = *dest_scan_top_r & (255 >> right_shift);
   4266             if (width) {
   4267                 FXSYS_memset8(dest_scan_top + 1, index ? 255 : 0, width - 1);
   4268                 if (!index) {
   4269                     *dest_scan_top &= left_flag;
   4270                     *dest_scan_top_r &= right_flag;
   4271                 } else {
   4272                     *dest_scan_top |= ~left_flag;
   4273                     *dest_scan_top_r |= ~right_flag;
   4274                 }
   4275             } else {
   4276                 if (!index) {
   4277                     *dest_scan_top &= left_flag | right_flag;
   4278                 } else {
   4279                     *dest_scan_top |= ~(left_flag | right_flag);
   4280                 }
   4281             }
   4282         }
   4283         return TRUE;
   4284     }
   4285     ASSERT(m_bpp >= 24);
   4286     if (m_bpp < 24) {
   4287         return FALSE;
   4288     }
   4289     if (pIccTransform && CFX_GEModule::Get()->GetCodecModule()) {
   4290         ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   4291         pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1);
   4292     } else {
   4293         if (alpha_flag >> 8 && !IsCmykImage())
   4294             AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), FXSYS_GetYValue(color), FXSYS_GetKValue(color),
   4295                                color_p[2], color_p[1], color_p[0]);
   4296         else if (!(alpha_flag >> 8) && IsCmykImage()) {
   4297             return FALSE;
   4298         }
   4299     }
   4300     if(!IsCmykImage()) {
   4301         color_p[3] = (FX_BYTE)src_alpha;
   4302     }
   4303     int Bpp = m_bpp / 8;
   4304     FX_BOOL bAlpha = HasAlpha();
   4305     FX_BOOL bArgb = GetFormat() == FXDIB_Argb ? TRUE : FALSE;
   4306     if (src_alpha == 255) {
   4307         for (int row = rect.top; row < rect.bottom; row ++) {
   4308             FX_LPBYTE dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp;
   4309             FX_LPBYTE dest_scan_alpha = m_pAlphaMask ? (FX_LPBYTE)m_pAlphaMask->GetScanline(row) + rect.left : NULL;
   4310             if (dest_scan_alpha) {
   4311                 FXSYS_memset8(dest_scan_alpha, 0xff, width);
   4312             }
   4313             if (Bpp == 4) {
   4314                 FX_DWORD* scan = (FX_DWORD*)dest_scan;
   4315                 for (int col = 0; col < width; col ++) {
   4316                     *scan ++ = dst_color;
   4317                 }
   4318             } else {
   4319                 for (int col = 0; col < width; col ++) {
   4320                     *dest_scan ++ = color_p[0];
   4321                     *dest_scan ++ = color_p[1];
   4322                     *dest_scan ++ = color_p[2];
   4323                 }
   4324             }
   4325         }
   4326         return TRUE;
   4327     }
   4328     for (int row = rect.top; row < rect.bottom; row ++) {
   4329         FX_LPBYTE dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp;
   4330         if (bAlpha) {
   4331             if (bArgb) {
   4332                 for (int col = 0; col < width; col ++) {
   4333                     FX_BYTE back_alpha = dest_scan[3];
   4334                     if (back_alpha == 0) {
   4335                         FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, color_p[2], color_p[1], color_p[0]));
   4336                         dest_scan += 4;
   4337                         continue;
   4338                     }
   4339                     FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   4340                     int alpha_ratio = src_alpha * 255 / dest_alpha;
   4341                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[0], alpha_ratio);
   4342                     dest_scan ++;
   4343                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[1], alpha_ratio);
   4344                     dest_scan ++;
   4345                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[2], alpha_ratio);
   4346                     dest_scan ++;
   4347                     *dest_scan++ = dest_alpha;
   4348                 }
   4349             } else {
   4350                 FX_LPBYTE dest_scan_alpha = (FX_LPBYTE)m_pAlphaMask->GetScanline(row) + rect.left;
   4351                 for (int col = 0; col < width; col ++) {
   4352                     FX_BYTE back_alpha = *dest_scan_alpha;
   4353                     if (back_alpha == 0) {
   4354                         *dest_scan_alpha++ = src_alpha;
   4355                         FXSYS_memcpy32(dest_scan, color_p, Bpp);
   4356                         dest_scan += Bpp;
   4357                         continue;
   4358                     }
   4359                     FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   4360                     *dest_scan_alpha ++ = dest_alpha;
   4361                     int alpha_ratio = src_alpha * 255 / dest_alpha;
   4362                     for(int comps = 0; comps < Bpp; comps ++) {
   4363                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], alpha_ratio);
   4364                         dest_scan ++;
   4365                     }
   4366                 }
   4367             }
   4368         } else {
   4369             for (int col = 0; col < width; col ++) {
   4370                 for(int comps = 0; comps < Bpp; comps ++) {
   4371                     if (comps == 3) {
   4372                         *dest_scan ++ = 255;
   4373                         continue;
   4374                     }
   4375                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], src_alpha);
   4376                     dest_scan ++;
   4377                 }
   4378             }
   4379         }
   4380     }
   4381     return TRUE;
   4382 }
   4383 CFX_BitmapComposer::CFX_BitmapComposer()
   4384 {
   4385     m_pScanlineV = NULL;
   4386     m_pScanlineAlphaV = NULL;
   4387     m_pClipScanV = NULL;
   4388     m_pAddClipScan = NULL;
   4389     m_bRgbByteOrder = FALSE;
   4390     m_BlendType = FXDIB_BLEND_NORMAL;
   4391 }
   4392 CFX_BitmapComposer::~CFX_BitmapComposer()
   4393 {
   4394     if (m_pScanlineV) {
   4395         FX_Free(m_pScanlineV);
   4396     }
   4397     if (m_pScanlineAlphaV) {
   4398         FX_Free(m_pScanlineAlphaV);
   4399     }
   4400     if (m_pClipScanV) {
   4401         FX_Free(m_pClipScanV);
   4402     }
   4403     if (m_pAddClipScan) {
   4404         FX_Free(m_pAddClipScan);
   4405     }
   4406 }
   4407 void CFX_BitmapComposer::Compose(CFX_DIBitmap* pDest, const CFX_ClipRgn* pClipRgn, int bitmap_alpha,
   4408                                  FX_DWORD mask_color, FX_RECT& dest_rect, FX_BOOL bVertical,
   4409                                  FX_BOOL bFlipX, FX_BOOL bFlipY, FX_BOOL bRgbByteOrder,
   4410                                  int alpha_flag, void* pIccTransform, int blend_type)
   4411 {
   4412     m_pBitmap = pDest;
   4413     m_pClipRgn = pClipRgn;
   4414     m_DestLeft = dest_rect.left;
   4415     m_DestTop = dest_rect.top;
   4416     m_DestWidth = dest_rect.Width();
   4417     m_DestHeight = dest_rect.Height();
   4418     m_BitmapAlpha = bitmap_alpha;
   4419     m_MaskColor = mask_color;
   4420     m_pClipMask = NULL;
   4421     if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
   4422         m_pClipMask = pClipRgn->GetMask();
   4423     }
   4424     m_bVertical = bVertical;
   4425     m_bFlipX = bFlipX;
   4426     m_bFlipY = bFlipY;
   4427     m_AlphaFlag = alpha_flag;
   4428     m_pIccTransform = pIccTransform;
   4429     m_bRgbByteOrder = bRgbByteOrder;
   4430     m_BlendType = blend_type;
   4431 }
   4432 FX_BOOL CFX_BitmapComposer::SetInfo(int width, int height, FXDIB_Format src_format, FX_DWORD* pSrcPalette)
   4433 {
   4434     m_SrcFormat = src_format;
   4435     if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, pSrcPalette, m_MaskColor, FXDIB_BLEND_NORMAL,
   4436                            m_pClipMask != NULL || (m_BitmapAlpha < 255), m_bRgbByteOrder, m_AlphaFlag, m_pIccTransform)) {
   4437         return FALSE;
   4438     }
   4439     if (m_bVertical) {
   4440         m_pScanlineV = FX_Alloc(FX_BYTE, m_pBitmap->GetBPP() / 8 * width + 4);
   4441         m_pClipScanV = FX_Alloc(FX_BYTE, m_pBitmap->GetHeight());
   4442         if (m_pBitmap->m_pAlphaMask) {
   4443             m_pScanlineAlphaV = FX_Alloc(FX_BYTE, width + 4);
   4444         }
   4445     }
   4446     if (m_BitmapAlpha < 255) {
   4447         m_pAddClipScan = FX_Alloc(FX_BYTE, m_bVertical ? m_pBitmap->GetHeight() : m_pBitmap->GetWidth());
   4448     }
   4449     return TRUE;
   4450 }
   4451 void CFX_BitmapComposer::DoCompose(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int dest_width, FX_LPCBYTE clip_scan,
   4452                                    FX_LPCBYTE src_extra_alpha, FX_LPBYTE dst_extra_alpha)
   4453 {
   4454     if (m_BitmapAlpha < 255) {
   4455         if (clip_scan) {
   4456             for (int i = 0; i < dest_width; i ++) {
   4457                 m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255;
   4458             }
   4459         } else {
   4460             FXSYS_memset8(m_pAddClipScan, m_BitmapAlpha, dest_width);
   4461         }
   4462         clip_scan = m_pAddClipScan;
   4463     }
   4464     if (m_SrcFormat == FXDIB_8bppMask) {
   4465         m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width, clip_scan, dst_extra_alpha);
   4466     } else if ((m_SrcFormat & 0xff) == 8) {
   4467         m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width, clip_scan, src_extra_alpha, dst_extra_alpha);
   4468     } else {
   4469         m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width, clip_scan, src_extra_alpha, dst_extra_alpha);
   4470     }
   4471 }
   4472 void CFX_BitmapComposer::ComposeScanline(int line, FX_LPCBYTE scanline, FX_LPCBYTE scan_extra_alpha)
   4473 {
   4474     if (m_bVertical) {
   4475         ComposeScanlineV(line, scanline, scan_extra_alpha);
   4476         return;
   4477     }
   4478     FX_LPCBYTE clip_scan = NULL;
   4479     if (m_pClipMask)
   4480         clip_scan = m_pClipMask->GetBuffer() + (m_DestTop + line - m_pClipRgn->GetBox().top) *
   4481                     m_pClipMask->GetPitch() + (m_DestLeft - m_pClipRgn->GetBox().left);
   4482     FX_LPBYTE dest_scan = (FX_LPBYTE)m_pBitmap->GetScanline(line + m_DestTop) +
   4483                           m_DestLeft * m_pBitmap->GetBPP() / 8;
   4484     FX_LPBYTE dest_alpha_scan = m_pBitmap->m_pAlphaMask ?
   4485                                 (FX_LPBYTE)m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop) + m_DestLeft : NULL;
   4486     DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha, dest_alpha_scan);
   4487 }
   4488 void CFX_BitmapComposer::ComposeScanlineV(int line, FX_LPCBYTE scanline, FX_LPCBYTE scan_extra_alpha)
   4489 {
   4490     int i;
   4491     int Bpp = m_pBitmap->GetBPP() / 8;
   4492     int dest_pitch = m_pBitmap->GetPitch();
   4493     int dest_alpha_pitch = m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetPitch() : 0;
   4494     int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
   4495     FX_LPBYTE dest_buf = m_pBitmap->GetBuffer() + dest_x * Bpp + m_DestTop * dest_pitch;
   4496     FX_LPBYTE dest_alpha_buf = m_pBitmap->m_pAlphaMask ?
   4497                                m_pBitmap->m_pAlphaMask->GetBuffer() + dest_x + m_DestTop * dest_alpha_pitch : NULL;
   4498     if (m_bFlipY) {
   4499         dest_buf += dest_pitch * (m_DestHeight - 1);
   4500         dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1);
   4501     }
   4502     int y_step = dest_pitch;
   4503     int y_alpha_step = dest_alpha_pitch;
   4504     if (m_bFlipY) {
   4505         y_step = -y_step;
   4506         y_alpha_step = -y_alpha_step;
   4507     }
   4508     FX_LPBYTE src_scan = m_pScanlineV;
   4509     FX_LPBYTE dest_scan = dest_buf;
   4510     for (i = 0; i < m_DestHeight; i ++) {
   4511         for (int j = 0; j < Bpp; j ++) {
   4512             *src_scan++ = dest_scan[j];
   4513         }
   4514         dest_scan += y_step;
   4515     }
   4516     FX_LPBYTE src_alpha_scan = m_pScanlineAlphaV;
   4517     FX_LPBYTE dest_alpha_scan = dest_alpha_buf;
   4518     if (dest_alpha_scan) {
   4519         for (i = 0; i < m_DestHeight; i ++) {
   4520             *src_alpha_scan++ = *dest_alpha_scan;
   4521             dest_alpha_scan += y_alpha_step;
   4522         }
   4523     }
   4524     FX_LPBYTE clip_scan = NULL;
   4525     if (m_pClipMask) {
   4526         clip_scan = m_pClipScanV;
   4527         int clip_pitch = m_pClipMask->GetPitch();
   4528         FX_LPCBYTE src_clip = m_pClipMask->GetBuffer() + (m_DestTop - m_pClipRgn->GetBox().top) *
   4529                               clip_pitch + (dest_x - m_pClipRgn->GetBox().left);
   4530         if (m_bFlipY) {
   4531             src_clip += clip_pitch * (m_DestHeight - 1);
   4532             clip_pitch = -clip_pitch;
   4533         }
   4534         for (i = 0; i < m_DestHeight; i ++) {
   4535             clip_scan[i] = *src_clip;
   4536             src_clip += clip_pitch;
   4537         }
   4538     }
   4539     DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan, scan_extra_alpha, m_pScanlineAlphaV);
   4540     src_scan = m_pScanlineV;
   4541     dest_scan = dest_buf;
   4542     for (i = 0; i < m_DestHeight; i ++) {
   4543         for (int j = 0; j < Bpp; j ++) {
   4544             dest_scan[j] = *src_scan++;
   4545         }
   4546         dest_scan += y_step;
   4547     }
   4548     src_alpha_scan = m_pScanlineAlphaV;
   4549     dest_alpha_scan = dest_alpha_buf;
   4550     if (dest_alpha_scan) {
   4551         for (i = 0; i < m_DestHeight; i ++) {
   4552             *dest_alpha_scan = *src_alpha_scan++;
   4553             dest_alpha_scan += y_alpha_step;
   4554         }
   4555     }
   4556 }
   4557