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