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