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