Don't bother checking pointers before delete[] and FX_Free().
[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     }