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