Home | History | Annotate | Download | only in dib
      1 // Copyright 2017 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/fxge/dib/cfx_scanlinecompositor.h"
      8 
      9 #include <algorithm>
     10 
     11 #include "core/fxcodec/fx_codec.h"
     12 
     13 #define FX_CCOLOR(val) (255 - (val))
     14 #define FXDIB_ALPHA_UNION(dest, src) ((dest) + (src) - (dest) * (src) / 255)
     15 #define FXARGB_COPY(dest, src)                    \
     16   *(dest) = *(src), *((dest) + 1) = *((src) + 1), \
     17   *((dest) + 2) = *((src) + 2), *((dest) + 3) = *((src) + 3)
     18 #define FXARGB_RGBORDERCOPY(dest, src)                  \
     19   *((dest) + 3) = *((src) + 3), *(dest) = *((src) + 2), \
     20              *((dest) + 1) = *((src) + 1), *((dest) + 2) = *((src))
     21 
     22 namespace {
     23 
     24 const uint8_t color_sqrt[256] = {
     25     0x00, 0x03, 0x07, 0x0B, 0x0F, 0x12, 0x16, 0x19, 0x1D, 0x20, 0x23, 0x26,
     26     0x29, 0x2C, 0x2F, 0x32, 0x35, 0x37, 0x3A, 0x3C, 0x3F, 0x41, 0x43, 0x46,
     27     0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x57, 0x59, 0x5B, 0x5C,
     28     0x5E, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D,
     29     0x6E, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
     30     0x7B, 0x7C, 0x7D, 0x7E, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
     31     0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x91,
     32     0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C,
     33     0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5,
     34     0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE,
     35     0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7,
     36     0xB7, 0xB8, 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBE, 0xBF,
     37     0xC0, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7,
     38     0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCE,
     39     0xCF, 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6,
     40     0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD,
     41     0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE2, 0xE3, 0xE4,
     42     0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA,
     43     0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE, 0xEF, 0xF0, 0xF0, 0xF1,
     44     0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7,
     45     0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD,
     46     0xFD, 0xFE, 0xFE, 0xFF};
     47 
     48 int Blend(int blend_mode, int back_color, int src_color) {
     49   switch (blend_mode) {
     50     case FXDIB_BLEND_NORMAL:
     51       return src_color;
     52     case FXDIB_BLEND_MULTIPLY:
     53       return src_color * back_color / 255;
     54     case FXDIB_BLEND_SCREEN:
     55       return src_color + back_color - src_color * back_color / 255;
     56     case FXDIB_BLEND_OVERLAY:
     57       return Blend(FXDIB_BLEND_HARDLIGHT, src_color, back_color);
     58     case FXDIB_BLEND_DARKEN:
     59       return src_color < back_color ? src_color : back_color;
     60     case FXDIB_BLEND_LIGHTEN:
     61       return src_color > back_color ? src_color : back_color;
     62     case FXDIB_BLEND_COLORDODGE: {
     63       if (src_color == 255)
     64         return src_color;
     65 
     66       return std::min(back_color * 255 / (255 - src_color), 255);
     67     }
     68     case FXDIB_BLEND_COLORBURN: {
     69       if (src_color == 0)
     70         return src_color;
     71 
     72       return 255 - std::min((255 - back_color) * 255 / src_color, 255);
     73     }
     74     case FXDIB_BLEND_HARDLIGHT:
     75       if (src_color < 128)
     76         return (src_color * back_color * 2) / 255;
     77 
     78       return Blend(FXDIB_BLEND_SCREEN, back_color, 2 * src_color - 255);
     79     case FXDIB_BLEND_SOFTLIGHT: {
     80       if (src_color < 128) {
     81         return back_color -
     82                (255 - 2 * src_color) * back_color * (255 - back_color) / 255 /
     83                    255;
     84       }
     85       return back_color +
     86              (2 * src_color - 255) * (color_sqrt[back_color] - back_color) /
     87                  255;
     88     }
     89     case FXDIB_BLEND_DIFFERENCE:
     90       return back_color < src_color ? src_color - back_color
     91                                     : back_color - src_color;
     92     case FXDIB_BLEND_EXCLUSION:
     93       return back_color + src_color - 2 * back_color * src_color / 255;
     94   }
     95   return src_color;
     96 }
     97 
     98 struct RGB {
     99   int red;
    100   int green;
    101   int blue;
    102 };
    103 
    104 int Lum(RGB color) {
    105   return (color.red * 30 + color.green * 59 + color.blue * 11) / 100;
    106 }
    107 
    108 RGB ClipColor(RGB color) {
    109   int l = Lum(color);
    110   int n = std::min(color.red, std::min(color.green, color.blue));
    111   int x = std::max(color.red, std::max(color.green, color.blue));
    112   if (n < 0) {
    113     color.red = l + ((color.red - l) * l / (l - n));
    114     color.green = l + ((color.green - l) * l / (l - n));
    115     color.blue = l + ((color.blue - l) * l / (l - n));
    116   }
    117   if (x > 255) {
    118     color.red = l + ((color.red - l) * (255 - l) / (x - l));
    119     color.green = l + ((color.green - l) * (255 - l) / (x - l));
    120     color.blue = l + ((color.blue - l) * (255 - l) / (x - l));
    121   }
    122   return color;
    123 }
    124 
    125 RGB SetLum(RGB color, int l) {
    126   int d = l - Lum(color);
    127   color.red += d;
    128   color.green += d;
    129   color.blue += d;
    130   return ClipColor(color);
    131 }
    132 
    133 int Sat(RGB color) {
    134   return std::max(color.red, std::max(color.green, color.blue)) -
    135          std::min(color.red, std::min(color.green, color.blue));
    136 }
    137 
    138 RGB SetSat(RGB color, int s) {
    139   int min = std::min(color.red, std::min(color.green, color.blue));
    140   int max = std::max(color.red, std::max(color.green, color.blue));
    141   if (min == max)
    142     return {0, 0, 0};
    143 
    144   color.red = (color.red - min) * s / (max - min);
    145   color.green = (color.green - min) * s / (max - min);
    146   color.blue = (color.blue - min) * s / (max - min);
    147   return color;
    148 }
    149 
    150 void RGB_Blend(int blend_mode,
    151                const uint8_t* src_scan,
    152                const uint8_t* dest_scan,
    153                int results[3]) {
    154   RGB result = {0, 0, 0};
    155   RGB src;
    156   src.red = src_scan[2];
    157   src.green = src_scan[1];
    158   src.blue = src_scan[0];
    159   RGB back;
    160   back.red = dest_scan[2];
    161   back.green = dest_scan[1];
    162   back.blue = dest_scan[0];
    163   switch (blend_mode) {
    164     case FXDIB_BLEND_HUE:
    165       result = SetLum(SetSat(src, Sat(back)), Lum(back));
    166       break;
    167     case FXDIB_BLEND_SATURATION:
    168       result = SetLum(SetSat(back, Sat(src)), Lum(back));
    169       break;
    170     case FXDIB_BLEND_COLOR:
    171       result = SetLum(src, Lum(back));
    172       break;
    173     case FXDIB_BLEND_LUMINOSITY:
    174       result = SetLum(back, Lum(src));
    175       break;
    176   }
    177   results[0] = result.blue;
    178   results[1] = result.green;
    179   results[2] = result.red;
    180 }
    181 
    182 int GetAlpha(uint8_t src_alpha, const uint8_t* clip_scan, int col) {
    183   return clip_scan ? clip_scan[col] * src_alpha / 255 : src_alpha;
    184 }
    185 
    186 void CompositeRow_AlphaToMask(uint8_t* dest_scan,
    187                               const uint8_t* src_scan,
    188                               int pixel_count,
    189                               const uint8_t* clip_scan,
    190                               uint8_t stride) {
    191   src_scan += stride - 1;
    192   for (int col = 0; col < pixel_count; ++col) {
    193     int src_alpha = GetAlpha(*src_scan, clip_scan, col);
    194     uint8_t back_alpha = *dest_scan;
    195     if (!back_alpha)
    196       *dest_scan = src_alpha;
    197     else if (src_alpha)
    198       *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    199     ++dest_scan;
    200     src_scan += stride;
    201   }
    202 }
    203 
    204 void CompositeRow_Rgb2Mask(uint8_t* dest_scan,
    205                            const uint8_t* src_scan,
    206                            int width,
    207                            const uint8_t* clip_scan) {
    208   if (!clip_scan) {
    209     memset(dest_scan, 0xff, width);
    210     return;
    211   }
    212   for (int i = 0; i < width; ++i) {
    213     *dest_scan = FXDIB_ALPHA_UNION(*dest_scan, *clip_scan);
    214     ++dest_scan;
    215     ++clip_scan;
    216   }
    217 }
    218 
    219 uint8_t GetGray(const uint8_t* src_scan) {
    220   return FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
    221 }
    222 
    223 uint8_t GetGrayWithBlend(const uint8_t* src_scan,
    224                          const uint8_t* dest_scan,
    225                          int blend_type) {
    226   uint8_t gray = GetGray(src_scan);
    227   if (blend_type >= FXDIB_BLEND_NONSEPARABLE)
    228     gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    229   else if (blend_type)
    230     gray = Blend(blend_type, *dest_scan, gray);
    231   return gray;
    232 }
    233 
    234 void CompositeRow_Argb2Graya(uint8_t* dest_scan,
    235                              const uint8_t* src_scan,
    236                              int pixel_count,
    237                              int blend_type,
    238                              const uint8_t* clip_scan,
    239                              const uint8_t* src_alpha_scan,
    240                              uint8_t* dst_alpha_scan) {
    241   uint8_t offset = src_alpha_scan ? 3 : 4;
    242   for (int col = 0; col < pixel_count; ++col) {
    243     const uint8_t* alpha_scan =
    244         src_alpha_scan ? src_alpha_scan++ : &src_scan[3];
    245     uint8_t back_alpha = *dst_alpha_scan;
    246     if (back_alpha == 0) {
    247       int src_alpha = GetAlpha(*alpha_scan, clip_scan, col);
    248       if (src_alpha) {
    249         *dest_scan = GetGray(src_scan);
    250         *dst_alpha_scan = src_alpha;
    251       }
    252       ++dest_scan;
    253       ++dst_alpha_scan;
    254       src_scan += offset;
    255       continue;
    256     }
    257     uint8_t src_alpha = GetAlpha(*alpha_scan, clip_scan, col);
    258     if (src_alpha == 0) {
    259       ++dest_scan;
    260       ++dst_alpha_scan;
    261       src_scan += offset;
    262       continue;
    263     }
    264     *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha);
    265     int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan);
    266     uint8_t gray = GetGray(src_scan);
    267     // TODO(npm): Does this if really need src_alpha_scan or was that a bug?
    268     if (blend_type && src_alpha_scan) {
    269       if (blend_type >= FXDIB_BLEND_NONSEPARABLE)
    270         gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    271       else
    272         gray = Blend(blend_type, *dest_scan, gray);
    273     }
    274     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
    275     ++dest_scan;
    276     ++dst_alpha_scan;
    277     src_scan += offset;
    278   }
    279 }
    280 
    281 void CompositeRow_Argb2Gray(uint8_t* dest_scan,
    282                             const uint8_t* src_scan,
    283                             int pixel_count,
    284                             int blend_type,
    285                             const uint8_t* clip_scan,
    286                             const uint8_t* src_alpha_scan) {
    287   uint8_t gray;
    288   uint8_t offset = src_alpha_scan ? 3 : 4;
    289   for (int col = 0; col < pixel_count; ++col) {
    290     const uint8_t* alpha_scan =
    291         src_alpha_scan ? src_alpha_scan++ : &src_scan[3];
    292     int src_alpha = GetAlpha(*alpha_scan, clip_scan, col);
    293     if (src_alpha) {
    294       gray = GetGrayWithBlend(src_scan, dest_scan, blend_type);
    295       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
    296     }
    297     ++dest_scan;
    298     src_scan += offset;
    299   }
    300 }
    301 
    302 void CompositeRow_Rgb2Gray(uint8_t* dest_scan,
    303                            const uint8_t* src_scan,
    304                            int src_Bpp,
    305                            int pixel_count,
    306                            int blend_type,
    307                            const uint8_t* clip_scan) {
    308   uint8_t gray;
    309   for (int col = 0; col < pixel_count; ++col) {
    310     gray = GetGrayWithBlend(src_scan, dest_scan, blend_type);
    311     if (clip_scan && clip_scan[col] < 255)
    312       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
    313     else
    314       *dest_scan = gray;
    315     ++dest_scan;
    316     src_scan += src_Bpp;
    317   }
    318 }
    319 
    320 void CompositeRow_Rgb2Graya(uint8_t* dest_scan,
    321                             const uint8_t* src_scan,
    322                             int src_Bpp,
    323                             int pixel_count,
    324                             int blend_type,
    325                             const uint8_t* clip_scan,
    326                             uint8_t* dest_alpha_scan) {
    327   for (int col = 0; col < pixel_count; ++col) {
    328     if (blend_type && *dest_alpha_scan == 0) {
    329       *dest_scan = GetGray(src_scan);
    330       ++dest_scan;
    331       ++dest_alpha_scan;
    332       src_scan += src_Bpp;
    333       continue;
    334     }
    335     int src_alpha = clip_scan ? clip_scan[col] : 255;
    336     if (src_alpha == 255) {
    337       *dest_scan = GetGrayWithBlend(src_scan, dest_scan, blend_type);
    338       ++dest_scan;
    339       *dest_alpha_scan = 255;
    340       ++dest_alpha_scan;
    341       src_scan += src_Bpp;
    342       continue;
    343     }
    344     if (src_alpha == 0) {
    345       ++dest_scan;
    346       ++dest_alpha_scan;
    347       src_scan += src_Bpp;
    348       continue;
    349     }
    350     int back_alpha = *dest_alpha_scan;
    351     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    352     *dest_alpha_scan = dest_alpha;
    353     ++dest_alpha_scan;
    354     int alpha_ratio = src_alpha * 255 / dest_alpha;
    355     uint8_t gray = GetGrayWithBlend(src_scan, dest_scan, blend_type);
    356     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
    357     ++dest_scan;
    358     src_scan += src_Bpp;
    359   }
    360 }
    361 
    362 void CompositeRow_Argb2Argb(uint8_t* dest_scan,
    363                             const uint8_t* src_scan,
    364                             int pixel_count,
    365                             int blend_type,
    366                             const uint8_t* clip_scan,
    367                             uint8_t* dest_alpha_scan,
    368                             const uint8_t* src_alpha_scan) {
    369   int blended_colors[3];
    370   uint8_t dest_offset = dest_alpha_scan ? 3 : 4;
    371   uint8_t src_offset = src_alpha_scan ? 3 : 4;
    372   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    373   bool has_src = !!src_alpha_scan;
    374   bool has_dest = !!dest_alpha_scan;
    375   for (int col = 0; col < pixel_count; ++col) {
    376     uint8_t back_alpha = has_dest ? *dest_alpha_scan : dest_scan[3];
    377     const uint8_t* alpha_source = has_src ? src_alpha_scan++ : &src_scan[3];
    378     uint8_t src_alpha = GetAlpha(*alpha_source, clip_scan, col);
    379     if (back_alpha == 0) {
    380       if (!has_dest && !has_src) {
    381         if (clip_scan) {
    382           FXARGB_SETDIB(dest_scan, (FXARGB_GETDIB(src_scan) & 0xffffff) |
    383                                        (src_alpha << 24));
    384         } else {
    385           FXARGB_COPY(dest_scan, src_scan);
    386         }
    387       } else if (has_dest) {
    388         *dest_alpha_scan = src_alpha;
    389         for (int i = 0; i < 3; ++i) {
    390           *dest_scan = *src_scan++;
    391           ++dest_scan;
    392         }
    393         ++dest_alpha_scan;
    394         if (!has_src)
    395           ++src_scan;
    396       } else {
    397         FXARGB_SETDIB(dest_scan, FXARGB_MAKE((src_alpha << 24), src_scan[2],
    398                                              src_scan[1], *src_scan));
    399       }
    400       if (!has_dest) {
    401         dest_scan += dest_offset;
    402         src_scan += src_offset;
    403       }
    404       continue;
    405     }
    406     if (src_alpha == 0) {
    407       dest_scan += dest_offset;
    408       src_scan += src_offset;
    409       if (has_dest)
    410         ++dest_alpha_scan;
    411       continue;
    412     }
    413     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    414     if (has_dest) {
    415       *dest_alpha_scan = dest_alpha;
    416       ++dest_alpha_scan;
    417     } else {
    418       dest_scan[3] = dest_alpha;
    419     }
    420     int alpha_ratio = src_alpha * 255 / dest_alpha;
    421     if (bNonseparableBlend)
    422       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    423     for (int color = 0; color < 3; ++color) {
    424       if (blend_type) {
    425         int blended = bNonseparableBlend
    426                           ? blended_colors[color]
    427                           : Blend(blend_type, *dest_scan, *src_scan);
    428         blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
    429         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
    430       } else {
    431         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
    432       }
    433       ++dest_scan;
    434       ++src_scan;
    435     }
    436     if (!has_dest)
    437       ++dest_scan;
    438     if (!has_src)
    439       ++src_scan;
    440   }
    441 }
    442 
    443 void CompositeRow_Rgb2Argb_Blend_NoClip(uint8_t* dest_scan,
    444                                         const uint8_t* src_scan,
    445                                         int width,
    446                                         int blend_type,
    447                                         int src_Bpp,
    448                                         uint8_t* dest_alpha_scan) {
    449   int blended_colors[3];
    450   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    451   int src_gap = src_Bpp - 3;
    452   for (int col = 0; col < width; ++col) {
    453     uint8_t* dest_alpha = dest_alpha_scan ? dest_alpha_scan : &dest_scan[3];
    454     uint8_t back_alpha = *dest_alpha;
    455     if (back_alpha == 0) {
    456       if (dest_alpha_scan) {
    457         for (int i = 0; i < 3; ++i) {
    458           *dest_scan = *src_scan++;
    459           ++dest_scan;
    460         }
    461         *dest_alpha_scan = 0xff;
    462         ++dest_alpha_scan;
    463       } else {
    464         if (src_Bpp == 4) {
    465           FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
    466         } else {
    467           FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1],
    468                                                src_scan[0]));
    469         }
    470         dest_scan += 4;
    471       }
    472       src_scan += src_Bpp;
    473       continue;
    474     }
    475     *dest_alpha = 0xff;
    476     if (bNonseparableBlend)
    477       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    478     for (int color = 0; color < 3; ++color) {
    479       int src_color = *src_scan;
    480       int blended = bNonseparableBlend
    481                         ? blended_colors[color]
    482                         : Blend(blend_type, *dest_scan, src_color);
    483       *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
    484       ++dest_scan;
    485       ++src_scan;
    486     }
    487     if (dest_alpha_scan)
    488       ++dest_alpha_scan;
    489     else
    490       ++dest_scan;
    491     src_scan += src_gap;
    492   }
    493 }
    494 
    495 void CompositeRow_Rgb2Argb_Blend_Clip(uint8_t* dest_scan,
    496                                       const uint8_t* src_scan,
    497                                       int width,
    498                                       int blend_type,
    499                                       int src_Bpp,
    500                                       const uint8_t* clip_scan,
    501                                       uint8_t* dest_alpha_scan) {
    502   int blended_colors[3];
    503   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    504   int src_gap = src_Bpp - 3;
    505   bool has_dest = !!dest_alpha_scan;
    506   for (int col = 0; col < width; ++col) {
    507     int src_alpha = *clip_scan++;
    508     uint8_t back_alpha = has_dest ? *dest_alpha_scan : dest_scan[3];
    509     if (back_alpha == 0) {
    510       for (int i = 0; i < 3; ++i) {
    511         *dest_scan = *src_scan++;
    512         ++dest_scan;
    513       }
    514       src_scan += src_gap;
    515       if (has_dest)
    516         dest_alpha_scan++;
    517       else
    518         dest_scan++;
    519       continue;
    520     }
    521     if (src_alpha == 0) {
    522       dest_scan += has_dest ? 3 : 4;
    523       if (has_dest)
    524         dest_alpha_scan++;
    525       src_scan += src_Bpp;
    526       continue;
    527     }
    528     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
    529     if (has_dest)
    530       *dest_alpha_scan++ = dest_alpha;
    531     else
    532       dest_scan[3] = dest_alpha;
    533     int alpha_ratio = src_alpha * 255 / dest_alpha;
    534     if (bNonseparableBlend)
    535       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    536     for (int color = 0; color < 3; color++) {
    537       int src_color = *src_scan;
    538       int blended = bNonseparableBlend
    539                         ? blended_colors[color]
    540                         : Blend(blend_type, *dest_scan, src_color);
    541       blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
    542       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
    543       dest_scan++;
    544       src_scan++;
    545     }
    546     src_scan += src_gap;
    547     if (!has_dest)
    548       dest_scan++;
    549   }
    550 }
    551 
    552 void CompositeRow_Rgb2Argb_NoBlend_Clip(uint8_t* dest_scan,
    553                                         const uint8_t* src_scan,
    554                                         int width,
    555                                         int src_Bpp,
    556                                         const uint8_t* clip_scan,
    557                                         uint8_t* dest_alpha_scan) {
    558   int src_gap = src_Bpp - 3;
    559   if (dest_alpha_scan) {
    560     for (int col = 0; col < width; col++) {
    561       int src_alpha = clip_scan[col];
    562       if (src_alpha == 255) {
    563         *dest_scan++ = *src_scan++;
    564         *dest_scan++ = *src_scan++;
    565         *dest_scan++ = *src_scan++;
    566         *dest_alpha_scan++ = 255;
    567         src_scan += src_gap;
    568         continue;
    569       }
    570       if (src_alpha == 0) {
    571         dest_scan += 3;
    572         dest_alpha_scan++;
    573         src_scan += src_Bpp;
    574         continue;
    575       }
    576       int back_alpha = *dest_alpha_scan;
    577       uint8_t dest_alpha =
    578           back_alpha + src_alpha - back_alpha * src_alpha / 255;
    579       *dest_alpha_scan++ = dest_alpha;
    580       int alpha_ratio = src_alpha * 255 / dest_alpha;
    581       for (int color = 0; color < 3; color++) {
    582         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
    583         dest_scan++;
    584         src_scan++;
    585       }
    586       src_scan += src_gap;
    587     }
    588   } else {
    589     for (int col = 0; col < width; col++) {
    590       int src_alpha = clip_scan[col];
    591       if (src_alpha == 255) {
    592         *dest_scan++ = *src_scan++;
    593         *dest_scan++ = *src_scan++;
    594         *dest_scan++ = *src_scan++;
    595         *dest_scan++ = 255;
    596         src_scan += src_gap;
    597         continue;
    598       }
    599       if (src_alpha == 0) {
    600         dest_scan += 4;
    601         src_scan += src_Bpp;
    602         continue;
    603       }
    604       int back_alpha = dest_scan[3];
    605       uint8_t dest_alpha =
    606           back_alpha + src_alpha - back_alpha * src_alpha / 255;
    607       dest_scan[3] = dest_alpha;
    608       int alpha_ratio = src_alpha * 255 / dest_alpha;
    609       for (int color = 0; color < 3; color++) {
    610         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
    611         dest_scan++;
    612         src_scan++;
    613       }
    614       dest_scan++;
    615       src_scan += src_gap;
    616     }
    617   }
    618 }
    619 
    620 void CompositeRow_Rgb2Argb_NoBlend_NoClip(uint8_t* dest_scan,
    621                                           const uint8_t* src_scan,
    622                                           int width,
    623                                           int src_Bpp,
    624                                           uint8_t* dest_alpha_scan) {
    625   if (dest_alpha_scan) {
    626     int src_gap = src_Bpp - 3;
    627     for (int col = 0; col < width; col++) {
    628       *dest_scan++ = *src_scan++;
    629       *dest_scan++ = *src_scan++;
    630       *dest_scan++ = *src_scan++;
    631       *dest_alpha_scan++ = 0xff;
    632       src_scan += src_gap;
    633     }
    634   } else {
    635     for (int col = 0; col < width; col++) {
    636       if (src_Bpp == 4) {
    637         FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
    638       } else {
    639         FXARGB_SETDIB(dest_scan,
    640                       FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
    641       }
    642       dest_scan += 4;
    643       src_scan += src_Bpp;
    644     }
    645   }
    646 }
    647 
    648 void CompositeRow_Argb2Rgb_Blend(uint8_t* dest_scan,
    649                                  const uint8_t* src_scan,
    650                                  int width,
    651                                  int blend_type,
    652                                  int dest_Bpp,
    653                                  const uint8_t* clip_scan,
    654                                  const uint8_t* src_alpha_scan) {
    655   int blended_colors[3];
    656   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    657   int dest_gap = dest_Bpp - 3;
    658   if (src_alpha_scan) {
    659     for (int col = 0; col < width; col++) {
    660       uint8_t src_alpha;
    661       if (clip_scan) {
    662         src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255;
    663       } else {
    664         src_alpha = *src_alpha_scan++;
    665       }
    666       if (src_alpha == 0) {
    667         dest_scan += dest_Bpp;
    668         src_scan += 3;
    669         continue;
    670       }
    671       if (bNonseparableBlend) {
    672         RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    673       }
    674       for (int color = 0; color < 3; color++) {
    675         int back_color = *dest_scan;
    676         int blended = bNonseparableBlend
    677                           ? blended_colors[color]
    678                           : Blend(blend_type, back_color, *src_scan);
    679         *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
    680         dest_scan++;
    681         src_scan++;
    682       }
    683       dest_scan += dest_gap;
    684     }
    685   } else {
    686     for (int col = 0; col < width; col++) {
    687       uint8_t src_alpha;
    688       if (clip_scan) {
    689         src_alpha = src_scan[3] * (*clip_scan++) / 255;
    690       } else {
    691         src_alpha = src_scan[3];
    692       }
    693       if (src_alpha == 0) {
    694         dest_scan += dest_Bpp;
    695         src_scan += 4;
    696         continue;
    697       }
    698       if (bNonseparableBlend) {
    699         RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    700       }
    701       for (int color = 0; color < 3; color++) {
    702         int back_color = *dest_scan;
    703         int blended = bNonseparableBlend
    704                           ? blended_colors[color]
    705                           : Blend(blend_type, back_color, *src_scan);
    706         *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
    707         dest_scan++;
    708         src_scan++;
    709       }
    710       dest_scan += dest_gap;
    711       src_scan++;
    712     }
    713   }
    714 }
    715 
    716 void CompositeRow_Argb2Rgb_NoBlend(uint8_t* dest_scan,
    717                                    const uint8_t* src_scan,
    718                                    int width,
    719                                    int dest_Bpp,
    720                                    const uint8_t* clip_scan,
    721                                    const uint8_t* src_alpha_scan) {
    722   int dest_gap = dest_Bpp - 3;
    723   if (src_alpha_scan) {
    724     for (int col = 0; col < width; col++) {
    725       uint8_t src_alpha;
    726       if (clip_scan) {
    727         src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255;
    728       } else {
    729         src_alpha = *src_alpha_scan++;
    730       }
    731       if (src_alpha == 255) {
    732         *dest_scan++ = *src_scan++;
    733         *dest_scan++ = *src_scan++;
    734         *dest_scan++ = *src_scan++;
    735         dest_scan += dest_gap;
    736         continue;
    737       }
    738       if (src_alpha == 0) {
    739         dest_scan += dest_Bpp;
    740         src_scan += 3;
    741         continue;
    742       }
    743       for (int color = 0; color < 3; color++) {
    744         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
    745         dest_scan++;
    746         src_scan++;
    747       }
    748       dest_scan += dest_gap;
    749     }
    750   } else {
    751     for (int col = 0; col < width; col++) {
    752       uint8_t src_alpha;
    753       if (clip_scan) {
    754         src_alpha = src_scan[3] * (*clip_scan++) / 255;
    755       } else {
    756         src_alpha = src_scan[3];
    757       }
    758       if (src_alpha == 255) {
    759         *dest_scan++ = *src_scan++;
    760         *dest_scan++ = *src_scan++;
    761         *dest_scan++ = *src_scan++;
    762         dest_scan += dest_gap;
    763         src_scan++;
    764         continue;
    765       }
    766       if (src_alpha == 0) {
    767         dest_scan += dest_Bpp;
    768         src_scan += 4;
    769         continue;
    770       }
    771       for (int color = 0; color < 3; color++) {
    772         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
    773         dest_scan++;
    774         src_scan++;
    775       }
    776       dest_scan += dest_gap;
    777       src_scan++;
    778     }
    779   }
    780 }
    781 
    782 void CompositeRow_Rgb2Rgb_Blend_NoClip(uint8_t* dest_scan,
    783                                        const uint8_t* src_scan,
    784                                        int width,
    785                                        int blend_type,
    786                                        int dest_Bpp,
    787                                        int src_Bpp) {
    788   int blended_colors[3];
    789   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    790   int dest_gap = dest_Bpp - 3;
    791   int src_gap = src_Bpp - 3;
    792   for (int col = 0; col < width; col++) {
    793     if (bNonseparableBlend) {
    794       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    795     }
    796     for (int color = 0; color < 3; color++) {
    797       int back_color = *dest_scan;
    798       int src_color = *src_scan;
    799       int blended = bNonseparableBlend
    800                         ? blended_colors[color]
    801                         : Blend(blend_type, back_color, src_color);
    802       *dest_scan = blended;
    803       dest_scan++;
    804       src_scan++;
    805     }
    806     dest_scan += dest_gap;
    807     src_scan += src_gap;
    808   }
    809 }
    810 
    811 void CompositeRow_Rgb2Rgb_Blend_Clip(uint8_t* dest_scan,
    812                                      const uint8_t* src_scan,
    813                                      int width,
    814                                      int blend_type,
    815                                      int dest_Bpp,
    816                                      int src_Bpp,
    817                                      const uint8_t* clip_scan) {
    818   int blended_colors[3];
    819   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    820   int dest_gap = dest_Bpp - 3;
    821   int src_gap = src_Bpp - 3;
    822   for (int col = 0; col < width; col++) {
    823     uint8_t src_alpha = *clip_scan++;
    824     if (src_alpha == 0) {
    825       dest_scan += dest_Bpp;
    826       src_scan += src_Bpp;
    827       continue;
    828     }
    829     if (bNonseparableBlend) {
    830       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
    831     }
    832     for (int color = 0; color < 3; color++) {
    833       int src_color = *src_scan;
    834       int back_color = *dest_scan;
    835       int blended = bNonseparableBlend
    836                         ? blended_colors[color]
    837                         : Blend(blend_type, back_color, src_color);
    838       *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
    839       dest_scan++;
    840       src_scan++;
    841     }
    842     dest_scan += dest_gap;
    843     src_scan += src_gap;
    844   }
    845 }
    846 
    847 void CompositeRow_Rgb2Rgb_NoBlend_NoClip(uint8_t* dest_scan,
    848                                          const uint8_t* src_scan,
    849                                          int width,
    850                                          int dest_Bpp,
    851                                          int src_Bpp) {
    852   if (dest_Bpp == src_Bpp) {
    853     memcpy(dest_scan, src_scan, width * dest_Bpp);
    854     return;
    855   }
    856   for (int col = 0; col < width; col++) {
    857     dest_scan[0] = src_scan[0];
    858     dest_scan[1] = src_scan[1];
    859     dest_scan[2] = src_scan[2];
    860     dest_scan += dest_Bpp;
    861     src_scan += src_Bpp;
    862   }
    863 }
    864 
    865 void CompositeRow_Rgb2Rgb_NoBlend_Clip(uint8_t* dest_scan,
    866                                        const uint8_t* src_scan,
    867                                        int width,
    868                                        int dest_Bpp,
    869                                        int src_Bpp,
    870                                        const uint8_t* clip_scan) {
    871   for (int col = 0; col < width; col++) {
    872     int src_alpha = clip_scan[col];
    873     if (src_alpha == 255) {
    874       dest_scan[0] = src_scan[0];
    875       dest_scan[1] = src_scan[1];
    876       dest_scan[2] = src_scan[2];
    877     } else if (src_alpha) {
    878       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
    879       dest_scan++;
    880       src_scan++;
    881       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
    882       dest_scan++;
    883       src_scan++;
    884       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
    885       dest_scan += dest_Bpp - 2;
    886       src_scan += src_Bpp - 2;
    887       continue;
    888     }
    889     dest_scan += dest_Bpp;
    890     src_scan += src_Bpp;
    891   }
    892 }
    893 
    894 void CompositeRow_8bppPal2Gray(uint8_t* dest_scan,
    895                                const uint8_t* src_scan,
    896                                const uint8_t* pPalette,
    897                                int pixel_count,
    898                                int blend_type,
    899                                const uint8_t* clip_scan,
    900                                const uint8_t* src_alpha_scan) {
    901   if (src_alpha_scan) {
    902     if (blend_type) {
    903       bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    904       for (int col = 0; col < pixel_count; col++) {
    905         uint8_t gray = pPalette[*src_scan];
    906         int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col);
    907         if (bNonseparableBlend)
    908           gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    909         else
    910           gray = Blend(blend_type, *dest_scan, gray);
    911         if (src_alpha)
    912           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
    913         else
    914           *dest_scan = gray;
    915         dest_scan++;
    916         src_scan++;
    917       }
    918       return;
    919     }
    920     for (int col = 0; col < pixel_count; col++) {
    921       uint8_t gray = pPalette[*src_scan];
    922       int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col);
    923       if (src_alpha)
    924         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
    925       else
    926         *dest_scan = gray;
    927       dest_scan++;
    928       src_scan++;
    929     }
    930   } else {
    931     if (blend_type) {
    932       bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    933       for (int col = 0; col < pixel_count; col++) {
    934         uint8_t gray = pPalette[*src_scan];
    935         if (bNonseparableBlend)
    936           gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    937         else
    938           gray = Blend(blend_type, *dest_scan, gray);
    939         if (clip_scan && clip_scan[col] < 255)
    940           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
    941         else
    942           *dest_scan = gray;
    943         dest_scan++;
    944         src_scan++;
    945       }
    946       return;
    947     }
    948     for (int col = 0; col < pixel_count; col++) {
    949       uint8_t gray = pPalette[*src_scan];
    950       if (clip_scan && clip_scan[col] < 255)
    951         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
    952       else
    953         *dest_scan = gray;
    954       dest_scan++;
    955       src_scan++;
    956     }
    957   }
    958 }
    959 
    960 void CompositeRow_8bppPal2Graya(uint8_t* dest_scan,
    961                                 const uint8_t* src_scan,
    962                                 const uint8_t* pPalette,
    963                                 int pixel_count,
    964                                 int blend_type,
    965                                 const uint8_t* clip_scan,
    966                                 uint8_t* dest_alpha_scan,
    967                                 const uint8_t* src_alpha_scan) {
    968   if (src_alpha_scan) {
    969     if (blend_type) {
    970       bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
    971       for (int col = 0; col < pixel_count; col++) {
    972         uint8_t gray = pPalette[*src_scan];
    973         src_scan++;
    974         uint8_t back_alpha = *dest_alpha_scan;
    975         if (back_alpha == 0) {
    976           int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col);
    977           if (src_alpha) {
    978             *dest_scan = gray;
    979             *dest_alpha_scan = src_alpha;
    980           }
    981           dest_scan++;
    982           dest_alpha_scan++;
    983           continue;
    984         }
    985         uint8_t src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col);
    986         if (src_alpha == 0) {
    987           dest_scan++;
    988           dest_alpha_scan++;
    989           continue;
    990         }
    991         *dest_alpha_scan =
    992             back_alpha + src_alpha - back_alpha * src_alpha / 255;
    993         int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan);
    994         if (bNonseparableBlend)
    995           gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
    996         else
    997           gray = Blend(blend_type, *dest_scan, gray);
    998         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
    999         dest_alpha_scan++;
   1000         dest_scan++;
   1001       }
   1002       return;
   1003     }
   1004     for (int col = 0; col < pixel_count; col++) {
   1005       uint8_t gray = pPalette[*src_scan];
   1006       src_scan++;
   1007       uint8_t back_alpha = *dest_alpha_scan;
   1008       if (back_alpha == 0) {
   1009         int src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col);
   1010         if (src_alpha) {
   1011           *dest_scan = gray;
   1012           *dest_alpha_scan = src_alpha;
   1013         }
   1014         dest_scan++;
   1015         dest_alpha_scan++;
   1016         continue;
   1017       }
   1018       uint8_t src_alpha = GetAlpha(*src_alpha_scan++, clip_scan, col);
   1019       if (src_alpha == 0) {
   1020         dest_scan++;
   1021         dest_alpha_scan++;
   1022         continue;
   1023       }
   1024       *dest_alpha_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1025       int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan);
   1026       dest_alpha_scan++;
   1027       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1028       dest_scan++;
   1029     }
   1030   } else {
   1031     if (blend_type) {
   1032       bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1033       for (int col = 0; col < pixel_count; col++) {
   1034         uint8_t gray = pPalette[*src_scan];
   1035         src_scan++;
   1036         if (!clip_scan || clip_scan[col] == 255) {
   1037           *dest_scan++ = gray;
   1038           *dest_alpha_scan++ = 255;
   1039           continue;
   1040         }
   1041         int src_alpha = clip_scan[col];
   1042         if (src_alpha == 0) {
   1043           dest_scan++;
   1044           dest_alpha_scan++;
   1045           continue;
   1046         }
   1047         int back_alpha = *dest_alpha_scan;
   1048         uint8_t dest_alpha =
   1049             back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1050         *dest_alpha_scan++ = dest_alpha;
   1051         int alpha_ratio = src_alpha * 255 / dest_alpha;
   1052         if (bNonseparableBlend)
   1053           gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
   1054         else
   1055           gray = Blend(blend_type, *dest_scan, gray);
   1056         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1057         dest_scan++;
   1058       }
   1059       return;
   1060     }
   1061     for (int col = 0; col < pixel_count; col++) {
   1062       uint8_t gray = pPalette[*src_scan];
   1063       src_scan++;
   1064       if (!clip_scan || clip_scan[col] == 255) {
   1065         *dest_scan++ = gray;
   1066         *dest_alpha_scan++ = 255;
   1067         continue;
   1068       }
   1069       int src_alpha = clip_scan[col];
   1070       if (src_alpha == 0) {
   1071         dest_scan++;
   1072         dest_alpha_scan++;
   1073         continue;
   1074       }
   1075       int back_alpha = *dest_alpha_scan;
   1076       uint8_t dest_alpha =
   1077           back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1078       *dest_alpha_scan++ = dest_alpha;
   1079       int alpha_ratio = src_alpha * 255 / dest_alpha;
   1080       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1081       dest_scan++;
   1082     }
   1083   }
   1084 }
   1085 
   1086 void CompositeRow_1bppPal2Gray(uint8_t* dest_scan,
   1087                                const uint8_t* src_scan,
   1088                                int src_left,
   1089                                const uint8_t* pPalette,
   1090                                int pixel_count,
   1091                                int blend_type,
   1092                                const uint8_t* clip_scan) {
   1093   int reset_gray = pPalette[0];
   1094   int set_gray = pPalette[1];
   1095   if (blend_type) {
   1096     bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1097     for (int col = 0; col < pixel_count; col++) {
   1098       uint8_t gray =
   1099           (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
   1100               ? set_gray
   1101               : reset_gray;
   1102       if (bNonseparableBlend)
   1103         gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
   1104       else
   1105         gray = Blend(blend_type, *dest_scan, gray);
   1106       if (clip_scan && clip_scan[col] < 255) {
   1107         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
   1108       } else {
   1109         *dest_scan = gray;
   1110       }
   1111       dest_scan++;
   1112     }
   1113     return;
   1114   }
   1115   for (int col = 0; col < pixel_count; col++) {
   1116     uint8_t gray =
   1117         (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
   1118             ? set_gray
   1119             : reset_gray;
   1120     if (clip_scan && clip_scan[col] < 255) {
   1121       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
   1122     } else {
   1123       *dest_scan = gray;
   1124     }
   1125     dest_scan++;
   1126   }
   1127 }
   1128 
   1129 void CompositeRow_1bppPal2Graya(uint8_t* dest_scan,
   1130                                 const uint8_t* src_scan,
   1131                                 int src_left,
   1132                                 const uint8_t* pPalette,
   1133                                 int pixel_count,
   1134                                 int blend_type,
   1135                                 const uint8_t* clip_scan,
   1136                                 uint8_t* dest_alpha_scan) {
   1137   int reset_gray = pPalette[0];
   1138   int set_gray = pPalette[1];
   1139   if (blend_type) {
   1140     bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   1141     for (int col = 0; col < pixel_count; col++) {
   1142       uint8_t gray =
   1143           (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
   1144               ? set_gray
   1145               : reset_gray;
   1146       if (!clip_scan || clip_scan[col] == 255) {
   1147         *dest_scan++ = gray;
   1148         *dest_alpha_scan++ = 255;
   1149         continue;
   1150       }
   1151       int src_alpha = clip_scan[col];
   1152       if (src_alpha == 0) {
   1153         dest_scan++;
   1154         dest_alpha_scan++;
   1155         continue;
   1156       }
   1157       int back_alpha = *dest_alpha_scan;
   1158       uint8_t dest_alpha =
   1159           back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1160       *dest_alpha_scan++ = dest_alpha;
   1161       int alpha_ratio = src_alpha * 255 / dest_alpha;
   1162       if (bNonseparableBlend)
   1163         gray = blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
   1164       else
   1165         gray = Blend(blend_type, *dest_scan, gray);
   1166       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1167       dest_scan++;
   1168     }
   1169     return;
   1170   }
   1171   for (int col = 0; col < pixel_count; col++) {
   1172     uint8_t gray =
   1173         (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
   1174             ? set_gray
   1175             : reset_gray;
   1176     if (!clip_scan || clip_scan[col] == 255) {
   1177       *dest_scan++ = gray;
   1178       *dest_alpha_scan++ = 255;
   1179       continue;
   1180     }
   1181     int src_alpha = clip_scan[col];
   1182     if (src_alpha == 0) {
   1183       dest_scan++;
   1184       dest_alpha_scan++;
   1185       continue;
   1186     }
   1187     int back_alpha = *dest_alpha_scan;
   1188     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1189     *dest_alpha_scan++ = dest_alpha;
   1190     int alpha_ratio = src_alpha * 255 / dest_alpha;
   1191     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
   1192     dest_scan++;
   1193   }
   1194 }
   1195 
   1196 void CompositeRow_8bppRgb2Rgb_NoBlend(uint8_t* dest_scan,
   1197                                       const uint8_t* src_scan,
   1198                                       uint32_t* pPalette,
   1199                                       int pixel_count,
   1200                                       int DestBpp,
   1201                                       const uint8_t* clip_scan,
   1202                                       const uint8_t* src_alpha_scan) {
   1203   if (src_alpha_scan) {
   1204     int dest_gap = DestBpp - 3;
   1205     FX_ARGB argb = 0;
   1206     for (int col = 0; col < pixel_count; col++) {
   1207       argb = pPalette[*src_scan];
   1208       int src_r = FXARGB_R(argb);
   1209       int src_g = FXARGB_G(argb);
   1210       int src_b = FXARGB_B(argb);
   1211       src_scan++;
   1212       uint8_t src_alpha = 0;
   1213       if (clip_scan) {
   1214         src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255;
   1215       } else {
   1216         src_alpha = *src_alpha_scan++;
   1217       }
   1218       if (src_alpha == 255) {
   1219         *dest_scan++ = src_b;
   1220         *dest_scan++ = src_g;
   1221         *dest_scan++ = src_r;
   1222         dest_scan += dest_gap;
   1223         continue;
   1224       }
   1225       if (src_alpha == 0) {
   1226         dest_scan += DestBpp;
   1227         continue;
   1228       }
   1229       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
   1230       dest_scan++;
   1231       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
   1232       dest_scan++;
   1233       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
   1234       dest_scan++;
   1235       dest_scan += dest_gap;
   1236     }
   1237   } else {
   1238     FX_ARGB argb = 0;
   1239     for (int col = 0; col < pixel_count; col++) {
   1240       argb = pPalette[*src_scan];
   1241       int src_r = FXARGB_R(argb);
   1242       int src_g = FXARGB_G(argb);
   1243       int src_b = FXARGB_B(argb);
   1244       if (clip_scan && clip_scan[col] < 255) {
   1245         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]);
   1246         dest_scan++;
   1247         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]);
   1248         dest_scan++;
   1249         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]);
   1250         dest_scan++;
   1251       } else {
   1252         *dest_scan++ = src_b;
   1253         *dest_scan++ = src_g;
   1254         *dest_scan++ = src_r;
   1255       }
   1256       if (DestBpp == 4) {
   1257         dest_scan++;
   1258       }
   1259       src_scan++;
   1260     }
   1261   }
   1262 }
   1263 
   1264 void CompositeRow_1bppRgb2Rgb_NoBlend(uint8_t* dest_scan,
   1265                                       const uint8_t* src_scan,
   1266                                       int src_left,
   1267                                       uint32_t* pPalette,
   1268                                       int pixel_count,
   1269                                       int DestBpp,
   1270                                       const uint8_t* clip_scan) {
   1271   int reset_r, reset_g, reset_b;
   1272   int set_r, set_g, set_b;
   1273   reset_r = FXARGB_R(pPalette[0]);
   1274   reset_g = FXARGB_G(pPalette[0]);
   1275   reset_b = FXARGB_B(pPalette[0]);
   1276   set_r = FXARGB_R(pPalette[1]);
   1277   set_g = FXARGB_G(pPalette[1]);
   1278   set_b = FXARGB_B(pPalette[1]);
   1279   for (int col = 0; col < pixel_count; col++) {
   1280     int src_r, src_g, src_b;
   1281     if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   1282       src_r = set_r;
   1283       src_g = set_g;
   1284       src_b = set_b;
   1285     } else {
   1286       src_r = reset_r;
   1287       src_g = reset_g;
   1288       src_b = reset_b;
   1289     }
   1290     if (clip_scan && clip_scan[col] < 255) {
   1291       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]);
   1292       dest_scan++;
   1293       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]);
   1294       dest_scan++;
   1295       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]);
   1296       dest_scan++;
   1297     } else {
   1298       *dest_scan++ = src_b;
   1299       *dest_scan++ = src_g;
   1300       *dest_scan++ = src_r;
   1301     }
   1302     if (DestBpp == 4) {
   1303       dest_scan++;
   1304     }
   1305   }
   1306 }
   1307 
   1308 void CompositeRow_8bppRgb2Argb_NoBlend(uint8_t* dest_scan,
   1309                                        const uint8_t* src_scan,
   1310                                        int width,
   1311                                        uint32_t* pPalette,
   1312                                        const uint8_t* clip_scan,
   1313                                        const uint8_t* src_alpha_scan) {
   1314   if (src_alpha_scan) {
   1315     for (int col = 0; col < width; col++) {
   1316       FX_ARGB argb = pPalette[*src_scan];
   1317       src_scan++;
   1318       int src_r = FXARGB_R(argb);
   1319       int src_g = FXARGB_G(argb);
   1320       int src_b = FXARGB_B(argb);
   1321       uint8_t back_alpha = dest_scan[3];
   1322       if (back_alpha == 0) {
   1323         if (clip_scan) {
   1324           int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255;
   1325           FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   1326         } else {
   1327           FXARGB_SETDIB(dest_scan,
   1328                         FXARGB_MAKE(*src_alpha_scan, src_r, src_g, src_b));
   1329         }
   1330         dest_scan += 4;
   1331         src_alpha_scan++;
   1332         continue;
   1333       }
   1334       uint8_t src_alpha;
   1335       if (clip_scan) {
   1336         src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255;
   1337       } else {
   1338         src_alpha = *src_alpha_scan++;
   1339       }
   1340       if (src_alpha == 0) {
   1341         dest_scan += 4;
   1342         continue;
   1343       }
   1344       uint8_t dest_alpha =
   1345           back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1346       dest_scan[3] = dest_alpha;
   1347       int alpha_ratio = src_alpha * 255 / dest_alpha;
   1348       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   1349       dest_scan++;
   1350       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   1351       dest_scan++;
   1352       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   1353       dest_scan++;
   1354       dest_scan++;
   1355     }
   1356   } else {
   1357     for (int col = 0; col < width; col++) {
   1358       FX_ARGB argb = pPalette[*src_scan];
   1359       int src_r = FXARGB_R(argb);
   1360       int src_g = FXARGB_G(argb);
   1361       int src_b = FXARGB_B(argb);
   1362       if (!clip_scan || clip_scan[col] == 255) {
   1363         *dest_scan++ = src_b;
   1364         *dest_scan++ = src_g;
   1365         *dest_scan++ = src_r;
   1366         *dest_scan++ = 255;
   1367         src_scan++;
   1368         continue;
   1369       }
   1370       int src_alpha = clip_scan[col];
   1371       if (src_alpha == 0) {
   1372         dest_scan += 4;
   1373         src_scan++;
   1374         continue;
   1375       }
   1376       int back_alpha = dest_scan[3];
   1377       uint8_t dest_alpha =
   1378           back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1379       dest_scan[3] = dest_alpha;
   1380       int alpha_ratio = src_alpha * 255 / dest_alpha;
   1381       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   1382       dest_scan++;
   1383       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   1384       dest_scan++;
   1385       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   1386       dest_scan++;
   1387       dest_scan++;
   1388       src_scan++;
   1389     }
   1390   }
   1391 }
   1392 
   1393 void CompositeRow_1bppRgb2Argb_NoBlend(uint8_t* dest_scan,
   1394                                        const uint8_t* src_scan,
   1395                                        int src_left,
   1396                                        int width,
   1397                                        uint32_t* pPalette,
   1398                                        const uint8_t* clip_scan) {
   1399   int reset_r, reset_g, reset_b;
   1400   int set_r, set_g, set_b;
   1401   reset_r = FXARGB_R(pPalette[0]);
   1402   reset_g = FXARGB_G(pPalette[0]);
   1403   reset_b = FXARGB_B(pPalette[0]);
   1404   set_r = FXARGB_R(pPalette[1]);
   1405   set_g = FXARGB_G(pPalette[1]);
   1406   set_b = FXARGB_B(pPalette[1]);
   1407   for (int col = 0; col < width; col++) {
   1408     int src_r, src_g, src_b;
   1409     if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   1410       src_r = set_r;
   1411       src_g = set_g;
   1412       src_b = set_b;
   1413     } else {
   1414       src_r = reset_r;
   1415       src_g = reset_g;
   1416       src_b = reset_b;
   1417     }
   1418     if (!clip_scan || clip_scan[col] == 255) {
   1419       *dest_scan++ = src_b;
   1420       *dest_scan++ = src_g;
   1421       *dest_scan++ = src_r;
   1422       *dest_scan++ = 255;
   1423       continue;
   1424     }
   1425     int src_alpha = clip_scan[col];
   1426     if (src_alpha == 0) {
   1427       dest_scan += 4;
   1428       continue;
   1429     }
   1430     int back_alpha = dest_scan[3];
   1431     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1432     dest_scan[3] = dest_alpha;
   1433     int alpha_ratio = src_alpha * 255 / dest_alpha;
   1434     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   1435     dest_scan++;
   1436     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   1437     dest_scan++;
   1438     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   1439     dest_scan++;
   1440     dest_scan++;
   1441   }
   1442 }
   1443 
   1444 void CompositeRow_1bppRgb2Rgba_NoBlend(uint8_t* dest_scan,
   1445                                        const uint8_t* src_scan,
   1446                                        int src_left,
   1447                                        int width,
   1448                                        uint32_t* pPalette,
   1449                                        const uint8_t* clip_scan,
   1450                                        uint8_t* dest_alpha_scan) {
   1451   int reset_r, reset_g, reset_b;
   1452   int set_r, set_g, set_b;
   1453   reset_r = FXARGB_R(pPalette[0]);
   1454   reset_g = FXARGB_G(pPalette[0]);
   1455   reset_b = FXARGB_B(pPalette[0]);
   1456   set_r = FXARGB_R(pPalette[1]);
   1457   set_g = FXARGB_G(pPalette[1]);
   1458   set_b = FXARGB_B(pPalette[1]);
   1459   for (int col = 0; col < width; col++) {
   1460     int src_r, src_g, src_b;
   1461     if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   1462       src_r = set_r;
   1463       src_g = set_g;
   1464       src_b = set_b;
   1465     } else {
   1466       src_r = reset_r;
   1467       src_g = reset_g;
   1468       src_b = reset_b;
   1469     }
   1470     if (!clip_scan || clip_scan[col] == 255) {
   1471       *dest_scan++ = src_b;
   1472       *dest_scan++ = src_g;
   1473       *dest_scan++ = src_r;
   1474       *dest_alpha_scan++ = 255;
   1475       continue;
   1476     }
   1477     int src_alpha = clip_scan[col];
   1478     if (src_alpha == 0) {
   1479       dest_scan += 3;
   1480       dest_alpha_scan++;
   1481       continue;
   1482     }
   1483     int back_alpha = *dest_alpha_scan;
   1484     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1485     *dest_alpha_scan++ = dest_alpha;
   1486     int alpha_ratio = src_alpha * 255 / dest_alpha;
   1487     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   1488     dest_scan++;
   1489     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   1490     dest_scan++;
   1491     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   1492     dest_scan++;
   1493   }
   1494 }
   1495 
   1496 void CompositeRow_ByteMask2Argb(uint8_t* dest_scan,
   1497                                 const uint8_t* src_scan,
   1498                                 int mask_alpha,
   1499                                 int src_r,
   1500                                 int src_g,
   1501                                 int src_b,
   1502                                 int pixel_count,
   1503                                 int blend_type,
   1504                                 const uint8_t* clip_scan) {
   1505   for (int col = 0; col < pixel_count; col++) {
   1506     int src_alpha;
   1507     if (clip_scan) {
   1508       src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   1509     } else {
   1510       src_alpha = mask_alpha * src_scan[col] / 255;
   1511     }
   1512     uint8_t back_alpha = dest_scan[3];
   1513     if (back_alpha == 0) {
   1514       FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   1515       dest_scan += 4;
   1516       continue;
   1517     }
   1518     if (src_alpha == 0) {
   1519       dest_scan += 4;
   1520       continue;
   1521     }
   1522     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1523     dest_scan[3] = dest_alpha;
   1524     int alpha_ratio = src_alpha * 255 / dest_alpha;
   1525     if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   1526       int blended_colors[3];
   1527       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
   1528                          static_cast<uint8_t>(src_g),
   1529                          static_cast<uint8_t>(src_r)};
   1530       RGB_Blend(blend_type, scan, dest_scan, blended_colors);
   1531       *dest_scan =
   1532           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
   1533       dest_scan++;
   1534       *dest_scan =
   1535           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
   1536       dest_scan++;
   1537       *dest_scan =
   1538           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
   1539     } else if (blend_type) {
   1540       int blended = Blend(blend_type, *dest_scan, src_b);
   1541       blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   1542       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1543       dest_scan++;
   1544       blended = Blend(blend_type, *dest_scan, src_g);
   1545       blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   1546       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1547       dest_scan++;
   1548       blended = Blend(blend_type, *dest_scan, src_r);
   1549       blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   1550       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1551     } else {
   1552       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   1553       dest_scan++;
   1554       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   1555       dest_scan++;
   1556       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   1557     }
   1558     dest_scan += 2;
   1559   }
   1560 }
   1561 
   1562 void CompositeRow_ByteMask2Rgba(uint8_t* dest_scan,
   1563                                 const uint8_t* src_scan,
   1564                                 int mask_alpha,
   1565                                 int src_r,
   1566                                 int src_g,
   1567                                 int src_b,
   1568                                 int pixel_count,
   1569                                 int blend_type,
   1570                                 const uint8_t* clip_scan,
   1571                                 uint8_t* dest_alpha_scan) {
   1572   for (int col = 0; col < pixel_count; col++) {
   1573     int src_alpha;
   1574     if (clip_scan) {
   1575       src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   1576     } else {
   1577       src_alpha = mask_alpha * src_scan[col] / 255;
   1578     }
   1579     uint8_t back_alpha = *dest_alpha_scan;
   1580     if (back_alpha == 0) {
   1581       *dest_scan++ = src_b;
   1582       *dest_scan++ = src_g;
   1583       *dest_scan++ = src_r;
   1584       *dest_alpha_scan++ = src_alpha;
   1585       continue;
   1586     }
   1587     if (src_alpha == 0) {
   1588       dest_scan += 3;
   1589       dest_alpha_scan++;
   1590       continue;
   1591     }
   1592     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1593     *dest_alpha_scan++ = dest_alpha;
   1594     int alpha_ratio = src_alpha * 255 / dest_alpha;
   1595     if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   1596       int blended_colors[3];
   1597       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
   1598                          static_cast<uint8_t>(src_g),
   1599                          static_cast<uint8_t>(src_r)};
   1600       RGB_Blend(blend_type, scan, dest_scan, blended_colors);
   1601       *dest_scan =
   1602           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
   1603       dest_scan++;
   1604       *dest_scan =
   1605           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
   1606       dest_scan++;
   1607       *dest_scan =
   1608           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
   1609       dest_scan++;
   1610     } else if (blend_type) {
   1611       int blended = Blend(blend_type, *dest_scan, src_b);
   1612       blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   1613       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1614       dest_scan++;
   1615       blended = Blend(blend_type, *dest_scan, src_g);
   1616       blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   1617       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1618       dest_scan++;
   1619       blended = Blend(blend_type, *dest_scan, src_r);
   1620       blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   1621       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1622       dest_scan++;
   1623     } else {
   1624       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   1625       dest_scan++;
   1626       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   1627       dest_scan++;
   1628       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   1629       dest_scan++;
   1630     }
   1631   }
   1632 }
   1633 
   1634 void CompositeRow_ByteMask2Rgb(uint8_t* dest_scan,
   1635                                const uint8_t* src_scan,
   1636                                int mask_alpha,
   1637                                int src_r,
   1638                                int src_g,
   1639                                int src_b,
   1640                                int pixel_count,
   1641                                int blend_type,
   1642                                int Bpp,
   1643                                const uint8_t* clip_scan) {
   1644   for (int col = 0; col < pixel_count; col++) {
   1645     int src_alpha;
   1646     if (clip_scan) {
   1647       src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   1648     } else {
   1649       src_alpha = mask_alpha * src_scan[col] / 255;
   1650     }
   1651     if (src_alpha == 0) {
   1652       dest_scan += Bpp;
   1653       continue;
   1654     }
   1655     if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   1656       int blended_colors[3];
   1657       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
   1658                          static_cast<uint8_t>(src_g),
   1659                          static_cast<uint8_t>(src_r)};
   1660       RGB_Blend(blend_type, scan, dest_scan, blended_colors);
   1661       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha);
   1662       dest_scan++;
   1663       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha);
   1664       dest_scan++;
   1665       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha);
   1666     } else if (blend_type) {
   1667       int blended = Blend(blend_type, *dest_scan, src_b);
   1668       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   1669       dest_scan++;
   1670       blended = Blend(blend_type, *dest_scan, src_g);
   1671       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   1672       dest_scan++;
   1673       blended = Blend(blend_type, *dest_scan, src_r);
   1674       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   1675     } else {
   1676       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
   1677       dest_scan++;
   1678       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
   1679       dest_scan++;
   1680       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
   1681     }
   1682     dest_scan += Bpp - 2;
   1683   }
   1684 }
   1685 
   1686 void CompositeRow_ByteMask2Mask(uint8_t* dest_scan,
   1687                                 const uint8_t* src_scan,
   1688                                 int mask_alpha,
   1689                                 int pixel_count,
   1690                                 const uint8_t* clip_scan) {
   1691   for (int col = 0; col < pixel_count; col++) {
   1692     int src_alpha;
   1693     if (clip_scan) {
   1694       src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   1695     } else {
   1696       src_alpha = mask_alpha * src_scan[col] / 255;
   1697     }
   1698     uint8_t back_alpha = *dest_scan;
   1699     if (!back_alpha) {
   1700       *dest_scan = src_alpha;
   1701     } else if (src_alpha) {
   1702       *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1703     }
   1704     dest_scan++;
   1705   }
   1706 }
   1707 
   1708 void CompositeRow_ByteMask2Gray(uint8_t* dest_scan,
   1709                                 const uint8_t* src_scan,
   1710                                 int mask_alpha,
   1711                                 int src_gray,
   1712                                 int pixel_count,
   1713                                 const uint8_t* clip_scan) {
   1714   for (int col = 0; col < pixel_count; col++) {
   1715     int src_alpha;
   1716     if (clip_scan) {
   1717       src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   1718     } else {
   1719       src_alpha = mask_alpha * src_scan[col] / 255;
   1720     }
   1721     if (src_alpha) {
   1722       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha);
   1723     }
   1724     dest_scan++;
   1725   }
   1726 }
   1727 
   1728 void CompositeRow_ByteMask2Graya(uint8_t* dest_scan,
   1729                                  const uint8_t* src_scan,
   1730                                  int mask_alpha,
   1731                                  int src_gray,
   1732                                  int pixel_count,
   1733                                  const uint8_t* clip_scan,
   1734                                  uint8_t* dest_alpha_scan) {
   1735   for (int col = 0; col < pixel_count; col++) {
   1736     int src_alpha;
   1737     if (clip_scan) {
   1738       src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   1739     } else {
   1740       src_alpha = mask_alpha * src_scan[col] / 255;
   1741     }
   1742     uint8_t back_alpha = *dest_alpha_scan;
   1743     if (back_alpha == 0) {
   1744       *dest_scan++ = src_gray;
   1745       *dest_alpha_scan++ = src_alpha;
   1746       continue;
   1747     }
   1748     if (src_alpha == 0) {
   1749       dest_scan++;
   1750       dest_alpha_scan++;
   1751       continue;
   1752     }
   1753     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1754     *dest_alpha_scan++ = dest_alpha;
   1755     int alpha_ratio = src_alpha * 255 / dest_alpha;
   1756     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio);
   1757     dest_scan++;
   1758   }
   1759 }
   1760 
   1761 void CompositeRow_BitMask2Argb(uint8_t* dest_scan,
   1762                                const uint8_t* src_scan,
   1763                                int mask_alpha,
   1764                                int src_r,
   1765                                int src_g,
   1766                                int src_b,
   1767                                int src_left,
   1768                                int pixel_count,
   1769                                int blend_type,
   1770                                const uint8_t* clip_scan) {
   1771   if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) {
   1772     FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b);
   1773     for (int col = 0; col < pixel_count; col++) {
   1774       if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   1775         FXARGB_SETDIB(dest_scan, argb);
   1776       }
   1777       dest_scan += 4;
   1778     }
   1779     return;
   1780   }
   1781   for (int col = 0; col < pixel_count; col++) {
   1782     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   1783       dest_scan += 4;
   1784       continue;
   1785     }
   1786     int src_alpha;
   1787     if (clip_scan) {
   1788       src_alpha = mask_alpha * clip_scan[col] / 255;
   1789     } else {
   1790       src_alpha = mask_alpha;
   1791     }
   1792     uint8_t back_alpha = dest_scan[3];
   1793     if (back_alpha == 0) {
   1794       FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   1795       dest_scan += 4;
   1796       continue;
   1797     }
   1798     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1799     dest_scan[3] = dest_alpha;
   1800     int alpha_ratio = src_alpha * 255 / dest_alpha;
   1801     if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   1802       int blended_colors[3];
   1803       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
   1804                          static_cast<uint8_t>(src_g),
   1805                          static_cast<uint8_t>(src_r)};
   1806       RGB_Blend(blend_type, scan, dest_scan, blended_colors);
   1807       *dest_scan =
   1808           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
   1809       dest_scan++;
   1810       *dest_scan =
   1811           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
   1812       dest_scan++;
   1813       *dest_scan =
   1814           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
   1815     } else if (blend_type) {
   1816       int blended = Blend(blend_type, *dest_scan, src_b);
   1817       blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   1818       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1819       dest_scan++;
   1820       blended = Blend(blend_type, *dest_scan, src_g);
   1821       blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   1822       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1823       dest_scan++;
   1824       blended = Blend(blend_type, *dest_scan, src_r);
   1825       blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   1826       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
   1827     } else {
   1828       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
   1829       dest_scan++;
   1830       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
   1831       dest_scan++;
   1832       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
   1833     }
   1834     dest_scan += 2;
   1835   }
   1836 }
   1837 
   1838 void CompositeRow_BitMask2Rgb(uint8_t* dest_scan,
   1839                               const uint8_t* src_scan,
   1840                               int mask_alpha,
   1841                               int src_r,
   1842                               int src_g,
   1843                               int src_b,
   1844                               int src_left,
   1845                               int pixel_count,
   1846                               int blend_type,
   1847                               int Bpp,
   1848                               const uint8_t* clip_scan) {
   1849   if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) {
   1850     for (int col = 0; col < pixel_count; col++) {
   1851       if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   1852         dest_scan[2] = src_r;
   1853         dest_scan[1] = src_g;
   1854         dest_scan[0] = src_b;
   1855       }
   1856       dest_scan += Bpp;
   1857     }
   1858     return;
   1859   }
   1860   for (int col = 0; col < pixel_count; col++) {
   1861     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   1862       dest_scan += Bpp;
   1863       continue;
   1864     }
   1865     int src_alpha;
   1866     if (clip_scan) {
   1867       src_alpha = mask_alpha * clip_scan[col] / 255;
   1868     } else {
   1869       src_alpha = mask_alpha;
   1870     }
   1871     if (src_alpha == 0) {
   1872       dest_scan += Bpp;
   1873       continue;
   1874     }
   1875     if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   1876       int blended_colors[3];
   1877       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
   1878                          static_cast<uint8_t>(src_g),
   1879                          static_cast<uint8_t>(src_r)};
   1880       RGB_Blend(blend_type, scan, dest_scan, blended_colors);
   1881       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha);
   1882       dest_scan++;
   1883       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha);
   1884       dest_scan++;
   1885       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha);
   1886     } else if (blend_type) {
   1887       int blended = Blend(blend_type, *dest_scan, src_b);
   1888       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   1889       dest_scan++;
   1890       blended = Blend(blend_type, *dest_scan, src_g);
   1891       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   1892       dest_scan++;
   1893       blended = Blend(blend_type, *dest_scan, src_r);
   1894       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
   1895     } else {
   1896       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
   1897       dest_scan++;
   1898       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
   1899       dest_scan++;
   1900       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
   1901     }
   1902     dest_scan += Bpp - 2;
   1903   }
   1904 }
   1905 
   1906 void CompositeRow_BitMask2Mask(uint8_t* dest_scan,
   1907                                const uint8_t* src_scan,
   1908                                int mask_alpha,
   1909                                int src_left,
   1910                                int pixel_count,
   1911                                const uint8_t* clip_scan) {
   1912   for (int col = 0; col < pixel_count; col++) {
   1913     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   1914       dest_scan++;
   1915       continue;
   1916     }
   1917     int src_alpha;
   1918     if (clip_scan) {
   1919       src_alpha = mask_alpha * clip_scan[col] / 255;
   1920     } else {
   1921       src_alpha = mask_alpha;
   1922     }
   1923     uint8_t back_alpha = *dest_scan;
   1924     if (!back_alpha) {
   1925       *dest_scan = src_alpha;
   1926     } else if (src_alpha) {
   1927       *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1928     }
   1929     dest_scan++;
   1930   }
   1931 }
   1932 
   1933 void CompositeRow_BitMask2Gray(uint8_t* dest_scan,
   1934                                const uint8_t* src_scan,
   1935                                int mask_alpha,
   1936                                int src_gray,
   1937                                int src_left,
   1938                                int pixel_count,
   1939                                const uint8_t* clip_scan) {
   1940   for (int col = 0; col < pixel_count; col++) {
   1941     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   1942       dest_scan++;
   1943       continue;
   1944     }
   1945     int src_alpha;
   1946     if (clip_scan) {
   1947       src_alpha = mask_alpha * clip_scan[col] / 255;
   1948     } else {
   1949       src_alpha = mask_alpha;
   1950     }
   1951     if (src_alpha) {
   1952       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha);
   1953     }
   1954     dest_scan++;
   1955   }
   1956 }
   1957 
   1958 void CompositeRow_BitMask2Graya(uint8_t* dest_scan,
   1959                                 const uint8_t* src_scan,
   1960                                 int mask_alpha,
   1961                                 int src_gray,
   1962                                 int src_left,
   1963                                 int pixel_count,
   1964                                 const uint8_t* clip_scan,
   1965                                 uint8_t* dest_alpha_scan) {
   1966   for (int col = 0; col < pixel_count; col++) {
   1967     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   1968       dest_scan++;
   1969       dest_alpha_scan++;
   1970       continue;
   1971     }
   1972     int src_alpha;
   1973     if (clip_scan) {
   1974       src_alpha = mask_alpha * clip_scan[col] / 255;
   1975     } else {
   1976       src_alpha = mask_alpha;
   1977     }
   1978     uint8_t back_alpha = *dest_alpha_scan;
   1979     if (back_alpha == 0) {
   1980       *dest_scan++ = src_gray;
   1981       *dest_alpha_scan++ = src_alpha;
   1982       continue;
   1983     }
   1984     if (src_alpha == 0) {
   1985       dest_scan++;
   1986       dest_alpha_scan++;
   1987       continue;
   1988     }
   1989     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   1990     *dest_alpha_scan++ = dest_alpha;
   1991     int alpha_ratio = src_alpha * 255 / dest_alpha;
   1992     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio);
   1993     dest_scan++;
   1994   }
   1995 }
   1996 
   1997 void CompositeRow_Argb2Argb_RgbByteOrder(uint8_t* dest_scan,
   1998                                          const uint8_t* src_scan,
   1999                                          int pixel_count,
   2000                                          int blend_type,
   2001                                          const uint8_t* clip_scan) {
   2002   int blended_colors[3];
   2003   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2004   for (int col = 0; col < pixel_count; col++) {
   2005     uint8_t back_alpha = dest_scan[3];
   2006     if (back_alpha == 0) {
   2007       if (clip_scan) {
   2008         int src_alpha = clip_scan[col] * src_scan[3] / 255;
   2009         dest_scan[3] = src_alpha;
   2010         dest_scan[0] = src_scan[2];
   2011         dest_scan[1] = src_scan[1];
   2012         dest_scan[2] = src_scan[0];
   2013       } else {
   2014         FXARGB_RGBORDERCOPY(dest_scan, src_scan);
   2015       }
   2016       dest_scan += 4;
   2017       src_scan += 4;
   2018       continue;
   2019     }
   2020     uint8_t src_alpha;
   2021     if (clip_scan) {
   2022       src_alpha = clip_scan[col] * src_scan[3] / 255;
   2023     } else {
   2024       src_alpha = src_scan[3];
   2025     }
   2026     if (src_alpha == 0) {
   2027       dest_scan += 4;
   2028       src_scan += 4;
   2029       continue;
   2030     }
   2031     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2032     dest_scan[3] = dest_alpha;
   2033     int alpha_ratio = src_alpha * 255 / dest_alpha;
   2034     if (bNonseparableBlend) {
   2035       uint8_t dest_scan_o[3];
   2036       dest_scan_o[0] = dest_scan[2];
   2037       dest_scan_o[1] = dest_scan[1];
   2038       dest_scan_o[2] = dest_scan[0];
   2039       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2040     }
   2041     for (int color = 0; color < 3; color++) {
   2042       int index = 2 - color;
   2043       if (blend_type) {
   2044         int blended = bNonseparableBlend
   2045                           ? blended_colors[color]
   2046                           : Blend(blend_type, dest_scan[index], *src_scan);
   2047         blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
   2048         dest_scan[index] =
   2049             FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
   2050       } else {
   2051         dest_scan[index] =
   2052             FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio);
   2053       }
   2054       src_scan++;
   2055     }
   2056     dest_scan += 4;
   2057     src_scan++;
   2058   }
   2059 }
   2060 
   2061 void CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan,
   2062                                                      const uint8_t* src_scan,
   2063                                                      int width,
   2064                                                      int blend_type,
   2065                                                      int src_Bpp) {
   2066   int blended_colors[3];
   2067   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2068   int src_gap = src_Bpp - 3;
   2069   for (int col = 0; col < width; col++) {
   2070     uint8_t back_alpha = dest_scan[3];
   2071     if (back_alpha == 0) {
   2072       if (src_Bpp == 4) {
   2073         FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
   2074       } else {
   2075         FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2],
   2076                                                      src_scan[1], src_scan[0]));
   2077       }
   2078       dest_scan += 4;
   2079       src_scan += src_Bpp;
   2080       continue;
   2081     }
   2082     dest_scan[3] = 0xff;
   2083     if (bNonseparableBlend) {
   2084       uint8_t dest_scan_o[3];
   2085       dest_scan_o[0] = dest_scan[2];
   2086       dest_scan_o[1] = dest_scan[1];
   2087       dest_scan_o[2] = dest_scan[0];
   2088       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2089     }
   2090     for (int color = 0; color < 3; color++) {
   2091       int index = 2 - color;
   2092       int src_color = *src_scan;
   2093       int blended = bNonseparableBlend
   2094                         ? blended_colors[color]
   2095                         : Blend(blend_type, dest_scan[index], src_color);
   2096       dest_scan[index] = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
   2097       src_scan++;
   2098     }
   2099     dest_scan += 4;
   2100     src_scan += src_gap;
   2101   }
   2102 }
   2103 
   2104 void CompositeRow_Argb2Rgb_Blend_RgbByteOrder(uint8_t* dest_scan,
   2105                                               const uint8_t* src_scan,
   2106                                               int width,
   2107                                               int blend_type,
   2108                                               int dest_Bpp,
   2109                                               const uint8_t* clip_scan) {
   2110   int blended_colors[3];
   2111   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2112   for (int col = 0; col < width; col++) {
   2113     uint8_t src_alpha;
   2114     if (clip_scan) {
   2115       src_alpha = src_scan[3] * (*clip_scan++) / 255;
   2116     } else {
   2117       src_alpha = src_scan[3];
   2118     }
   2119     if (src_alpha == 0) {
   2120       dest_scan += dest_Bpp;
   2121       src_scan += 4;
   2122       continue;
   2123     }
   2124     if (bNonseparableBlend) {
   2125       uint8_t dest_scan_o[3];
   2126       dest_scan_o[0] = dest_scan[2];
   2127       dest_scan_o[1] = dest_scan[1];
   2128       dest_scan_o[2] = dest_scan[0];
   2129       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2130     }
   2131     for (int color = 0; color < 3; color++) {
   2132       int index = 2 - color;
   2133       int back_color = dest_scan[index];
   2134       int blended = bNonseparableBlend
   2135                         ? blended_colors[color]
   2136                         : Blend(blend_type, back_color, *src_scan);
   2137       dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
   2138       src_scan++;
   2139     }
   2140     dest_scan += dest_Bpp;
   2141     src_scan++;
   2142   }
   2143 }
   2144 
   2145 void CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan,
   2146                                                        const uint8_t* src_scan,
   2147                                                        int width,
   2148                                                        int src_Bpp) {
   2149   for (int col = 0; col < width; col++) {
   2150     if (src_Bpp == 4) {
   2151       FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
   2152     } else {
   2153       FXARGB_SETRGBORDERDIB(
   2154           dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
   2155     }
   2156     dest_scan += 4;
   2157     src_scan += src_Bpp;
   2158   }
   2159 }
   2160 
   2161 void CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan,
   2162                                                     const uint8_t* src_scan,
   2163                                                     int width,
   2164                                                     int blend_type,
   2165                                                     int dest_Bpp,
   2166                                                     int src_Bpp) {
   2167   int blended_colors[3];
   2168   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2169   int src_gap = src_Bpp - 3;
   2170   for (int col = 0; col < width; col++) {
   2171     if (bNonseparableBlend) {
   2172       uint8_t dest_scan_o[3];
   2173       dest_scan_o[0] = dest_scan[2];
   2174       dest_scan_o[1] = dest_scan[1];
   2175       dest_scan_o[2] = dest_scan[0];
   2176       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2177     }
   2178     for (int color = 0; color < 3; color++) {
   2179       int index = 2 - color;
   2180       int back_color = dest_scan[index];
   2181       int src_color = *src_scan;
   2182       int blended = bNonseparableBlend
   2183                         ? blended_colors[color]
   2184                         : Blend(blend_type, back_color, src_color);
   2185       dest_scan[index] = blended;
   2186       src_scan++;
   2187     }
   2188     dest_scan += dest_Bpp;
   2189     src_scan += src_gap;
   2190   }
   2191 }
   2192 
   2193 void CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan,
   2194                                                 const uint8_t* src_scan,
   2195                                                 int width,
   2196                                                 int dest_Bpp,
   2197                                                 const uint8_t* clip_scan) {
   2198   for (int col = 0; col < width; col++) {
   2199     uint8_t src_alpha;
   2200     if (clip_scan) {
   2201       src_alpha = src_scan[3] * (*clip_scan++) / 255;
   2202     } else {
   2203       src_alpha = src_scan[3];
   2204     }
   2205     if (src_alpha == 255) {
   2206       dest_scan[2] = *src_scan++;
   2207       dest_scan[1] = *src_scan++;
   2208       dest_scan[0] = *src_scan++;
   2209       dest_scan += dest_Bpp;
   2210       src_scan++;
   2211       continue;
   2212     }
   2213     if (src_alpha == 0) {
   2214       dest_scan += dest_Bpp;
   2215       src_scan += 4;
   2216       continue;
   2217     }
   2218     for (int color = 0; color < 3; color++) {
   2219       int index = 2 - color;
   2220       dest_scan[index] =
   2221           FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, src_alpha);
   2222       src_scan++;
   2223     }
   2224     dest_scan += dest_Bpp;
   2225     src_scan++;
   2226   }
   2227 }
   2228 
   2229 void CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(uint8_t* dest_scan,
   2230                                                       const uint8_t* src_scan,
   2231                                                       int width,
   2232                                                       int dest_Bpp,
   2233                                                       int src_Bpp) {
   2234   for (int col = 0; col < width; col++) {
   2235     dest_scan[2] = src_scan[0];
   2236     dest_scan[1] = src_scan[1];
   2237     dest_scan[0] = src_scan[2];
   2238     dest_scan += dest_Bpp;
   2239     src_scan += src_Bpp;
   2240   }
   2241 }
   2242 
   2243 void CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan,
   2244                                                    const uint8_t* src_scan,
   2245                                                    int width,
   2246                                                    int blend_type,
   2247                                                    int src_Bpp,
   2248                                                    const uint8_t* clip_scan) {
   2249   int blended_colors[3];
   2250   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2251   int src_gap = src_Bpp - 3;
   2252   for (int col = 0; col < width; col++) {
   2253     int src_alpha = *clip_scan++;
   2254     uint8_t back_alpha = dest_scan[3];
   2255     if (back_alpha == 0) {
   2256       dest_scan[2] = *src_scan++;
   2257       dest_scan[1] = *src_scan++;
   2258       dest_scan[0] = *src_scan++;
   2259       src_scan += src_gap;
   2260       dest_scan += 4;
   2261       continue;
   2262     }
   2263     if (src_alpha == 0) {
   2264       dest_scan += 4;
   2265       src_scan += src_Bpp;
   2266       continue;
   2267     }
   2268     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2269     dest_scan[3] = dest_alpha;
   2270     int alpha_ratio = src_alpha * 255 / dest_alpha;
   2271     if (bNonseparableBlend) {
   2272       uint8_t dest_scan_o[3];
   2273       dest_scan_o[0] = dest_scan[2];
   2274       dest_scan_o[1] = dest_scan[1];
   2275       dest_scan_o[2] = dest_scan[0];
   2276       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2277     }
   2278     for (int color = 0; color < 3; color++) {
   2279       int index = 2 - color;
   2280       int src_color = *src_scan;
   2281       int blended = bNonseparableBlend
   2282                         ? blended_colors[color]
   2283                         : Blend(blend_type, dest_scan[index], src_color);
   2284       blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
   2285       dest_scan[index] =
   2286           FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
   2287       src_scan++;
   2288     }
   2289     dest_scan += 4;
   2290     src_scan += src_gap;
   2291   }
   2292 }
   2293 
   2294 void CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(uint8_t* dest_scan,
   2295                                                   const uint8_t* src_scan,
   2296                                                   int width,
   2297                                                   int blend_type,
   2298                                                   int dest_Bpp,
   2299                                                   int src_Bpp,
   2300                                                   const uint8_t* clip_scan) {
   2301   int blended_colors[3];
   2302   bool bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
   2303   int src_gap = src_Bpp - 3;
   2304   for (int col = 0; col < width; col++) {
   2305     uint8_t src_alpha = *clip_scan++;
   2306     if (src_alpha == 0) {
   2307       dest_scan += dest_Bpp;
   2308       src_scan += src_Bpp;
   2309       continue;
   2310     }
   2311     if (bNonseparableBlend) {
   2312       uint8_t dest_scan_o[3];
   2313       dest_scan_o[0] = dest_scan[2];
   2314       dest_scan_o[1] = dest_scan[1];
   2315       dest_scan_o[2] = dest_scan[0];
   2316       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
   2317     }
   2318     for (int color = 0; color < 3; color++) {
   2319       int index = 2 - color;
   2320       int src_color = *src_scan;
   2321       int back_color = dest_scan[index];
   2322       int blended = bNonseparableBlend
   2323                         ? blended_colors[color]
   2324                         : Blend(blend_type, back_color, src_color);
   2325       dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
   2326       src_scan++;
   2327     }
   2328     dest_scan += dest_Bpp;
   2329     src_scan += src_gap;
   2330   }
   2331 }
   2332 
   2333 void CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan,
   2334                                                      const uint8_t* src_scan,
   2335                                                      int width,
   2336                                                      int src_Bpp,
   2337                                                      const uint8_t* clip_scan) {
   2338   int src_gap = src_Bpp - 3;
   2339   for (int col = 0; col < width; col++) {
   2340     int src_alpha = clip_scan[col];
   2341     if (src_alpha == 255) {
   2342       dest_scan[2] = *src_scan++;
   2343       dest_scan[1] = *src_scan++;
   2344       dest_scan[0] = *src_scan++;
   2345       dest_scan[3] = 255;
   2346       dest_scan += 4;
   2347       src_scan += src_gap;
   2348       continue;
   2349     }
   2350     if (src_alpha == 0) {
   2351       dest_scan += 4;
   2352       src_scan += src_Bpp;
   2353       continue;
   2354     }
   2355     int back_alpha = dest_scan[3];
   2356     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2357     dest_scan[3] = dest_alpha;
   2358     int alpha_ratio = src_alpha * 255 / dest_alpha;
   2359     for (int color = 0; color < 3; color++) {
   2360       int index = 2 - color;
   2361       dest_scan[index] =
   2362           FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio);
   2363       src_scan++;
   2364     }
   2365     dest_scan += 4;
   2366     src_scan += src_gap;
   2367   }
   2368 }
   2369 
   2370 void CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(uint8_t* dest_scan,
   2371                                                     const uint8_t* src_scan,
   2372                                                     int width,
   2373                                                     int dest_Bpp,
   2374                                                     int src_Bpp,
   2375                                                     const uint8_t* clip_scan) {
   2376   for (int col = 0; col < width; col++) {
   2377     int src_alpha = clip_scan[col];
   2378     if (src_alpha == 255) {
   2379       dest_scan[2] = src_scan[0];
   2380       dest_scan[1] = src_scan[1];
   2381       dest_scan[0] = src_scan[2];
   2382     } else if (src_alpha) {
   2383       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], *src_scan, src_alpha);
   2384       src_scan++;
   2385       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], *src_scan, src_alpha);
   2386       src_scan++;
   2387       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], *src_scan, src_alpha);
   2388       dest_scan += dest_Bpp;
   2389       src_scan += src_Bpp - 2;
   2390       continue;
   2391     }
   2392     dest_scan += dest_Bpp;
   2393     src_scan += src_Bpp;
   2394   }
   2395 }
   2396 
   2397 void CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan,
   2398                                                    const uint8_t* src_scan,
   2399                                                    FX_ARGB* pPalette,
   2400                                                    int pixel_count,
   2401                                                    int DestBpp,
   2402                                                    const uint8_t* clip_scan) {
   2403   for (int col = 0; col < pixel_count; col++) {
   2404     FX_ARGB argb = pPalette ? pPalette[*src_scan] : (*src_scan) * 0x010101;
   2405     int src_r = FXARGB_R(argb);
   2406     int src_g = FXARGB_G(argb);
   2407     int src_b = FXARGB_B(argb);
   2408     if (clip_scan && clip_scan[col] < 255) {
   2409       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
   2410       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
   2411       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
   2412     } else {
   2413       dest_scan[2] = src_b;
   2414       dest_scan[1] = src_g;
   2415       dest_scan[0] = src_r;
   2416     }
   2417     dest_scan += DestBpp;
   2418     src_scan++;
   2419   }
   2420 }
   2421 
   2422 void CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(uint8_t* dest_scan,
   2423                                                    const uint8_t* src_scan,
   2424                                                    int src_left,
   2425                                                    FX_ARGB* pPalette,
   2426                                                    int pixel_count,
   2427                                                    int DestBpp,
   2428                                                    const uint8_t* clip_scan) {
   2429   int reset_r, reset_g, reset_b;
   2430   int set_r, set_g, set_b;
   2431   if (pPalette) {
   2432     reset_r = FXARGB_R(pPalette[0]);
   2433     reset_g = FXARGB_G(pPalette[0]);
   2434     reset_b = FXARGB_B(pPalette[0]);
   2435     set_r = FXARGB_R(pPalette[1]);
   2436     set_g = FXARGB_G(pPalette[1]);
   2437     set_b = FXARGB_B(pPalette[1]);
   2438   } else {
   2439     reset_r = reset_g = reset_b = 0;
   2440     set_r = set_g = set_b = 255;
   2441   }
   2442   for (int col = 0; col < pixel_count; col++) {
   2443     int src_r, src_g, src_b;
   2444     if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   2445       src_r = set_r;
   2446       src_g = set_g;
   2447       src_b = set_b;
   2448     } else {
   2449       src_r = reset_r;
   2450       src_g = reset_g;
   2451       src_b = reset_b;
   2452     }
   2453     if (clip_scan && clip_scan[col] < 255) {
   2454       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
   2455       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
   2456       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
   2457     } else {
   2458       dest_scan[2] = src_b;
   2459       dest_scan[1] = src_g;
   2460       dest_scan[0] = src_r;
   2461     }
   2462     dest_scan += DestBpp;
   2463   }
   2464 }
   2465 
   2466 void CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan,
   2467                                                     const uint8_t* src_scan,
   2468                                                     int width,
   2469                                                     FX_ARGB* pPalette,
   2470                                                     const uint8_t* clip_scan) {
   2471   for (int col = 0; col < width; col++) {
   2472     int src_r, src_g, src_b;
   2473     if (pPalette) {
   2474       FX_ARGB argb = pPalette[*src_scan];
   2475       src_r = FXARGB_R(argb);
   2476       src_g = FXARGB_G(argb);
   2477       src_b = FXARGB_B(argb);
   2478     } else {
   2479       src_r = src_g = src_b = *src_scan;
   2480     }
   2481     if (!clip_scan || clip_scan[col] == 255) {
   2482       dest_scan[2] = src_b;
   2483       dest_scan[1] = src_g;
   2484       dest_scan[0] = src_r;
   2485       dest_scan[3] = 255;
   2486       src_scan++;
   2487       dest_scan += 4;
   2488       continue;
   2489     }
   2490     int src_alpha = clip_scan[col];
   2491     if (src_alpha == 0) {
   2492       dest_scan += 4;
   2493       src_scan++;
   2494       continue;
   2495     }
   2496     int back_alpha = dest_scan[3];
   2497     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2498     dest_scan[3] = dest_alpha;
   2499     int alpha_ratio = src_alpha * 255 / dest_alpha;
   2500     dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
   2501     dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
   2502     dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
   2503     dest_scan += 4;
   2504     src_scan++;
   2505   }
   2506 }
   2507 
   2508 void CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(uint8_t* dest_scan,
   2509                                                     const uint8_t* src_scan,
   2510                                                     int src_left,
   2511                                                     int width,
   2512                                                     FX_ARGB* pPalette,
   2513                                                     const uint8_t* clip_scan) {
   2514   int reset_r, reset_g, reset_b;
   2515   int set_r, set_g, set_b;
   2516   if (pPalette) {
   2517     reset_r = FXARGB_R(pPalette[0]);
   2518     reset_g = FXARGB_G(pPalette[0]);
   2519     reset_b = FXARGB_B(pPalette[0]);
   2520     set_r = FXARGB_R(pPalette[1]);
   2521     set_g = FXARGB_G(pPalette[1]);
   2522     set_b = FXARGB_B(pPalette[1]);
   2523   } else {
   2524     reset_r = reset_g = reset_b = 0;
   2525     set_r = set_g = set_b = 255;
   2526   }
   2527   for (int col = 0; col < width; col++) {
   2528     int src_r, src_g, src_b;
   2529     if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
   2530       src_r = set_r;
   2531       src_g = set_g;
   2532       src_b = set_b;
   2533     } else {
   2534       src_r = reset_r;
   2535       src_g = reset_g;
   2536       src_b = reset_b;
   2537     }
   2538     if (!clip_scan || clip_scan[col] == 255) {
   2539       dest_scan[2] = src_b;
   2540       dest_scan[1] = src_g;
   2541       dest_scan[0] = src_r;
   2542       dest_scan[3] = 255;
   2543       dest_scan += 4;
   2544       continue;
   2545     }
   2546     int src_alpha = clip_scan[col];
   2547     if (src_alpha == 0) {
   2548       dest_scan += 4;
   2549       continue;
   2550     }
   2551     int back_alpha = dest_scan[3];
   2552     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2553     dest_scan[3] = dest_alpha;
   2554     int alpha_ratio = src_alpha * 255 / dest_alpha;
   2555     dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
   2556     dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
   2557     dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
   2558     dest_scan += 4;
   2559   }
   2560 }
   2561 
   2562 void CompositeRow_ByteMask2Argb_RgbByteOrder(uint8_t* dest_scan,
   2563                                              const uint8_t* src_scan,
   2564                                              int mask_alpha,
   2565                                              int src_r,
   2566                                              int src_g,
   2567                                              int src_b,
   2568                                              int pixel_count,
   2569                                              int blend_type,
   2570                                              const uint8_t* clip_scan) {
   2571   for (int col = 0; col < pixel_count; col++) {
   2572     int src_alpha;
   2573     if (clip_scan) {
   2574       src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   2575     } else {
   2576       src_alpha = mask_alpha * src_scan[col] / 255;
   2577     }
   2578     uint8_t back_alpha = dest_scan[3];
   2579     if (back_alpha == 0) {
   2580       FXARGB_SETRGBORDERDIB(dest_scan,
   2581                             FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   2582       dest_scan += 4;
   2583       continue;
   2584     }
   2585     if (src_alpha == 0) {
   2586       dest_scan += 4;
   2587       continue;
   2588     }
   2589     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2590     dest_scan[3] = dest_alpha;
   2591     int alpha_ratio = src_alpha * 255 / dest_alpha;
   2592     if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2593       int blended_colors[3];
   2594       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
   2595                          static_cast<uint8_t>(src_g),
   2596                          static_cast<uint8_t>(src_r)};
   2597       uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]};
   2598       RGB_Blend(blend_type, scan, dest_scan_o, blended_colors);
   2599       dest_scan[2] =
   2600           FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
   2601       dest_scan[1] =
   2602           FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
   2603       dest_scan[0] =
   2604           FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
   2605     } else if (blend_type) {
   2606       int blended = Blend(blend_type, dest_scan[2], src_b);
   2607       blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   2608       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
   2609       blended = Blend(blend_type, dest_scan[1], src_g);
   2610       blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   2611       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
   2612       blended = Blend(blend_type, dest_scan[0], src_r);
   2613       blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   2614       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
   2615     } else {
   2616       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
   2617       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
   2618       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
   2619     }
   2620     dest_scan += 4;
   2621   }
   2622 }
   2623 
   2624 void CompositeRow_ByteMask2Rgb_RgbByteOrder(uint8_t* dest_scan,
   2625                                             const uint8_t* src_scan,
   2626                                             int mask_alpha,
   2627                                             int src_r,
   2628                                             int src_g,
   2629                                             int src_b,
   2630                                             int pixel_count,
   2631                                             int blend_type,
   2632                                             int Bpp,
   2633                                             const uint8_t* clip_scan) {
   2634   for (int col = 0; col < pixel_count; col++) {
   2635     int src_alpha;
   2636     if (clip_scan) {
   2637       src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
   2638     } else {
   2639       src_alpha = mask_alpha * src_scan[col] / 255;
   2640     }
   2641     if (src_alpha == 0) {
   2642       dest_scan += Bpp;
   2643       continue;
   2644     }
   2645     if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2646       int blended_colors[3];
   2647       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
   2648                          static_cast<uint8_t>(src_g),
   2649                          static_cast<uint8_t>(src_r)};
   2650       uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]};
   2651       RGB_Blend(blend_type, scan, dest_scan_o, blended_colors);
   2652       dest_scan[2] =
   2653           FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
   2654       dest_scan[1] =
   2655           FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
   2656       dest_scan[0] =
   2657           FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
   2658     } else if (blend_type) {
   2659       int blended = Blend(blend_type, dest_scan[2], src_b);
   2660       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha);
   2661       blended = Blend(blend_type, dest_scan[1], src_g);
   2662       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha);
   2663       blended = Blend(blend_type, dest_scan[0], src_r);
   2664       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha);
   2665     } else {
   2666       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha);
   2667       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha);
   2668       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha);
   2669     }
   2670     dest_scan += Bpp;
   2671   }
   2672 }
   2673 
   2674 void CompositeRow_BitMask2Argb_RgbByteOrder(uint8_t* dest_scan,
   2675                                             const uint8_t* src_scan,
   2676                                             int mask_alpha,
   2677                                             int src_r,
   2678                                             int src_g,
   2679                                             int src_b,
   2680                                             int src_left,
   2681                                             int pixel_count,
   2682                                             int blend_type,
   2683                                             const uint8_t* clip_scan) {
   2684   if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) {
   2685     FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b);
   2686     for (int col = 0; col < pixel_count; col++) {
   2687       if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   2688         FXARGB_SETRGBORDERDIB(dest_scan, argb);
   2689       }
   2690       dest_scan += 4;
   2691     }
   2692     return;
   2693   }
   2694   for (int col = 0; col < pixel_count; col++) {
   2695     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   2696       dest_scan += 4;
   2697       continue;
   2698     }
   2699     int src_alpha;
   2700     if (clip_scan) {
   2701       src_alpha = mask_alpha * clip_scan[col] / 255;
   2702     } else {
   2703       src_alpha = mask_alpha;
   2704     }
   2705     uint8_t back_alpha = dest_scan[3];
   2706     if (back_alpha == 0) {
   2707       FXARGB_SETRGBORDERDIB(dest_scan,
   2708                             FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
   2709       dest_scan += 4;
   2710       continue;
   2711     }
   2712     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
   2713     dest_scan[3] = dest_alpha;
   2714     int alpha_ratio = src_alpha * 255 / dest_alpha;
   2715     if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2716       int blended_colors[3];
   2717       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
   2718                          static_cast<uint8_t>(src_g),
   2719                          static_cast<uint8_t>(src_r)};
   2720       uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]};
   2721       RGB_Blend(blend_type, scan, dest_scan_o, blended_colors);
   2722       dest_scan[2] =
   2723           FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
   2724       dest_scan[1] =
   2725           FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
   2726       dest_scan[0] =
   2727           FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
   2728     } else if (blend_type) {
   2729       int blended = Blend(blend_type, dest_scan[2], src_b);
   2730       blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
   2731       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
   2732       blended = Blend(blend_type, dest_scan[1], src_g);
   2733       blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
   2734       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
   2735       blended = Blend(blend_type, dest_scan[0], src_r);
   2736       blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
   2737       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
   2738     } else {
   2739       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
   2740       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
   2741       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
   2742     }
   2743     dest_scan += 4;
   2744   }
   2745 }
   2746 
   2747 void CompositeRow_BitMask2Rgb_RgbByteOrder(uint8_t* dest_scan,
   2748                                            const uint8_t* src_scan,
   2749                                            int mask_alpha,
   2750                                            int src_r,
   2751                                            int src_g,
   2752                                            int src_b,
   2753                                            int src_left,
   2754                                            int pixel_count,
   2755                                            int blend_type,
   2756                                            int Bpp,
   2757                                            const uint8_t* clip_scan) {
   2758   if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) {
   2759     for (int col = 0; col < pixel_count; col++) {
   2760       if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
   2761         dest_scan[2] = src_b;
   2762         dest_scan[1] = src_g;
   2763         dest_scan[0] = src_r;
   2764       }
   2765       dest_scan += Bpp;
   2766     }
   2767     return;
   2768   }
   2769   for (int col = 0; col < pixel_count; col++) {
   2770     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
   2771       dest_scan += Bpp;
   2772       continue;
   2773     }
   2774     int src_alpha;
   2775     if (clip_scan) {
   2776       src_alpha = mask_alpha * clip_scan[col] / 255;
   2777     } else {
   2778       src_alpha = mask_alpha;
   2779     }
   2780     if (src_alpha == 0) {
   2781       dest_scan += Bpp;
   2782       continue;
   2783     }
   2784     if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
   2785       int blended_colors[3];
   2786       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
   2787                          static_cast<uint8_t>(src_g),
   2788                          static_cast<uint8_t>(src_r)};
   2789       uint8_t dest_scan_o[3] = {dest_scan[2], dest_scan[1], dest_scan[0]};
   2790       RGB_Blend(blend_type, scan, dest_scan_o, blended_colors);
   2791       dest_scan[2] =
   2792           FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
   2793       dest_scan[1] =
   2794           FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
   2795       dest_scan[0] =
   2796           FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
   2797     } else if (blend_type) {
   2798       int back_color = dest_scan[2];
   2799       int blended = Blend(blend_type, back_color, src_b);
   2800       dest_scan[2] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
   2801       back_color = dest_scan[1];
   2802       blended = Blend(blend_type, back_color, src_g);
   2803       dest_scan[1] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
   2804       back_color = dest_scan[0];
   2805       blended = Blend(blend_type, back_color, src_r);
   2806       dest_scan[0] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
   2807     } else {
   2808       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha);
   2809       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha);
   2810       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha);
   2811     }
   2812     dest_scan += Bpp;
   2813   }
   2814 }
   2815 
   2816 }  // namespace
   2817 
   2818 CFX_ScanlineCompositor::CFX_ScanlineCompositor()
   2819     : m_BlendType(FXDIB_BLEND_NORMAL), m_bRgbByteOrder(false) {}
   2820 
   2821 CFX_ScanlineCompositor::~CFX_ScanlineCompositor() {}
   2822 
   2823 bool CFX_ScanlineCompositor::Init(FXDIB_Format dest_format,
   2824                                   FXDIB_Format src_format,
   2825                                   int32_t width,
   2826                                   uint32_t* pSrcPalette,
   2827                                   uint32_t mask_color,
   2828                                   int blend_type,
   2829                                   bool bClip,
   2830                                   bool bRgbByteOrder,
   2831                                   int alpha_flag) {
   2832   m_SrcFormat = src_format;
   2833   m_DestFormat = dest_format;
   2834   m_BlendType = blend_type;
   2835   m_bRgbByteOrder = bRgbByteOrder;
   2836   if ((dest_format & 0xff) == 1)
   2837     return false;
   2838   if (m_SrcFormat == FXDIB_1bppMask || m_SrcFormat == FXDIB_8bppMask) {
   2839     InitSourceMask(alpha_flag, mask_color);
   2840     return true;
   2841   }
   2842   if ((~src_format & 0x0400) && (dest_format & 0x0400))
   2843     return false;
   2844   if ((m_SrcFormat & 0xff) <= 8) {
   2845     if (dest_format == FXDIB_8bppMask)
   2846       return true;
   2847 
   2848     InitSourcePalette(src_format, dest_format, pSrcPalette);
   2849     m_iTransparency =
   2850         (dest_format == FXDIB_Argb ? 1 : 0) + (dest_format & 0x0200 ? 2 : 0) +
   2851         (dest_format & 0x0400 ? 4 : 0) + ((src_format & 0xff) == 1 ? 8 : 0);
   2852     return true;
   2853   }
   2854   m_iTransparency =
   2855       (src_format & 0x0200 ? 0 : 1) + (dest_format & 0x0200 ? 0 : 2) +
   2856       (blend_type == FXDIB_BLEND_NORMAL ? 4 : 0) + (bClip ? 8 : 0) +
   2857       (src_format & 0x0400 ? 16 : 0) + (dest_format & 0x0400 ? 32 : 0);
   2858   return true;
   2859 }
   2860 
   2861 void CFX_ScanlineCompositor::InitSourceMask(int alpha_flag,
   2862                                             uint32_t mask_color) {
   2863   int mask_black = 0;
   2864   if (alpha_flag >> 8) {
   2865     m_MaskAlpha = alpha_flag & 0xff;
   2866     m_MaskRed = FXSYS_GetCValue(mask_color);
   2867     m_MaskGreen = FXSYS_GetMValue(mask_color);
   2868     m_MaskBlue = FXSYS_GetYValue(mask_color);
   2869     mask_black = FXSYS_GetKValue(mask_color);
   2870   } else {
   2871     m_MaskAlpha = FXARGB_A(mask_color);
   2872     m_MaskRed = FXARGB_R(mask_color);
   2873     m_MaskGreen = FXARGB_G(mask_color);
   2874     m_MaskBlue = FXARGB_B(mask_color);
   2875   }
   2876   if (m_DestFormat == FXDIB_8bppMask)
   2877     return;
   2878 
   2879   if ((m_DestFormat & 0xff) == 8) {
   2880     if (alpha_flag >> 8) {
   2881       uint8_t r;
   2882       uint8_t g;
   2883       uint8_t b;
   2884       std::tie(r, g, b) =
   2885           AdobeCMYK_to_sRGB1(m_MaskRed, m_MaskGreen, m_MaskBlue, mask_black);
   2886       m_MaskRed = FXRGB2GRAY(r, g, b);
   2887     } else {
   2888       m_MaskRed = FXRGB2GRAY(m_MaskRed, m_MaskGreen, m_MaskBlue);
   2889     }
   2890     if (m_DestFormat & 0x0400)
   2891       m_MaskRed = FX_CCOLOR(m_MaskRed);
   2892     return;
   2893   }
   2894   uint8_t* mask_color_p = (uint8_t*)&mask_color;
   2895   mask_color =
   2896       (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color);
   2897   if (alpha_flag >> 8) {
   2898     std::tie(mask_color_p[2], mask_color_p[1], mask_color_p[0]) =
   2899         AdobeCMYK_to_sRGB1(mask_color_p[0], mask_color_p[1], mask_color_p[2],
   2900                            mask_color_p[3]);
   2901     m_MaskRed = mask_color_p[2];
   2902     m_MaskGreen = mask_color_p[1];
   2903     m_MaskBlue = mask_color_p[0];
   2904   }
   2905 }
   2906 
   2907 void CFX_ScanlineCompositor::InitSourcePalette(FXDIB_Format src_format,
   2908                                                FXDIB_Format dest_format,
   2909                                                const uint32_t* pSrcPalette) {
   2910   bool isSrcCmyk = !!(src_format & 0x0400);
   2911   bool isDstCmyk = !!(dest_format & 0x0400);
   2912   m_pSrcPalette = nullptr;
   2913   if (pSrcPalette) {
   2914     if ((dest_format & 0xff) == 8) {
   2915       int pal_count = 1 << (src_format & 0xff);
   2916       uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count);
   2917       m_pSrcPalette.reset(reinterpret_cast<uint32_t*>(gray_pal));
   2918       if (isSrcCmyk) {
   2919         for (int i = 0; i < pal_count; ++i) {
   2920           FX_CMYK cmyk = pSrcPalette[i];
   2921           uint8_t r;
   2922           uint8_t g;
   2923           uint8_t b;
   2924           std::tie(r, g, b) =
   2925               AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk),
   2926                                  FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk));
   2927           *gray_pal++ = FXRGB2GRAY(r, g, b);
   2928         }
   2929       } else {
   2930         for (int i = 0; i < pal_count; ++i) {
   2931           FX_ARGB argb = pSrcPalette[i];
   2932           *gray_pal++ =
   2933               FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
   2934         }
   2935       }
   2936       return;
   2937     }
   2938     int palsize = 1 << (src_format & 0xff);
   2939     m_pSrcPalette.reset(FX_Alloc(uint32_t, palsize));
   2940     uint32_t* pPalette = m_pSrcPalette.get();
   2941     if (isDstCmyk == isSrcCmyk) {
   2942       memcpy(pPalette, pSrcPalette, palsize * sizeof(uint32_t));
   2943     } else {
   2944       for (int i = 0; i < palsize; ++i) {
   2945         FX_CMYK cmyk = pSrcPalette[i];
   2946         uint8_t r;
   2947         uint8_t g;
   2948         uint8_t b;
   2949         std::tie(r, g, b) =
   2950             AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk),
   2951                                FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk));
   2952         pPalette[i] = FXARGB_MAKE(0xff, r, g, b);
   2953       }
   2954     }
   2955     return;
   2956   }
   2957   if ((dest_format & 0xff) == 8) {
   2958     int pal_count = 1 << (src_format & 0xff);
   2959     uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count);
   2960     if (pal_count == 2) {
   2961       gray_pal[0] = 0;
   2962       gray_pal[1] = 255;
   2963     } else {
   2964       for (int i = 0; i < pal_count; ++i)
   2965         gray_pal[i] = i;
   2966     }
   2967     m_pSrcPalette.reset(reinterpret_cast<uint32_t*>(gray_pal));
   2968     return;
   2969   }
   2970   int palsize = 1 << (src_format & 0xff);
   2971   m_pSrcPalette.reset(FX_Alloc(uint32_t, palsize));
   2972   uint32_t* pPalette = m_pSrcPalette.get();
   2973   if (palsize == 2) {
   2974     pPalette[0] = isSrcCmyk ? 255 : 0xff000000;
   2975     pPalette[1] = isSrcCmyk ? 0 : 0xffffffff;
   2976   } else {
   2977     for (int i = 0; i < palsize; ++i)
   2978       pPalette[i] = isSrcCmyk ? FX_CCOLOR(i) : (i * 0x10101);
   2979   }
   2980   if (isSrcCmyk != isDstCmyk) {
   2981     for (int i = 0; i < palsize; ++i) {
   2982       FX_CMYK cmyk = pPalette[i];
   2983       uint8_t r;
   2984       uint8_t g;
   2985       uint8_t b;
   2986       std::tie(r, g, b) =
   2987           AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk),
   2988                              FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk));
   2989       pPalette[i] = FXARGB_MAKE(0xff, r, g, b);
   2990     }
   2991   }
   2992 }
   2993 
   2994 void CFX_ScanlineCompositor::CompositeRgbBitmapLine(
   2995     uint8_t* dest_scan,
   2996     const uint8_t* src_scan,
   2997     int width,
   2998     const uint8_t* clip_scan,
   2999     const uint8_t* src_extra_alpha,
   3000     uint8_t* dst_extra_alpha) {
   3001   int src_Bpp = (m_SrcFormat & 0xff) >> 3;
   3002   int dest_Bpp = (m_DestFormat & 0xff) >> 3;
   3003   if (m_bRgbByteOrder) {
   3004     switch (m_iTransparency) {
   3005       case 0:
   3006       case 4:
   3007       case 8:
   3008       case 12:
   3009         CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width,
   3010                                             m_BlendType, clip_scan);
   3011         break;
   3012       case 1:
   3013         CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(
   3014             dest_scan, src_scan, width, m_BlendType, src_Bpp);
   3015         break;
   3016       case 2:
   3017       case 10:
   3018         CompositeRow_Argb2Rgb_Blend_RgbByteOrder(
   3019             dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan);
   3020         break;
   3021       case 3:
   3022         CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(
   3023             dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp);
   3024         break;
   3025       case 5:
   3026         CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan,
   3027                                                           width, src_Bpp);
   3028         break;
   3029       case 6:
   3030       case 14:
   3031         CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width,
   3032                                                    dest_Bpp, clip_scan);
   3033         break;
   3034       case 7:
   3035         CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(
   3036             dest_scan, src_scan, width, dest_Bpp, src_Bpp);
   3037         break;
   3038       case 9:
   3039         CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(
   3040             dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan);
   3041         break;
   3042       case 11:
   3043         CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width,
   3044                                                      m_BlendType, dest_Bpp,
   3045                                                      src_Bpp, clip_scan);
   3046         break;
   3047       case 13:
   3048         CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(
   3049             dest_scan, src_scan, width, src_Bpp, clip_scan);
   3050         break;
   3051       case 15:
   3052         CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(
   3053             dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan);
   3054         break;
   3055     }
   3056     return;
   3057   }
   3058   if (m_DestFormat == FXDIB_8bppMask) {
   3059     if (m_SrcFormat & 0x0200) {
   3060       if (m_SrcFormat == FXDIB_Argb) {
   3061         CompositeRow_AlphaToMask(dest_scan, src_scan, width, clip_scan, 4);
   3062       } else {
   3063         CompositeRow_AlphaToMask(dest_scan, src_extra_alpha, width, clip_scan,
   3064                                  1);
   3065       }
   3066     } else {
   3067       CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
   3068     }
   3069   } else if ((m_DestFormat & 0xff) == 8) {
   3070     if (m_DestFormat & 0x0400) {
   3071       for (int i = 0; i < width; ++i) {
   3072         *dest_scan = ~*dest_scan;
   3073         dest_scan++;
   3074       }
   3075     }
   3076     if (m_SrcFormat & 0x0200) {
   3077       if (m_DestFormat & 0x0200) {
   3078         CompositeRow_Argb2Graya(dest_scan, src_scan, width, m_BlendType,
   3079                                 clip_scan, src_extra_alpha, dst_extra_alpha);
   3080       } else {
   3081         CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType,
   3082                                clip_scan, src_extra_alpha);
   3083       }
   3084     } else {
   3085       if (m_DestFormat & 0x0200) {
   3086         CompositeRow_Rgb2Graya(dest_scan, src_scan, src_Bpp, width, m_BlendType,
   3087                                clip_scan, dst_extra_alpha);
   3088       } else {
   3089         CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType,
   3090                               clip_scan);
   3091       }
   3092     }
   3093     if (m_DestFormat & 0x0400) {
   3094       for (int i = 0; i < width; ++i) {
   3095         *dest_scan = ~*dest_scan;
   3096         dest_scan++;
   3097       }
   3098     }
   3099   } else {
   3100     switch (m_iTransparency) {
   3101       case 0:
   3102       case 4:
   3103       case 8:
   3104       case 4 + 8: {
   3105         CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType,
   3106                                clip_scan, dst_extra_alpha, src_extra_alpha);
   3107       } break;
   3108       case 1:
   3109         CompositeRow_Rgb2Argb_Blend_NoClip(
   3110             dest_scan, src_scan, width, m_BlendType, src_Bpp, dst_extra_alpha);
   3111         break;
   3112       case 1 + 8:
   3113         CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width,
   3114                                          m_BlendType, src_Bpp, clip_scan,
   3115                                          dst_extra_alpha);
   3116         break;
   3117       case 1 + 4:
   3118         CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width,
   3119                                              src_Bpp, dst_extra_alpha);
   3120         break;
   3121       case 1 + 4 + 8:
   3122         CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp,
   3123                                            clip_scan, dst_extra_alpha);
   3124         break;
   3125       case 2:
   3126       case 2 + 8:
   3127         CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType,
   3128                                     dest_Bpp, clip_scan, src_extra_alpha);
   3129         break;
   3130       case 2 + 4:
   3131       case 2 + 4 + 8:
   3132         CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp,
   3133                                       clip_scan, src_extra_alpha);
   3134         break;
   3135       case 1 + 2:
   3136         CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width,
   3137                                           m_BlendType, dest_Bpp, src_Bpp);
   3138         break;
   3139       case 1 + 2 + 8:
   3140         CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width, m_BlendType,
   3141                                         dest_Bpp, src_Bpp, clip_scan);
   3142         break;
   3143       case 1 + 2 + 4:
   3144         CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width,
   3145                                             dest_Bpp, src_Bpp);
   3146         break;
   3147       case 1 + 2 + 4 + 8:
   3148         CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp,
   3149                                           src_Bpp, clip_scan);
   3150         break;
   3151     }
   3152   }
   3153 }
   3154 
   3155 void CFX_ScanlineCompositor::CompositePalBitmapLine(
   3156     uint8_t* dest_scan,
   3157     const uint8_t* src_scan,
   3158     int src_left,
   3159     int width,
   3160     const uint8_t* clip_scan,
   3161     const uint8_t* src_extra_alpha,
   3162     uint8_t* dst_extra_alpha) {
   3163   if (m_bRgbByteOrder) {
   3164     if (m_SrcFormat == FXDIB_1bppRgb) {
   3165       if (m_DestFormat == FXDIB_8bppRgb) {
   3166         return;
   3167       }
   3168       if (m_DestFormat == FXDIB_Argb) {
   3169         CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(
   3170             dest_scan, src_scan, src_left, width, m_pSrcPalette.get(),
   3171             clip_scan);
   3172       } else {
   3173         CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(
   3174             dest_scan, src_scan, src_left, m_pSrcPalette.get(), width,
   3175             (m_DestFormat & 0xff) >> 3, clip_scan);
   3176       }
   3177     } else {
   3178       if (m_DestFormat == FXDIB_8bppRgb) {
   3179         return;
   3180       }
   3181       if (m_DestFormat == FXDIB_Argb) {
   3182         CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(
   3183             dest_scan, src_scan, width, m_pSrcPalette.get(), clip_scan);
   3184       } else {
   3185         CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(
   3186             dest_scan, src_scan, m_pSrcPalette.get(), width,
   3187             (m_DestFormat & 0xff) >> 3, clip_scan);
   3188       }
   3189     }
   3190     return;
   3191   }
   3192   if (m_DestFormat == FXDIB_8bppMask) {
   3193     CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
   3194     return;
   3195   }
   3196   if ((m_DestFormat & 0xff) == 8) {
   3197     if (m_iTransparency & 8) {
   3198       if (m_DestFormat & 0x0200) {
   3199         CompositeRow_1bppPal2Graya(
   3200             dest_scan, src_scan, src_left,
   3201             reinterpret_cast<const uint8_t*>(m_pSrcPalette.get()), width,
   3202             m_BlendType, clip_scan, dst_extra_alpha);
   3203       } else {
   3204         CompositeRow_1bppPal2Gray(
   3205             dest_scan, src_scan, src_left,
   3206             reinterpret_cast<const uint8_t*>(m_pSrcPalette.get()), width,
   3207             m_BlendType, clip_scan);
   3208       }
   3209     } else {
   3210       if (m_DestFormat & 0x0200)
   3211         CompositeRow_8bppPal2Graya(
   3212             dest_scan, src_scan,
   3213             reinterpret_cast<const uint8_t*>(m_pSrcPalette.get()), width,
   3214             m_BlendType, clip_scan, dst_extra_alpha, src_extra_alpha);
   3215       else
   3216         CompositeRow_8bppPal2Gray(
   3217             dest_scan, src_scan,
   3218             reinterpret_cast<const uint8_t*>(m_pSrcPalette.get()), width,
   3219             m_BlendType, clip_scan, src_extra_alpha);
   3220     }
   3221   } else {
   3222     switch (m_iTransparency) {
   3223       case 1 + 2:
   3224         CompositeRow_8bppRgb2Argb_NoBlend(dest_scan, src_scan, width,
   3225                                           m_pSrcPalette.get(), clip_scan,
   3226                                           src_extra_alpha);
   3227         break;
   3228       case 1 + 2 + 8:
   3229         CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width,
   3230                                           m_pSrcPalette.get(), clip_scan);
   3231         break;
   3232       case 0:
   3233         CompositeRow_8bppRgb2Rgb_NoBlend(
   3234             dest_scan, src_scan, m_pSrcPalette.get(), width,
   3235             (m_DestFormat & 0xff) >> 3, clip_scan, src_extra_alpha);
   3236         break;
   3237       case 0 + 8:
   3238         CompositeRow_1bppRgb2Rgb_NoBlend(dest_scan, src_scan, src_left,
   3239                                          m_pSrcPalette.get(), width,
   3240                                          (m_DestFormat & 0xff) >> 3, clip_scan);
   3241         break;
   3242       case 0 + 2:
   3243         CompositeRow_8bppRgb2Rgb_NoBlend(
   3244             dest_scan, src_scan, m_pSrcPalette.get(), width,
   3245             (m_DestFormat & 0xff) >> 3, clip_scan, src_extra_alpha);
   3246         break;
   3247       case 0 + 2 + 8:
   3248         CompositeRow_1bppRgb2Rgba_NoBlend(dest_scan, src_scan, src_left, width,
   3249                                           m_pSrcPalette.get(), clip_scan,
   3250                                           dst_extra_alpha);
   3251         break;
   3252         break;
   3253     }
   3254   }
   3255 }
   3256 
   3257 void CFX_ScanlineCompositor::CompositeByteMaskLine(uint8_t* dest_scan,
   3258                                                    const uint8_t* src_scan,
   3259                                                    int width,
   3260                                                    const uint8_t* clip_scan,
   3261                                                    uint8_t* dst_extra_alpha) {
   3262   if (m_DestFormat == FXDIB_8bppMask) {
   3263     CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width,
   3264                                clip_scan);
   3265   } else if ((m_DestFormat & 0xff) == 8) {
   3266     if (m_DestFormat & 0x0200) {
   3267       CompositeRow_ByteMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
   3268                                   width, clip_scan, dst_extra_alpha);
   3269     } else {
   3270       CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
   3271                                  width, clip_scan);
   3272     }
   3273   } else if (m_bRgbByteOrder) {
   3274     if (m_DestFormat == FXDIB_Argb) {
   3275       CompositeRow_ByteMask2Argb_RgbByteOrder(
   3276           dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   3277           width, m_BlendType, clip_scan);
   3278     } else {
   3279       CompositeRow_ByteMask2Rgb_RgbByteOrder(
   3280           dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   3281           width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   3282     }
   3283     return;
   3284   } else if (m_DestFormat == FXDIB_Argb) {
   3285     CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
   3286                                m_MaskGreen, m_MaskBlue, width, m_BlendType,
   3287                                clip_scan);
   3288   } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) {
   3289     CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
   3290                               m_MaskGreen, m_MaskBlue, width, m_BlendType,
   3291                               (m_DestFormat & 0xff) >> 3, clip_scan);
   3292   } else if (m_DestFormat == FXDIB_Rgba) {
   3293     CompositeRow_ByteMask2Rgba(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
   3294                                m_MaskGreen, m_MaskBlue, width, m_BlendType,
   3295                                clip_scan, dst_extra_alpha);
   3296   }
   3297 }
   3298 
   3299 void CFX_ScanlineCompositor::CompositeBitMaskLine(uint8_t* dest_scan,
   3300                                                   const uint8_t* src_scan,
   3301                                                   int src_left,
   3302                                                   int width,
   3303                                                   const uint8_t* clip_scan,
   3304                                                   uint8_t* dst_extra_alpha) {
   3305   if (m_DestFormat == FXDIB_8bppMask) {
   3306     CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left, width,
   3307                               clip_scan);
   3308   } else if ((m_DestFormat & 0xff) == 8) {
   3309     if (m_DestFormat & 0x0200) {
   3310       CompositeRow_BitMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
   3311                                  src_left, width, clip_scan, dst_extra_alpha);
   3312     } else {
   3313       CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
   3314                                 src_left, width, clip_scan);
   3315     }
   3316   } else if (m_bRgbByteOrder) {
   3317     if (m_DestFormat == FXDIB_Argb) {
   3318       CompositeRow_BitMask2Argb_RgbByteOrder(
   3319           dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   3320           src_left, width, m_BlendType, clip_scan);
   3321     } else {
   3322       CompositeRow_BitMask2Rgb_RgbByteOrder(
   3323           dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   3324           src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   3325     }
   3326     return;
   3327   } else if (m_DestFormat == FXDIB_Argb) {
   3328     CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
   3329                               m_MaskGreen, m_MaskBlue, src_left, width,
   3330                               m_BlendType, clip_scan);
   3331   } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) {
   3332     CompositeRow_BitMask2Rgb(
   3333         dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
   3334         src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
   3335   }
   3336 }
   3337