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