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