da555de9d501b45bae80e8e7acc438ec9f9014fd
[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     int src_gap = src_Bpp - 3;
2955     for (int col = 0; col < width; col ++) {
2956         if (src_Bpp == 4) {
2957             FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
2958         } else {
2959             FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
2960         }
2961         dest_scan += 4;
2962         src_scan += src_Bpp;
2963     }
2964 }
2965 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)
2966 {
2967     int blended_colors[3];
2968     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
2969     int src_gap = src_Bpp - 3;
2970     for (int col = 0; col < width; col ++) {
2971         if (bNonseparableBlend) {
2972             FX_BYTE dest_scan_o[3];
2973             dest_scan_o[0] = dest_scan[2];
2974             dest_scan_o[1] = dest_scan[1];
2975             dest_scan_o[2] = dest_scan[0];
2976             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
2977         }
2978         for (int color = 0; color < 3; color ++) {
2979             int index = 2 - color;
2980             int back_color = FX_GAMMA(dest_scan[index]);
2981             int src_color = FX_GAMMA(*src_scan);
2982             int blended = bNonseparableBlend ? blended_colors[color] :
2983                           _BLEND(blend_type, back_color, src_color);
2984             dest_scan[index] = FX_GAMMA_INVERSE(blended);
2985             src_scan ++;
2986         }
2987         dest_scan += dest_Bpp;
2988         src_scan += src_gap;
2989     }
2990 }
2991 inline void _CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, FX_LPCBYTE clip_scan)
2992 {
2993     for (int col = 0; col < width; col ++) {
2994         FX_BYTE src_alpha;
2995         if (clip_scan) {
2996             src_alpha = src_scan[3] * (*clip_scan++) / 255;
2997         } else {
2998             src_alpha = src_scan[3];
2999         }
3000         if (src_alpha == 255) {
3001             dest_scan[2] = FX_GAMMA_INVERSE(*src_scan++);
3002             dest_scan[1] = FX_GAMMA_INVERSE(*src_scan++);
3003             dest_scan[0] = FX_GAMMA_INVERSE(*src_scan++);
3004             dest_scan += dest_Bpp;
3005             src_scan ++;
3006             continue;
3007         }
3008         if (src_alpha == 0) {
3009             dest_scan += dest_Bpp;
3010             src_scan += 4;
3011             continue;
3012         }
3013         for (int color = 0; color < 3; color ++) {
3014             int index = 2 - color;
3015             dest_scan[index] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[index]), *src_scan, src_alpha));
3016             src_scan ++;
3017         }
3018         dest_scan += dest_Bpp;
3019         src_scan ++;
3020     }
3021 }
3022 inline void _CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int dest_Bpp, int src_Bpp)
3023 {
3024     for (int col = 0; col < width; col ++) {
3025         dest_scan[2] = src_scan[0];
3026         dest_scan[1] = src_scan[1];
3027         dest_scan[0] = src_scan[2];
3028         dest_scan += dest_Bpp;
3029         src_scan += src_Bpp;
3030     }
3031 }
3032 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)
3033 {
3034     int blended_colors[3];
3035     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
3036     int src_gap = src_Bpp - 3;
3037     for (int col = 0; col < width; col ++) {
3038         int src_alpha = *clip_scan ++;
3039         FX_BYTE back_alpha = dest_scan[3];
3040         if (back_alpha == 0) {
3041             dest_scan[2] = FX_GAMMA(*src_scan++);
3042             dest_scan[1] = FX_GAMMA(*src_scan++);
3043             dest_scan[0] = FX_GAMMA(*src_scan++);
3044             src_scan += src_gap;
3045             dest_scan += 4;
3046             continue;
3047         }
3048         if (src_alpha == 0) {
3049             dest_scan += 4;
3050             src_scan += src_Bpp;
3051             continue;
3052         }
3053         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
3054         dest_scan[3] = dest_alpha;
3055         int alpha_ratio = src_alpha * 255 / dest_alpha;
3056         if (bNonseparableBlend) {
3057             FX_BYTE dest_scan_o[3];
3058             dest_scan_o[0] = dest_scan[2];
3059             dest_scan_o[1] = dest_scan[1];
3060             dest_scan_o[2] = dest_scan[0];
3061             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
3062         }
3063         for (int color = 0; color < 3; color ++) {
3064             int index = 2 - color;
3065             int src_color = FX_GAMMA(*src_scan);
3066             int blended = bNonseparableBlend ? blended_colors[color] :
3067                           _BLEND(blend_type, dest_scan[index], src_color);
3068             blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
3069             dest_scan[index] = FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
3070             src_scan ++;
3071         }
3072         dest_scan += 4;
3073         src_scan += src_gap;
3074     }
3075 }
3076 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)
3077 {
3078     int blended_colors[3];
3079     FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
3080     int src_gap = src_Bpp - 3;
3081     for (int col = 0; col < width; col ++) {
3082         FX_BYTE src_alpha = *clip_scan ++;
3083         if (src_alpha == 0) {
3084             dest_scan += dest_Bpp;
3085             src_scan += src_Bpp;
3086             continue;
3087         }
3088         if (bNonseparableBlend) {
3089             FX_BYTE dest_scan_o[3];
3090             dest_scan_o[0] = dest_scan[2];
3091             dest_scan_o[1] = dest_scan[1];
3092             dest_scan_o[2] = dest_scan[0];
3093             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
3094         }
3095         for (int color = 0; color < 3; color ++) {
3096             int index = 2 - color;
3097             int src_color = FX_GAMMA(*src_scan);
3098             int back_color = FX_GAMMA(dest_scan[index]);
3099             int blended = bNonseparableBlend ? blended_colors[color] :
3100                           _BLEND(blend_type, back_color, src_color);
3101             dest_scan[index] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
3102             src_scan ++;
3103         }
3104         dest_scan += dest_Bpp;
3105         src_scan += src_gap;
3106     }
3107 }
3108 inline void _CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, int src_Bpp, FX_LPCBYTE clip_scan)
3109 {
3110     int src_gap = src_Bpp - 3;
3111     for (int col = 0; col < width; col ++) {
3112         int src_alpha = clip_scan[col];
3113         if (src_alpha == 255) {
3114             dest_scan[2] = FX_GAMMA(*src_scan++);
3115             dest_scan[1] = FX_GAMMA(*src_scan++);
3116             dest_scan[0] = FX_GAMMA(*src_scan++);
3117             dest_scan[3] = 255;
3118             dest_scan += 4;
3119             src_scan  += src_gap;
3120             continue;
3121         }
3122         if (src_alpha == 0) {
3123             dest_scan += 4;
3124             src_scan += src_Bpp;
3125             continue;
3126         }
3127         int back_alpha = dest_scan[3];
3128         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
3129         dest_scan[3] = dest_alpha;
3130         int alpha_ratio = src_alpha * 255 / dest_alpha;
3131         for (int color = 0; color < 3; color ++) {
3132             int index = 2 - color;
3133             dest_scan[index] = FXDIB_ALPHA_MERGE(dest_scan[index], FX_GAMMA(*src_scan), alpha_ratio);
3134             src_scan ++;
3135         }
3136         dest_scan += 4;
3137         src_scan += src_gap;
3138     }
3139 }
3140 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)
3141 {
3142     for (int col = 0; col < width; col ++) {
3143         int src_alpha = clip_scan[col];
3144         if (src_alpha == 255) {
3145             dest_scan[2] = src_scan[0];
3146             dest_scan[1] = src_scan[1];
3147             dest_scan[0] = src_scan[2];
3148         } else if (src_alpha) {
3149             dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), FX_GAMMA(*src_scan), src_alpha));
3150             src_scan ++;
3151             dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), FX_GAMMA(*src_scan), src_alpha));
3152             src_scan ++;
3153             dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), FX_GAMMA(*src_scan), src_alpha));
3154             dest_scan += dest_Bpp;
3155             src_scan += src_Bpp - 2;
3156             continue;
3157         }
3158         dest_scan += dest_Bpp;
3159         src_scan += src_Bpp;
3160     }
3161 }
3162 inline void _CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, FX_ARGB* pPalette, int pixel_count,
3163         int DestBpp, FX_LPCBYTE clip_scan)
3164 {
3165     for (int col = 0; col < pixel_count; col ++) {
3166         FX_ARGB argb = pPalette ? pPalette[*src_scan] : (*src_scan) * 0x010101;
3167         int src_r = FXARGB_R(argb);
3168         int src_g = FXARGB_G(argb);
3169         int src_b = FXARGB_B(argb);
3170         if (clip_scan && clip_scan[col] < 255) {
3171             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
3172             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
3173             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
3174         } else {
3175             dest_scan[2] = src_b;
3176             dest_scan[1] = src_g;
3177             dest_scan[0] = src_r;
3178         }
3179         dest_scan += DestBpp;
3180         src_scan ++;
3181     }
3182 }
3183 inline void _CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left,
3184         FX_ARGB* pPalette, int pixel_count, int DestBpp, FX_LPCBYTE clip_scan)
3185 {
3186     int reset_r, reset_g, reset_b;
3187     int set_r, set_g, set_b;
3188     if (pPalette) {
3189         reset_r = FXARGB_R(pPalette[0]);
3190         reset_g = FXARGB_G(pPalette[0]);
3191         reset_b = FXARGB_B(pPalette[0]);
3192         set_r = FXARGB_R(pPalette[1]);
3193         set_g = FXARGB_G(pPalette[1]);
3194         set_b = FXARGB_B(pPalette[1]);
3195     } else {
3196         reset_r = reset_g = reset_b = 0;
3197         set_r = set_g = set_b = 255;
3198     }
3199     for (int col = 0; col < pixel_count; col ++) {
3200         int src_r, src_g, src_b;
3201         if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
3202             src_r = set_r;
3203             src_g = set_g;
3204             src_b = set_b;
3205         } else {
3206             src_r = reset_r;
3207             src_g = reset_g;
3208             src_b = reset_b;
3209         }
3210         if (clip_scan && clip_scan[col] < 255) {
3211             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
3212             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
3213             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
3214         } else {
3215             dest_scan[2] = src_b;
3216             dest_scan[1] = src_g;
3217             dest_scan[0] = src_r;
3218         }
3219         dest_scan += DestBpp;
3220     }
3221 }
3222 inline void _CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width,
3223         FX_ARGB* pPalette, FX_LPCBYTE clip_scan)
3224 {
3225     for (int col = 0; col < width; col ++) {
3226         int src_r, src_g, src_b;
3227         if (pPalette) {
3228             FX_ARGB argb = pPalette[*src_scan];
3229             src_r = FXARGB_R(argb);
3230             src_g = FXARGB_G(argb);
3231             src_b = FXARGB_B(argb);
3232         } else {
3233             src_r = src_g = src_b = *src_scan;
3234         }
3235         if (clip_scan == NULL || clip_scan[col] == 255) {
3236             dest_scan[2] = FX_GAMMA(src_b);
3237             dest_scan[1] = FX_GAMMA(src_g);
3238             dest_scan[0] = FX_GAMMA(src_r);
3239             dest_scan[3] = 255;
3240             src_scan ++;
3241             dest_scan += 4;
3242             continue;
3243         }
3244         int src_alpha = clip_scan[col];
3245         if (src_alpha == 0) {
3246             dest_scan += 4;
3247             src_scan ++;
3248             continue;
3249         }
3250         int back_alpha = dest_scan[3];
3251         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
3252         dest_scan[3] = dest_alpha;
3253         int alpha_ratio = src_alpha * 255 / dest_alpha;
3254         dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], FX_GAMMA(src_b), alpha_ratio);
3255         dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], FX_GAMMA(src_g), alpha_ratio);
3256         dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], FX_GAMMA(src_r), alpha_ratio);
3257         dest_scan += 4;
3258         src_scan ++;
3259     }
3260 }
3261 inline void _CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width,
3262         FX_ARGB* pPalette, FX_LPCBYTE clip_scan)
3263 {
3264     int reset_r, reset_g, reset_b;
3265     int set_r, set_g, set_b;
3266     if (pPalette) {
3267         reset_r = FXARGB_R(pPalette[0]);
3268         reset_g = FXARGB_G(pPalette[0]);
3269         reset_b = FXARGB_B(pPalette[0]);
3270         set_r = FXARGB_R(pPalette[1]);
3271         set_g = FXARGB_G(pPalette[1]);
3272         set_b = FXARGB_B(pPalette[1]);
3273     } else {
3274         reset_r = reset_g = reset_b = 0;
3275         set_r = set_g = set_b = 255;
3276     }
3277     for (int col = 0; col < width; col ++) {
3278         int src_r, src_g, src_b;
3279         if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
3280             src_r = set_r;
3281             src_g = set_g;
3282             src_b = set_b;
3283         } else {
3284             src_r = reset_r;
3285             src_g = reset_g;
3286             src_b = reset_b;
3287         }
3288         if (clip_scan == NULL || clip_scan[col] == 255) {
3289             dest_scan[2] = FX_GAMMA(src_b);
3290             dest_scan[1] = FX_GAMMA(src_g);
3291             dest_scan[0] = FX_GAMMA(src_r);
3292             dest_scan[3] = 255;
3293             dest_scan += 4;
3294             continue;
3295         }
3296         int src_alpha = clip_scan[col];
3297         if (src_alpha == 0) {
3298             dest_scan += 4;
3299             continue;
3300         }
3301         int back_alpha = dest_scan[3];
3302         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
3303         dest_scan[3] = dest_alpha;
3304         int alpha_ratio = src_alpha * 255 / dest_alpha;
3305         dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], FX_GAMMA(src_b), alpha_ratio);
3306         dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], FX_GAMMA(src_g), alpha_ratio);
3307         dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], FX_GAMMA(src_r), alpha_ratio);
3308         dest_scan += 4;
3309     }
3310 }
3311 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,
3312         int blend_type, FX_LPCBYTE clip_scan)
3313 {
3314     for (int col = 0; col < pixel_count; col ++) {
3315         int src_alpha;
3316         if (clip_scan) {
3317             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
3318         } else {
3319             src_alpha = mask_alpha * src_scan[col] / 255;
3320         }
3321         FX_BYTE back_alpha = dest_scan[3];
3322         if (back_alpha == 0) {
3323             FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
3324             dest_scan += 4;
3325             continue;
3326         }
3327         if (src_alpha == 0) {
3328             dest_scan += 4;
3329             continue;
3330         }
3331         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
3332         dest_scan[3] = dest_alpha;
3333         int alpha_ratio = src_alpha * 255 / dest_alpha;
3334         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
3335             int blended_colors[3];
3336             FX_BYTE src_scan[3];
3337             FX_BYTE dest_scan_o[3];
3338             src_scan[0] = src_b;
3339             src_scan[1] = src_g;
3340             src_scan[2] = src_r;
3341             dest_scan_o[0] = dest_scan[2];
3342             dest_scan_o[1] = dest_scan[1];
3343             dest_scan_o[2] = dest_scan[0];
3344             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
3345             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
3346             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
3347             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
3348         } else if (blend_type) {
3349             int blended = _BLEND(blend_type, dest_scan[2], src_b);
3350             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
3351             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
3352             blended = _BLEND(blend_type, dest_scan[1], src_g);
3353             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
3354             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
3355             blended = _BLEND(blend_type, dest_scan[0], src_r);
3356             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
3357             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
3358         } else {
3359             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
3360             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
3361             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
3362         }
3363         dest_scan += 4;
3364     }
3365 }
3366 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,
3367         int blend_type, int Bpp, FX_LPCBYTE clip_scan)
3368 {
3369     for (int col = 0; col < pixel_count; col ++) {
3370         int src_alpha;
3371         if (clip_scan) {
3372             src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
3373         } else {
3374             src_alpha = mask_alpha * src_scan[col] / 255;
3375         }
3376         if (src_alpha == 0) {
3377             dest_scan += Bpp;
3378             continue;
3379         }
3380         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
3381             int blended_colors[3];
3382             FX_BYTE src_scan[3];
3383             FX_BYTE dest_scan_o[3];
3384             src_scan[0] = src_b;
3385             src_scan[1] = src_g;
3386             src_scan[2] = src_r;
3387             dest_scan_o[0] = dest_scan[2];
3388             dest_scan_o[1] = dest_scan[1];
3389             dest_scan_o[2] = dest_scan[0];
3390             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
3391             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
3392             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
3393             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
3394         } else if (blend_type) {
3395             int blended = _BLEND(blend_type, dest_scan[2], src_b);
3396             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha);
3397             blended = _BLEND(blend_type, dest_scan[1], src_g);
3398             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha);
3399             blended = _BLEND(blend_type, dest_scan[0], src_r);
3400             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha);
3401         } else {
3402             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha);
3403             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha);
3404             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha);
3405         }
3406         dest_scan += Bpp;
3407     }
3408 }
3409 void _CompositeRow_BitMask2Argb_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b,
3410         int src_left, int pixel_count, int blend_type, FX_LPCBYTE clip_scan)
3411 {
3412     if (blend_type == FXDIB_BLEND_NORMAL && clip_scan == NULL && mask_alpha == 255) {
3413         FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b);
3414         for (int col = 0; col < pixel_count; col ++) {
3415             if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
3416                 FXARGB_SETRGBORDERDIB(dest_scan, argb);
3417             }
3418             dest_scan += 4;
3419         }
3420         return;
3421     }
3422     for (int col = 0; col < pixel_count; col ++) {
3423         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
3424             dest_scan += 4;
3425             continue;
3426         }
3427         int src_alpha;
3428         if (clip_scan) {
3429             src_alpha = mask_alpha * clip_scan[col] / 255;
3430         } else {
3431             src_alpha = mask_alpha;
3432         }
3433         FX_BYTE back_alpha = dest_scan[3];
3434         if (back_alpha == 0) {
3435             FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
3436             dest_scan += 4;
3437             continue;
3438         }
3439         FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
3440         dest_scan[3] = dest_alpha;
3441         int alpha_ratio = src_alpha * 255 / dest_alpha;
3442         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
3443             int blended_colors[3];
3444             FX_BYTE src_scan[3];
3445             FX_BYTE dest_scan_o[3];
3446             src_scan[0] = src_b;
3447             src_scan[1] = src_g;
3448             src_scan[2] = src_r;
3449             dest_scan_o[0] = dest_scan[2];
3450             dest_scan_o[1] = dest_scan[1];
3451             dest_scan_o[2] = dest_scan[0];
3452             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
3453             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
3454             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
3455             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
3456         } else if (blend_type) {
3457             int blended = _BLEND(blend_type, dest_scan[2], src_b);
3458             blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
3459             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
3460             blended = _BLEND(blend_type, dest_scan[1], src_g);
3461             blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
3462             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
3463             blended = _BLEND(blend_type, dest_scan[0], src_r);
3464             blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
3465             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
3466         } else {
3467             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
3468             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
3469             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
3470         }
3471         dest_scan += 4;
3472     }
3473 }
3474 void _CompositeRow_BitMask2Rgb_RgbByteOrder(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int mask_alpha, int src_r, int src_g, int src_b,
3475         int src_left, int pixel_count, int blend_type, int Bpp, FX_LPCBYTE clip_scan)
3476 {
3477     if (blend_type == FXDIB_BLEND_NORMAL && clip_scan == NULL && mask_alpha == 255) {
3478         for (int col = 0; col < pixel_count; col ++) {
3479             if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
3480                 dest_scan[2] = src_b;
3481                 dest_scan[1] = src_g;
3482                 dest_scan[0] = src_r;
3483             }
3484             dest_scan += Bpp;
3485         }
3486         return;
3487     }
3488     for (int col = 0; col < pixel_count; col ++) {
3489         if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
3490             dest_scan += Bpp;
3491             continue;
3492         }
3493         int src_alpha;
3494         if (clip_scan) {
3495             src_alpha = mask_alpha * clip_scan[col] / 255;
3496         } else {
3497             src_alpha = mask_alpha;
3498         }
3499         if (src_alpha == 0) {
3500             dest_scan += Bpp;
3501             continue;
3502         }
3503         if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
3504             int blended_colors[3];
3505             FX_BYTE src_scan[3];
3506             FX_BYTE dest_scan_o[3];
3507             src_scan[0] = src_b;
3508             src_scan[1] = src_g;
3509             src_scan[2] = src_r;
3510             dest_scan_o[0] = dest_scan[2];
3511             dest_scan_o[1] = dest_scan[1];
3512             dest_scan_o[2] = dest_scan[0];
3513             _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
3514             dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
3515             dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
3516             dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
3517         } else if (blend_type) {
3518             int back_color = FX_GAMMA(dest_scan[2]);
3519             int blended = _BLEND(blend_type, back_color, src_b);
3520             dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
3521             back_color = FX_GAMMA(dest_scan[1]);
3522             blended = _BLEND(blend_type, back_color, src_g);
3523             dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
3524             back_color = FX_GAMMA(dest_scan[0]);
3525             blended = _BLEND(blend_type, back_color, src_r);
3526             dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
3527         } else {
3528             dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), src_b, src_alpha));
3529             dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), src_g, src_alpha));
3530             dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), src_r, src_alpha));
3531         }
3532         dest_scan += Bpp;
3533     }
3534 }
3535 inline FX_BOOL _ScanlineCompositor_InitSourceMask(FXDIB_Format dest_format, int alpha_flag, FX_DWORD mask_color, int& mask_alpha,
3536         int& mask_red, int& mask_green, int& mask_blue, int& mask_black,
3537         void* icc_module, void* pIccTransform)
3538 {
3539     ICodec_IccModule* pIccModule = (ICodec_IccModule*)icc_module;
3540     if (alpha_flag >> 8) {
3541         mask_alpha = alpha_flag & 0xff;
3542         mask_red = FXSYS_GetCValue(mask_color);
3543         mask_green = FXSYS_GetMValue(mask_color);
3544         mask_blue = FXSYS_GetYValue(mask_color);
3545         mask_black = FXSYS_GetKValue(mask_color);
3546     } else {
3547         mask_alpha = FXARGB_A(mask_color);
3548         mask_red = FXARGB_R(mask_color);
3549         mask_green = FXARGB_G(mask_color);
3550         mask_blue = FXARGB_B(mask_color);
3551     }
3552     if (dest_format == FXDIB_8bppMask) {
3553         return TRUE;
3554     }
3555     if ((dest_format & 0xff) == 8) {
3556         if (pIccTransform) {
3557             mask_color = (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color);
3558             FX_LPBYTE gray_p = (FX_LPBYTE)&mask_color;
3559             pIccModule->TranslateScanline(pIccTransform, gray_p, gray_p, 1);
3560             mask_red = dest_format & 0x0400 ? FX_CCOLOR(gray_p[0]) : gray_p[0];
3561         } else {
3562             if (alpha_flag >> 8) {
3563                 FX_BYTE r, g, b;
3564                 AdobeCMYK_to_sRGB1(mask_red, mask_green, mask_blue, mask_black,
3565                                    r, g, b);
3566                 mask_red = FXRGB2GRAY(r, g, b);
3567             } else {
3568                 mask_red = FXRGB2GRAY(mask_red, mask_green, mask_blue);
3569             }
3570             if (dest_format & 0x0400) {
3571                 mask_red = FX_CCOLOR(mask_red);
3572             }
3573         }
3574     } else {
3575         FX_LPBYTE mask_color_p = (FX_LPBYTE)&mask_color;
3576         mask_color = (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color);
3577         if (pIccTransform) {
3578             pIccModule->TranslateScanline(pIccTransform, mask_color_p, mask_color_p, 1);
3579             mask_red = mask_color_p[2];
3580             mask_green = mask_color_p[1];
3581             mask_blue = mask_color_p[0];
3582         } else if (alpha_flag >> 8) {
3583             AdobeCMYK_to_sRGB1(mask_color_p[0], mask_color_p[1], mask_color_p[2], mask_color_p[3],
3584                                mask_color_p[2], mask_color_p[1], mask_color_p[0]);
3585             mask_red = mask_color_p[2];
3586             mask_green = mask_color_p[1];
3587             mask_blue = mask_color_p[0];
3588         }
3589     }
3590     return TRUE;
3591 }
3592 inline void _ScanlineCompositor_InitSourcePalette(FXDIB_Format src_format, FXDIB_Format dest_format,
3593         FX_DWORD*& pDestPalette, FX_DWORD* pSrcPalette,
3594         void* icc_module, void* pIccTransform)
3595 {
3596     ICodec_IccModule* pIccModule = (ICodec_IccModule*)icc_module;
3597     FX_BOOL isSrcCmyk = src_format & 0x0400 ? TRUE : FALSE;
3598     FX_BOOL isDstCmyk = dest_format & 0x0400 ? TRUE : FALSE;
3599     pDestPalette = NULL;
3600     if (pIccTransform) {
3601         if (pSrcPalette) {
3602             if ((dest_format & 0xff) == 8) {
3603                 int pal_count = 1 << (src_format & 0xff);
3604                 FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
3605                 if (!gray_pal) {
3606                     return;
3607                 }
3608                 pDestPalette = (FX_DWORD*)gray_pal;
3609                 for (int i = 0; i < pal_count; i ++) {
3610                     FX_DWORD color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) : FXARGB_TODIB(pSrcPalette[i]);
3611                     pIccModule->TranslateScanline(pIccTransform, gray_pal, (FX_LPCBYTE)&color, 1);
3612                     gray_pal ++;
3613                 }
3614             } else {
3615                 int palsize = 1 << (src_format & 0xff);
3616                 pDestPalette = FX_Alloc(FX_DWORD, palsize);
3617                 if (!pDestPalette) {
3618                     return;
3619                 }
3620                 for (int i = 0; i < palsize; i ++) {
3621                     FX_DWORD color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i]) : FXARGB_TODIB(pSrcPalette[i]);
3622                     pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&color, (FX_LPCBYTE)&color, 1);
3623                     pDestPalette[i] = isDstCmyk ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
3624                 }
3625             }
3626         } else {
3627             int pal_count = 1 << (src_format & 0xff);
3628             FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
3629             if (!gray_pal) {
3630                 return;
3631             }
3632             if (pal_count == 2) {
3633                 gray_pal[0] = 0;
3634                 gray_pal[1] = 255;
3635             } else {
3636                 for (int i = 0; i < pal_count; i++) {
3637                     gray_pal[i] = i;
3638                 }
3639             }
3640             if ((dest_format & 0xff) == 8) {
3641                 pIccModule->TranslateScanline(pIccTransform, gray_pal, gray_pal, pal_count);
3642                 pDestPalette = (FX_DWORD*)gray_pal;
3643             } else {
3644                 pDestPalette = FX_Alloc(FX_DWORD, pal_count);
3645                 if (!pDestPalette) {
3646                     FX_Free(gray_pal);
3647                     return;
3648                 }
3649                 for (int i = 0; i < pal_count; i ++) {
3650                     pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&pDestPalette[i], &gray_pal[i], 1);
3651                     pDestPalette[i] = isDstCmyk ? FXCMYK_TODIB(pDestPalette[i]) : FXARGB_TODIB(pDestPalette[i]);
3652                 }
3653                 FX_Free(gray_pal);
3654             }
3655         }
3656     } else {
3657         if (pSrcPalette) {
3658             if ((dest_format & 0xff) == 8) {
3659                 int pal_count = 1 << (src_format & 0xff);
3660                 FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
3661                 if (!gray_pal) {
3662                     return;
3663                 }
3664                 pDestPalette = (FX_DWORD*)gray_pal;
3665                 if (isSrcCmyk) {
3666                     for (int i = 0; i < pal_count; i ++) {
3667                         FX_CMYK cmyk = pSrcPalette[i];
3668                         FX_BYTE r, g, b;
3669                         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
3670                                            r, g, b);
3671                         *gray_pal ++ = FXRGB2GRAY(r, g, b);
3672                     }
3673                 } else
3674                     for (int i = 0; i < pal_count; i ++) {
3675                         FX_ARGB argb = pSrcPalette[i];
3676                         *gray_pal ++ = FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
3677                     }
3678             } else {
3679                 int palsize = 1 << (src_format & 0xff);
3680                 pDestPalette = FX_Alloc(FX_DWORD, palsize);
3681                 if (!pDestPalette) {
3682                     return;
3683                 }
3684                 if (isDstCmyk == isSrcCmyk) {
3685                     FXSYS_memcpy32(pDestPalette, pSrcPalette, palsize * sizeof(FX_DWORD));
3686                 } else {
3687                     for (int i = 0; i < palsize; i ++) {
3688                         FX_CMYK cmyk = pSrcPalette[i];
3689                         FX_BYTE r, g, b;
3690                         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
3691                                            r, g, b);
3692                         pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b);
3693                     }
3694                 }
3695             }
3696         } else {
3697             if ((dest_format & 0xff) == 8) {
3698                 int pal_count = 1 << (src_format & 0xff);
3699                 FX_LPBYTE gray_pal = FX_Alloc(FX_BYTE, pal_count);
3700                 if (!gray_pal) {
3701                     return;
3702                 }
3703                 if (pal_count == 2) {
3704                     gray_pal[0] = 0;
3705                     gray_pal[1] = 255;
3706                 } else {
3707                     for (int i = 0; i < pal_count; i++) {
3708                         gray_pal[i] = i;
3709                     }
3710                 }
3711                 pDestPalette = (FX_DWORD*)gray_pal;
3712             } else {
3713                 int palsize = 1 << (src_format & 0xff);
3714                 pDestPalette = FX_Alloc(FX_DWORD, palsize);
3715                 if (!pDestPalette) {
3716                     return;
3717                 }
3718                 if (palsize == 2) {
3719                     pDestPalette[0] = isSrcCmyk ? 255 : 0xff000000;
3720                     pDestPalette[1] = isSrcCmyk ? 0 : 0xffffffff;
3721                 } else {
3722                     for (int i = 0; i < palsize; i++) {
3723                         pDestPalette[i] = isSrcCmyk ? FX_CCOLOR(i) : (i * 0x10101);
3724                     }
3725                 }
3726                 if (isSrcCmyk != isDstCmyk) {
3727                     for (int i = 0; i < palsize; i ++) {
3728                         FX_CMYK cmyk = pDestPalette[i];
3729                         FX_BYTE r, g, b;
3730                         AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
3731                                            r, g, b);
3732                         pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b);
3733                     }
3734                 }
3735             }
3736         }
3737     }
3738 }
3739 CFX_ScanlineCompositor::CFX_ScanlineCompositor()
3740 {
3741     m_pSrcPalette = NULL;
3742     m_pCacheScanline = NULL;
3743     m_CacheSize = 0;
3744     m_bRgbByteOrder = FALSE;
3745     m_BlendType = FXDIB_BLEND_NORMAL;
3746 }
3747 CFX_ScanlineCompositor::~CFX_ScanlineCompositor()
3748 {
3749     if (m_pSrcPalette) {
3750         FX_Free(m_pSrcPalette);
3751     }
3752     if (m_pCacheScanline) {
3753         FX_Free(m_pCacheScanline);
3754     }
3755 }
3756 FX_BOOL CFX_ScanlineCompositor::Init(FXDIB_Format dest_format, FXDIB_Format src_format, FX_INT32 width, FX_DWORD* pSrcPalette,
3757                                      FX_DWORD mask_color, int blend_type, FX_BOOL bClip, FX_BOOL bRgbByteOrder, int alpha_flag, void* pIccTransform)
3758 {
3759     m_SrcFormat = src_format;
3760     m_DestFormat = dest_format;
3761     m_BlendType = blend_type;
3762     m_bRgbByteOrder = bRgbByteOrder;
3763     ICodec_IccModule* pIccModule = NULL;
3764     if (CFX_GEModule::Get()->GetCodecModule()) {
3765         pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
3766     }
3767     if (pIccModule == NULL) {
3768         pIccTransform = NULL;
3769     }
3770     m_pIccTransform = pIccTransform;
3771     if ((dest_format & 0xff) == 1) {
3772         return FALSE;
3773     }
3774     if (m_SrcFormat == FXDIB_1bppMask || m_SrcFormat == FXDIB_8bppMask) {
3775         return _ScanlineCompositor_InitSourceMask(dest_format, alpha_flag, mask_color,
3776                 m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue, m_MaskBlack,
3777                 pIccModule, pIccTransform);
3778     }
3779     if (pIccTransform == NULL && (~src_format & 0x0400) && (dest_format & 0x0400)) {
3780         return FALSE;
3781     }
3782     if ((m_SrcFormat & 0xff) <= 8) {
3783         if (dest_format == FXDIB_8bppMask) {
3784             return TRUE;
3785         }
3786         _ScanlineCompositor_InitSourcePalette(src_format, dest_format, m_pSrcPalette, pSrcPalette,
3787                                               pIccModule, pIccTransform);
3788         m_Transparency = (dest_format == FXDIB_Argb ? 1 : 0)
3789                          + (dest_format & 0x0200 ? 2 : 0)
3790                          + (dest_format & 0x0400 ? 4 : 0)
3791                          + ((src_format & 0xff) == 1 ? 8 : 0);
3792         return TRUE;
3793     }
3794     m_Transparency = (src_format & 0x0200 ? 0 : 1)
3795                      + (dest_format & 0x0200 ? 0 : 2)
3796                      + (blend_type == FXDIB_BLEND_NORMAL ? 4 : 0)
3797                      + (bClip ? 8 : 0)
3798                      + (src_format & 0x0400 ? 16 : 0)
3799                      + (dest_format & 0x0400 ? 32 : 0)
3800                      + (pIccTransform ? 64 : 0);
3801     return TRUE;
3802 }
3803 void CFX_ScanlineCompositor::CompositeRgbBitmapLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, FX_LPCBYTE clip_scan,
3804         FX_LPCBYTE src_extra_alpha, FX_LPBYTE dst_extra_alpha)
3805 {
3806     int src_Bpp = (m_SrcFormat & 0xff) >> 3;
3807     int dest_Bpp = (m_DestFormat & 0xff) >> 3;
3808     if (m_bRgbByteOrder) {
3809         switch (m_Transparency) {
3810             case 0:
3811             case 4:
3812             case 8:
3813             case 12:
3814                 _CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, clip_scan);
3815                 break;
3816             case 1:
3817                 _CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, src_Bpp);
3818                 break;
3819             case 2:
3820             case 10:
3821                 _CompositeRow_Argb2Rgb_Blend_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan);
3822                 break;
3823             case 3:
3824                 _CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp);
3825                 break;
3826             case 5:
3827                 _CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, width, src_Bpp);
3828                 break;
3829             case 6:
3830             case 14:
3831                 _CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, dest_Bpp, clip_scan);
3832                 break;
3833             case 7:
3834                 _CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan, width, dest_Bpp, src_Bpp);
3835                 break;
3836             case 9:
3837                 _CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan);
3838                 break;
3839             case 11:
3840                 _CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, clip_scan);
3841                 break;
3842             case 13:
3843                 _CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(dest_scan, src_scan, width, src_Bpp, clip_scan);
3844                 break;
3845             case 15:
3846                 _CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan);
3847                 break;
3848         }
3849         return;
3850     }
3851     if (m_DestFormat == FXDIB_8bppMask) {
3852         if (m_SrcFormat & 0x0200) {
3853             if (m_SrcFormat == FXDIB_Argb) {
3854                 _CompositeRow_Argb2Mask(dest_scan, src_scan, width, clip_scan);
3855             } else {
3856                 _CompositeRow_Rgba2Mask(dest_scan, src_extra_alpha, width, clip_scan);
3857             }
3858         } else {
3859             _CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
3860         }
3861     } else if ((m_DestFormat & 0xff) == 8) {
3862         if (m_DestFormat & 0x0400) {
3863             for (int i = 0; i < width; i ++) {
3864                 *dest_scan = ~*dest_scan;
3865                 dest_scan++;
3866             }
3867         }
3868         if (m_SrcFormat & 0x0200) {
3869             if (m_DestFormat & 0x0200) {
3870                 _CompositeRow_Argb2Graya(dest_scan, src_scan, width, m_BlendType, clip_scan, src_extra_alpha, dst_extra_alpha, m_pIccTransform);
3871             } else {
3872                 _CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType, clip_scan, src_extra_alpha, m_pIccTransform);
3873             }
3874         } else {
3875             if (m_DestFormat & 0x0200) {
3876                 _CompositeRow_Rgb2Graya(dest_scan, src_scan, src_Bpp, width, m_BlendType, clip_scan, dst_extra_alpha, m_pIccTransform);
3877             } else {
3878                 _CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType, clip_scan, m_pIccTransform);
3879             }
3880         }
3881         if (m_DestFormat & 0x0400) {
3882             for (int i = 0; i < width; i ++) {
3883                 *dest_scan = ~*dest_scan;
3884                 dest_scan++;
3885             }
3886         }
3887     } else {
3888         int dest_Size = width * dest_Bpp + 4;
3889         if (dest_Size > m_CacheSize) {
3890             m_pCacheScanline = FX_Realloc(FX_BYTE, m_pCacheScanline, dest_Size);
3891             if (!m_pCacheScanline) {
3892                 return;
3893             }
3894             m_CacheSize = dest_Size;
3895         }
3896         switch (m_Transparency) {
3897             case 0:
3898             case 4:
3899             case 8:
3900             case 4+8: {
3901                     _CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType, clip_scan,
3902                                             dst_extra_alpha, src_extra_alpha);
3903                 }
3904                 break;
3905             case 64:
3906             case 4+64:
3907             case 8+64:
3908             case 4+8+64: {
3909                     _CompositeRow_Argb2Argb_Transform(dest_scan, src_scan, width, m_BlendType, clip_scan,
3910                                                       dst_extra_alpha, src_extra_alpha, m_pCacheScanline, m_pIccTransform);
3911                 }
3912                 break;
3913             case 1:
3914                 _CompositeRow_Rgb2Argb_Blend_NoClip(dest_scan, src_scan, width, m_BlendType, src_Bpp,
3915                                                     dst_extra_alpha);
3916                 break;
3917             case 1+64:
3918                 _CompositeRow_Rgb2Argb_Blend_NoClip_Transform(dest_scan, src_scan, width, m_BlendType, src_Bpp,
3919                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
3920                 break;
3921             case 1+8:
3922                 _CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan,
3923                                                   dst_extra_alpha);
3924                 break;
3925             case 1+8+64:
3926                 _CompositeRow_Rgb2Argb_Blend_Clip_Transform(dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan,
3927                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
3928                 break;
3929             case 1+4:
3930                 _CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width, src_Bpp,
3931                                                       dst_extra_alpha);
3932                 break;
3933             case 1+4+64:
3934                 _CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform(dest_scan, src_scan, width, src_Bpp,
3935                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
3936                 break;
3937             case 1+4+8:
3938                 _CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp, clip_scan,
3939                                                     dst_extra_alpha);
3940                 break;
3941             case 1+4+8+64:
3942                 _CompositeRow_Rgb2Argb_NoBlend_Clip_Transform(dest_scan, src_scan, width, src_Bpp, clip_scan,
3943                         dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
3944                 break;
3945             case 2:
3946             case 2+8:
3947                 _CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan,
3948                                              src_extra_alpha);
3949                 break;
3950             case 2+64:
3951             case 2+8+64:
3952                 _CompositeRow_Argb2Rgb_Blend_Transform(dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan,
3953                                                        src_extra_alpha, m_pCacheScanline, m_pIccTransform);
3954                 break;
3955             case 2+4:
3956             case 2+4+8:
3957                 _CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp, clip_scan,
3958                                                src_extra_alpha);
3959                 break;
3960             case 2+4+64:
3961             case 2+4+8+64:
3962                 _CompositeRow_Argb2Rgb_NoBlend_Transform(dest_scan, src_scan, width, dest_Bpp, clip_scan,
3963                         src_extra_alpha, m_pCacheScanline, m_pIccTransform);
3964                 break;
3965             case 1+2:
3966                 _CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp);
3967                 break;
3968             case 1+2+64:
3969                 _CompositeRow_Rgb2Rgb_Blend_NoClip_Transform(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp,
3970                         m_pCacheScanline, m_pIccTransform);
3971                 break;
3972             case 1+2+8:
3973                 _CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, clip_scan);
3974                 break;
3975             case 1+2+8+64:
3976                 _CompositeRow_Rgb2Rgb_Blend_Clip_Transform(dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp, clip_scan,
3977                         m_pCacheScanline, m_pIccTransform);
3978                 break;
3979             case 1+2+4:
3980                 _CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width, dest_Bpp, src_Bpp);
3981                 break;
3982             case 1+2+4+64:
3983                 _CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform(dest_scan, src_scan, width, dest_Bpp, src_Bpp,
3984                         m_pCacheScanline, m_pIccTransform);
3985                 break;
3986             case 1+2+4+8:
3987                 _CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan);
3988                 break;
3989             case 1+2+4+8+64:
3990                 _CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform(dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan,
3991                         m_pCacheScanline, m_pIccTransform);
3992                 break;
3993         }
3994     }
3995 }
3996 void CFX_ScanlineCompositor::CompositePalBitmapLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width, FX_LPCBYTE clip_scan,
3997         FX_LPCBYTE src_extra_alpha, FX_LPBYTE dst_extra_alpha)
3998 {
3999     if (m_bRgbByteOrder) {
4000         if (m_SrcFormat == FXDIB_1bppRgb) {
4001             if (m_DestFormat == FXDIB_8bppRgb) {
4002                 return;
4003             } else if(m_DestFormat == FXDIB_Argb) {
4004                 _CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan);
4005             } else {
4006                 _CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, src_left, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan);
4007             }
4008         } else {
4009             if (m_DestFormat == FXDIB_8bppRgb) {
4010                 return;
4011             } else if (m_DestFormat == FXDIB_Argb) {
4012                 _CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(dest_scan, src_scan, width, m_pSrcPalette, clip_scan);
4013             } else {
4014                 _CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan);
4015             }
4016         }
4017         return;
4018     }
4019     if (m_DestFormat == FXDIB_8bppMask) {
4020         _CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
4021         return;
4022     } else if ((m_DestFormat & 0xff) == 8) {
4023         if (m_Transparency & 8) {
4024             if (m_DestFormat & 0x0200) {
4025                 _CompositeRow_1bppPal2Graya(dest_scan, src_scan, src_left, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan, dst_extra_alpha);
4026             } else {
4027                 _CompositeRow_1bppPal2Gray(dest_scan, src_scan, src_left, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan);
4028             }
4029         } else {
4030             if (m_DestFormat & 0x0200)
4031                 _CompositeRow_8bppPal2Graya(dest_scan, src_scan, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan,
4032                                             dst_extra_alpha, src_extra_alpha);
4033             else
4034                 _CompositeRow_8bppPal2Gray(dest_scan, src_scan, (FX_LPCBYTE)m_pSrcPalette, width, m_BlendType, clip_scan,
4035                                            src_extra_alpha);
4036         }
4037     } else {
4038         switch (m_Transparency) {
4039             case 1+2:
4040                 _CompositeRow_8bppRgb2Argb_NoBlend(dest_scan, src_scan, width, m_pSrcPalette, clip_scan,
4041                                                    src_extra_alpha);
4042                 break;
4043             case 1+2+8:
4044                 _CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan);
4045                 break;
4046             case 0:
4047                 _CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan,
4048                                                   src_extra_alpha);
4049                 break;
4050             case 0+8:
4051                 _CompositeRow_1bppRgb2Rgb_NoBlend(dest_scan, src_scan, src_left, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan);
4052                 break;
4053             case 0+2:
4054                 _CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette, width, (m_DestFormat & 0xff) >> 3, clip_scan,
4055                                                   src_extra_alpha);
4056                 break;
4057             case 0+2+8:
4058                 _CompositeRow_1bppRgb2Rgba_NoBlend(dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan,
4059                                                    dst_extra_alpha);
4060                 break;
4061                 break;
4062         }
4063     }
4064 }
4065 void CFX_ScanlineCompositor::CompositeByteMaskLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int width, FX_LPCBYTE clip_scan,
4066         FX_LPBYTE dst_extra_alpha)
4067 {
4068     if (m_DestFormat == FXDIB_8bppMask) {
4069         _CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width, clip_scan);
4070     } else if ((m_DestFormat & 0xff) == 8) {
4071         if (m_DestFormat & 0x0200) {
4072             _CompositeRow_ByteMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, width, clip_scan, dst_extra_alpha);
4073         } else {
4074             _CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, width, clip_scan);
4075         }
4076     } else if (m_bRgbByteOrder) {
4077         if (m_DestFormat == FXDIB_Argb)
4078             _CompositeRow_ByteMask2Argb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
4079                     width, m_BlendType, clip_scan);
4080         else
4081             _CompositeRow_ByteMask2Rgb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
4082                                                     width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
4083         return;
4084     } else if (m_DestFormat == FXDIB_Argb)
4085         _CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
4086                                     width, m_BlendType, clip_scan);
4087     else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32)
4088         _CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
4089                                    width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
4090     else if (m_DestFormat == FXDIB_Rgba)
4091         _CompositeRow_ByteMask2Rgba(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
4092                                     width, m_BlendType, clip_scan, dst_extra_alpha);
4093 }
4094 void CFX_ScanlineCompositor::CompositeBitMaskLine(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int src_left, int width, FX_LPCBYTE clip_scan,
4095         FX_LPBYTE dst_extra_alpha)
4096 {
4097     if (m_DestFormat == FXDIB_8bppMask) {
4098         _CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left, width, clip_scan);
4099     } else if ((m_DestFormat & 0xff) == 8) {
4100         if (m_DestFormat & 0x0200)
4101             _CompositeRow_BitMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, src_left, width, clip_scan,
4102                                         dst_extra_alpha);
4103         else {
4104             _CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, src_left, width, clip_scan);
4105         }
4106     } else if (m_bRgbByteOrder) {
4107         if (m_DestFormat == FXDIB_Argb)
4108             _CompositeRow_BitMask2Argb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
4109                                                     src_left, width, m_BlendType, clip_scan);
4110         else
4111             _CompositeRow_BitMask2Rgb_RgbByteOrder(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
4112                                                    src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
4113         return;
4114     } else if (m_DestFormat == FXDIB_Argb)
4115         _CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
4116                                    src_left, width, m_BlendType, clip_scan);
4117     else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32)
4118         _CompositeRow_BitMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
4119                                   src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
4120 }
4121 FX_BOOL CFX_DIBitmap::CompositeBitmap(int dest_left, int dest_top, int width, int height,
4122                                       const CFX_DIBSource* pSrcBitmap, int src_left, int src_top,
4123                                       int blend_type, const CFX_ClipRgn* pClipRgn, FX_BOOL bRgbByteOrder, void* pIccTransform)
4124 {
4125     if (m_pBuffer == NULL) {
4126         return FALSE;
4127     }
4128     ASSERT(!pSrcBitmap->IsAlphaMask());
4129     ASSERT(m_bpp >= 8);
4130     if (pSrcBitmap->IsAlphaMask() || m_bpp < 8) {
4131         return FALSE;
4132     }
4133     GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(),
4134                    src_left, src_top, pClipRgn);
4135     if (width == 0 || height == 0) {
4136         return TRUE;
4137     }
4138     const CFX_DIBitmap* pClipMask = NULL;
4139     FX_RECT clip_box;
4140     if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
4141         ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF);
4142         pClipMask = pClipRgn->GetMask();
4143         clip_box = pClipRgn->GetBox();
4144     }
4145     CFX_ScanlineCompositor compositor;
4146     if (!compositor.Init(GetFormat(), pSrcBitmap->GetFormat(), width, pSrcBitmap->GetPalette(), 0, blend_type,
4147                          pClipMask != NULL, bRgbByteOrder, 0, pIccTransform)) {
4148         return FALSE;
4149     }
4150     int dest_Bpp = m_bpp / 8;
4151     int src_Bpp = pSrcBitmap->GetBPP() / 8;
4152     FX_BOOL bRgb = FALSE;
4153     FX_BOOL bCmyk = FALSE;
4154     if (src_Bpp > 1) {
4155         if (pSrcBitmap->IsCmykImage()) {
4156             bCmyk = TRUE;
4157         } else {
4158             bRgb = TRUE;
4159         }
4160     }
4161     CFX_DIBitmap* pSrcAlphaMask = pSrcBitmap->m_pAlphaMask;
4162     for (int row = 0; row < height; row ++) {
4163         FX_LPBYTE dest_scan = m_pBuffer + (dest_top + row) * m_Pitch + dest_left * dest_Bpp;
4164         FX_LPCBYTE src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left * src_Bpp;
4165         FX_LPCBYTE src_scan_extra_alpha = pSrcAlphaMask ? pSrcAlphaMask->GetScanline(src_top + row) + src_left : NULL;
4166         FX_LPBYTE dst_scan_extra_alpha = m_pAlphaMask ? (FX_LPBYTE)m_pAlphaMask->GetScanline(dest_top + row) + dest_left : NULL;
4167         FX_LPCBYTE clip_scan = NULL;
4168         if (pClipMask) {
4169             clip_scan = pClipMask->m_pBuffer + (dest_top + row - clip_box.top) * pClipMask->m_Pitch + (dest_left - clip_box.left);
4170         }
4171         if (bRgb) {
4172             compositor.CompositeRgbBitmapLine(dest_scan, src_scan, width, clip_scan, src_scan_extra_alpha, dst_scan_extra_alpha);
4173         } else {
4174             compositor.CompositePalBitmapLine(dest_scan, src_scan, src_left, width, clip_scan, src_scan_extra_alpha, dst_scan_extra_alpha);
4175         }
4176     }
4177     return TRUE;
4178 }
4179 FX_BOOL CFX_DIBitmap::CompositeMask(int dest_left, int dest_top, int width, int height,
4180                                     const CFX_DIBSource* pMask, FX_DWORD color, int src_left, int src_top,
4181                                     int blend_type, const CFX_ClipRgn* pClipRgn, FX_BOOL bRgbByteOrder, int alpha_flag, void* pIccTransform)
4182 {
4183     if (m_pBuffer == NULL) {
4184         return FALSE;
4185     }
4186     ASSERT(pMask->IsAlphaMask());
4187     ASSERT(m_bpp >= 8);
4188     if (!pMask->IsAlphaMask() || m_bpp < 8) {
4189         return FALSE;
4190     }
4191     GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(), pMask->GetHeight(), src_left, src_top, pClipRgn);
4192     if (width == 0 || height == 0) {
4193         return TRUE;
4194     }
4195     int src_alpha = (FX_BYTE)(alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color);
4196     if (src_alpha == 0) {
4197         return TRUE;
4198     }
4199     const CFX_DIBitmap* pClipMask = NULL;
4200     FX_RECT clip_box;
4201     if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
4202         ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF);
4203         pClipMask = pClipRgn->GetMask();
4204         clip_box = pClipRgn->GetBox();
4205     }
4206     int src_bpp = pMask->GetBPP();
4207     int Bpp = GetBPP() / 8;
4208     CFX_ScanlineCompositor compositor;
4209     if (!compositor.Init(GetFormat(), pMask->GetFormat(), width, NULL, color, blend_type, pClipMask != NULL, bRgbByteOrder, alpha_flag, pIccTransform)) {
4210         return FALSE;
4211     }
4212     for (int row = 0; row < height; row ++) {
4213         FX_LPBYTE dest_scan = m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp;
4214         FX_LPCBYTE src_scan = pMask->GetScanline(src_top + row);
4215         FX_LPBYTE dst_scan_extra_alpha = m_pAlphaMask ? (FX_LPBYTE)m_pAlphaMask->GetScanline(dest_top + row) + dest_left : NULL;
4216         FX_LPCBYTE clip_scan = NULL;
4217         if (pClipMask) {
4218             clip_scan = pClipMask->m_pBuffer + (dest_top + row - clip_box.top) * pClipMask->m_Pitch + (dest_left - clip_box.left);
4219         }
4220         if (src_bpp == 1) {
4221             compositor.CompositeBitMaskLine(dest_scan, src_scan, src_left, width, clip_scan, dst_scan_extra_alpha);
4222         } else {
4223             compositor.CompositeByteMaskLine(dest_scan, src_scan + src_left, width, clip_scan, dst_scan_extra_alpha);
4224         }
4225     }
4226     return TRUE;
4227 }
4228 FX_BOOL CFX_DIBitmap::CompositeRect(int left, int top, int width, int height, FX_DWORD color, int alpha_flag, void* pIccTransform)
4229 {
4230     if (m_pBuffer == NULL) {
4231         return FALSE;
4232     }
4233     int src_alpha = (alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color);
4234     if (src_alpha == 0) {
4235         return TRUE;
4236     }
4237     FX_RECT rect(left, top, left + width, top + height);
4238     rect.Intersect(0, 0, m_Width, m_Height);
4239     if (rect.IsEmpty()) {
4240         return TRUE;
4241     }
4242     width = rect.Width();
4243     FX_DWORD dst_color;
4244     if (alpha_flag >> 8) {
4245         dst_color = FXCMYK_TODIB(color);
4246     } else {
4247         dst_color = FXARGB_TODIB(color);
4248     }
4249     FX_LPBYTE color_p = (FX_LPBYTE)&dst_color;
4250     if (m_bpp == 8) {
4251         FX_BYTE gray = 255;
4252         if (!IsAlphaMask()) {
4253             if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() && CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
4254                 ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
4255                 pIccModule->TranslateScanline(pIccTransform, &gray, color_p, 1);
4256             } else {
4257                 if (alpha_flag >> 8) {
4258                     FX_BYTE r, g, b;
4259                     AdobeCMYK_to_sRGB1(color_p[0], color_p[1], color_p[2], color_p[3],
4260                                        r, g, b);
4261                     gray = FXRGB2GRAY(r, g, b);
4262                 } else {
4263                     gray = (FX_BYTE)FXRGB2GRAY((int)color_p[2], color_p[1], color_p[0]);
4264                 }
4265             }
4266             if (IsCmykImage()) {
4267                 gray = ~gray;
4268             }
4269         }
4270         for (int row = rect.top; row < rect.bottom; row ++) {
4271             FX_LPBYTE dest_scan = m_pBuffer + row * m_Pitch + rect.left;
4272             if (src_alpha == 255) {
4273                 FXSYS_memset8(dest_scan, gray, width);
4274             } else
4275                 for (int col = 0; col < width; col ++) {
4276                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
4277                     dest_scan ++;
4278                 }
4279         }
4280         return TRUE;
4281     } else if (m_bpp == 1) {
4282         ASSERT(!IsCmykImage() && (FX_BYTE)(alpha_flag >> 8) == 0);
4283         int left_shift = rect.left % 8;
4284         int right_shift = rect.right % 8;
4285         int width = rect.right / 8 - rect.left / 8;
4286         int index = 0;
4287         if (m_pPalette == NULL) {
4288             index = ((FX_BYTE)color == 0xff) ? 1 : 0;
4289         } else {
4290             for (int i = 0; i < 2; i ++)
4291                 if (m_pPalette[i] == color) {
4292                     index = i;
4293                 }
4294         }
4295         for (int row = rect.top; row < rect.bottom; row ++) {
4296             FX_BYTE* dest_scan_top = (FX_BYTE*)GetScanline(row) + rect.left / 8;
4297             FX_BYTE* dest_scan_top_r = (FX_BYTE*)GetScanline(row) + rect.right / 8;
4298             FX_BYTE left_flag =  *dest_scan_top & (255 << (8 - left_shift));
4299             FX_BYTE right_flag = *dest_scan_top_r & (255 >> right_shift);
4300             if (width) {
4301                 FXSYS_memset8(dest_scan_top + 1, index ? 255 : 0, width - 1);
4302                 if (!index) {
4303                     *dest_scan_top &= left_flag;
4304                     *dest_scan_top_r &= right_flag;
4305                 } else {
4306                     *dest_scan_top |= ~left_flag;
4307                     *dest_scan_top_r |= ~right_flag;
4308                 }
4309             } else {
4310                 if (!index) {
4311                     *dest_scan_top &= left_flag | right_flag;
4312                 } else {
4313                     *dest_scan_top |= ~(left_flag | right_flag);
4314                 }
4315             }
4316         }
4317         return TRUE;
4318     }
4319     ASSERT(m_bpp >= 24);
4320     if (m_bpp < 24) {
4321         return FALSE;
4322     }
4323     if (pIccTransform && CFX_GEModule::Get()->GetCodecModule()) {
4324         ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
4325         pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1);
4326     } else {
4327         if (alpha_flag >> 8 && !IsCmykImage())
4328             AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), FXSYS_GetYValue(color), FXSYS_GetKValue(color),
4329                                color_p[2], color_p[1], color_p[0]);
4330         else if (!(alpha_flag >> 8) && IsCmykImage()) {
4331             return FALSE;
4332         }
4333     }
4334     if(!IsCmykImage()) {
4335         color_p[3] = (FX_BYTE)src_alpha;
4336     }
4337     int Bpp = m_bpp / 8;
4338     FX_BOOL bAlpha = HasAlpha();
4339     FX_BOOL bArgb = GetFormat() == FXDIB_Argb ? TRUE : FALSE;
4340     if (src_alpha == 255) {
4341         for (int row = rect.top; row < rect.bottom; row ++) {
4342             FX_LPBYTE dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp;
4343             FX_LPBYTE dest_scan_alpha = m_pAlphaMask ? (FX_LPBYTE)m_pAlphaMask->GetScanline(row) + rect.left : NULL;
4344             if (dest_scan_alpha) {
4345                 FXSYS_memset8(dest_scan_alpha, 0xff, width);
4346             }
4347             if (Bpp == 4) {
4348                 FX_DWORD* scan = (FX_DWORD*)dest_scan;
4349                 for (int col = 0; col < width; col ++) {
4350                     *scan ++ = dst_color;
4351                 }
4352             } else {
4353                 for (int col = 0; col < width; col ++) {
4354                     *dest_scan ++ = color_p[0];
4355                     *dest_scan ++ = color_p[1];
4356                     *dest_scan ++ = color_p[2];
4357                 }
4358             }
4359         }
4360         return TRUE;
4361     }
4362     for (int row = rect.top; row < rect.bottom; row ++) {
4363         FX_LPBYTE dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp;
4364         if (bAlpha) {
4365             if (bArgb) {
4366                 for (int col = 0; col < width; col ++) {
4367                     FX_BYTE back_alpha = dest_scan[3];
4368                     if (back_alpha == 0) {
4369                         FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, color_p[2], color_p[1], color_p[0]));
4370                         dest_scan += 4;
4371                         continue;
4372                     }
4373                     FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
4374                     int alpha_ratio = src_alpha * 255 / dest_alpha;
4375                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[0], alpha_ratio);
4376                     dest_scan ++;
4377                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[1], alpha_ratio);
4378                     dest_scan ++;
4379                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[2], alpha_ratio);
4380                     dest_scan ++;
4381                     *dest_scan++ = dest_alpha;
4382                 }
4383             } else {
4384                 FX_LPBYTE dest_scan_alpha = (FX_LPBYTE)m_pAlphaMask->GetScanline(row) + rect.left;
4385                 for (int col = 0; col < width; col ++) {
4386                     FX_BYTE back_alpha = *dest_scan_alpha;
4387                     if (back_alpha == 0) {
4388                         *dest_scan_alpha++ = src_alpha;
4389                         FXSYS_memcpy32(dest_scan, color_p, Bpp);
4390                         dest_scan += Bpp;
4391                         continue;
4392                     }
4393                     FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
4394                     *dest_scan_alpha ++ = dest_alpha;
4395                     int alpha_ratio = src_alpha * 255 / dest_alpha;
4396                     for(int comps = 0; comps < Bpp; comps ++) {
4397                         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], alpha_ratio);
4398                         dest_scan ++;
4399                     }
4400                 }
4401             }
4402         } else {
4403             for (int col = 0; col < width; col ++) {
4404                 for(int comps = 0; comps < Bpp; comps ++) {
4405                     if (comps == 3) {
4406                         *dest_scan ++ = 255;
4407                         continue;
4408                     }
4409                     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], src_alpha);
4410                     dest_scan ++;
4411                 }
4412             }
4413         }
4414     }
4415     return TRUE;
4416 }
4417 CFX_BitmapComposer::CFX_BitmapComposer()
4418 {
4419     m_pScanlineV = NULL;
4420     m_pScanlineAlphaV = NULL;
4421     m_pClipScanV = NULL;
4422     m_pAddClipScan = NULL;
4423     m_bRgbByteOrder = FALSE;
4424     m_BlendType = FXDIB_BLEND_NORMAL;
4425 }
4426 CFX_BitmapComposer::~CFX_BitmapComposer()
4427 {
4428     if (m_pScanlineV) {
4429         FX_Free(m_pScanlineV);
4430     }
4431     if (m_pScanlineAlphaV) {
4432         FX_Free(m_pScanlineAlphaV);
4433     }
4434     if (m_pClipScanV) {
4435         FX_Free(m_pClipScanV);
4436     }
4437     if (m_pAddClipScan) {
4438         FX_Free(m_pAddClipScan);
4439     }
4440 }
4441 void CFX_BitmapComposer::Compose(CFX_DIBitmap* pDest, const CFX_ClipRgn* pClipRgn, int bitmap_alpha,
4442                                  FX_DWORD mask_color, FX_RECT& dest_rect, FX_BOOL bVertical,
4443                                  FX_BOOL bFlipX, FX_BOOL bFlipY, FX_BOOL bRgbByteOrder,
4444                                  int alpha_flag, void* pIccTransform, int blend_type)
4445 {
4446     m_pBitmap = pDest;
4447     m_pClipRgn = pClipRgn;
4448     m_DestLeft = dest_rect.left;
4449     m_DestTop = dest_rect.top;
4450     m_DestWidth = dest_rect.Width();
4451     m_DestHeight = dest_rect.Height();
4452     m_BitmapAlpha = bitmap_alpha;
4453     m_MaskColor = mask_color;
4454     m_pClipMask = NULL;
4455     if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
4456         m_pClipMask = pClipRgn->GetMask();
4457     }
4458     m_bVertical = bVertical;
4459     m_bFlipX = bFlipX;
4460     m_bFlipY = bFlipY;
4461     m_AlphaFlag = alpha_flag;
4462     m_pIccTransform = pIccTransform;
4463     m_bRgbByteOrder = bRgbByteOrder;
4464     m_BlendType = blend_type;
4465 }
4466 FX_BOOL CFX_BitmapComposer::SetInfo(int width, int height, FXDIB_Format src_format, FX_DWORD* pSrcPalette)
4467 {
4468     m_SrcFormat = src_format;
4469     if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, pSrcPalette, m_MaskColor, FXDIB_BLEND_NORMAL,
4470                            m_pClipMask != NULL || (m_BitmapAlpha < 255), m_bRgbByteOrder, m_AlphaFlag, m_pIccTransform)) {
4471         return FALSE;
4472     }
4473     if (m_bVertical) {
4474         m_pScanlineV = FX_Alloc(FX_BYTE, m_pBitmap->GetBPP() / 8 * width + 4);
4475         if (!m_pScanlineV) {
4476             return FALSE;
4477         }
4478         m_pClipScanV = FX_Alloc(FX_BYTE, m_pBitmap->GetHeight());
4479         if (!m_pClipScanV) {
4480             return FALSE;
4481         }
4482         if (m_pBitmap->m_pAlphaMask) {
4483             m_pScanlineAlphaV = FX_Alloc(FX_BYTE, width + 4);
4484             if (!m_pScanlineAlphaV) {
4485                 return FALSE;
4486             }
4487         }
4488     }
4489     if (m_BitmapAlpha < 255) {
4490         m_pAddClipScan = FX_Alloc(FX_BYTE, m_bVertical ? m_pBitmap->GetHeight() : m_pBitmap->GetWidth());
4491         if (!m_pAddClipScan) {
4492             return FALSE;
4493         }
4494     }
4495     return TRUE;
4496 }
4497 void CFX_BitmapComposer::DoCompose(FX_LPBYTE dest_scan, FX_LPCBYTE src_scan, int dest_width, FX_LPCBYTE clip_scan,
4498                                    FX_LPCBYTE src_extra_alpha, FX_LPBYTE dst_extra_alpha)
4499 {
4500     if (m_BitmapAlpha < 255) {
4501         if (clip_scan) {
4502             for (int i = 0; i < dest_width; i ++) {
4503                 m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255;
4504             }
4505         } else {
4506             FXSYS_memset8(m_pAddClipScan, m_BitmapAlpha, dest_width);
4507         }
4508         clip_scan = m_pAddClipScan;
4509     }
4510     if (m_SrcFormat == FXDIB_8bppMask) {
4511         m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width, clip_scan, dst_extra_alpha);
4512     } else if ((m_SrcFormat & 0xff) == 8) {
4513         m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width, clip_scan, src_extra_alpha, dst_extra_alpha);
4514     } else {
4515         m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width, clip_scan, src_extra_alpha, dst_extra_alpha);
4516     }
4517 }
4518 void CFX_BitmapComposer::ComposeScanline(int line, FX_LPCBYTE scanline, FX_LPCBYTE scan_extra_alpha)
4519 {
4520     if (m_bVertical) {
4521         ComposeScanlineV(line, scanline, scan_extra_alpha);
4522         return;
4523     }
4524     FX_LPCBYTE clip_scan = NULL;
4525     if (m_pClipMask)
4526         clip_scan = m_pClipMask->GetBuffer() + (m_DestTop + line - m_pClipRgn->GetBox().top) *
4527                     m_pClipMask->GetPitch() + (m_DestLeft - m_pClipRgn->GetBox().left);
4528     FX_LPBYTE dest_scan = (FX_LPBYTE)m_pBitmap->GetScanline(line + m_DestTop) +
4529                           m_DestLeft * m_pBitmap->GetBPP() / 8;
4530     FX_LPBYTE dest_alpha_scan = m_pBitmap->m_pAlphaMask ?
4531                                 (FX_LPBYTE)m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop) + m_DestLeft : NULL;
4532     DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha, dest_alpha_scan);
4533 }
4534 void CFX_BitmapComposer::ComposeScanlineV(int line, FX_LPCBYTE scanline, FX_LPCBYTE scan_extra_alpha)
4535 {
4536     int i;
4537     int Bpp = m_pBitmap->GetBPP() / 8;
4538     int dest_pitch = m_pBitmap->GetPitch();
4539     int dest_alpha_pitch = m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetPitch() : 0;
4540     int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
4541     FX_LPBYTE dest_buf = m_pBitmap->GetBuffer() + dest_x * Bpp + m_DestTop * dest_pitch;
4542     FX_LPBYTE dest_alpha_buf = m_pBitmap->m_pAlphaMask ?
4543                                m_pBitmap->m_pAlphaMask->GetBuffer() + dest_x + m_DestTop * dest_alpha_pitch : NULL;
4544     if (m_bFlipY) {
4545         dest_buf += dest_pitch * (m_DestHeight - 1);
4546         dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1);
4547     }
4548     int y_step = dest_pitch;
4549     int y_alpha_step = dest_alpha_pitch;
4550     if (m_bFlipY) {
4551         y_step = -y_step;
4552         y_alpha_step = -y_alpha_step;
4553     }
4554     FX_LPBYTE src_scan = m_pScanlineV;
4555     FX_LPBYTE dest_scan = dest_buf;
4556     for (i = 0; i < m_DestHeight; i ++) {
4557         for (int j = 0; j < Bpp; j ++) {
4558             *src_scan++ = dest_scan[j];
4559         }
4560         dest_scan += y_step;
4561     }
4562     FX_LPBYTE src_alpha_scan = m_pScanlineAlphaV;
4563     FX_LPBYTE dest_alpha_scan = dest_alpha_buf;
4564     if (dest_alpha_scan) {
4565         for (i = 0; i < m_DestHeight; i ++) {
4566             *src_alpha_scan++ = *dest_alpha_scan;
4567             dest_alpha_scan += y_alpha_step;
4568         }
4569     }
4570     FX_LPBYTE clip_scan = NULL;
4571     if (m_pClipMask) {
4572         clip_scan = m_pClipScanV;
4573         int clip_pitch = m_pClipMask->GetPitch();
4574         FX_LPCBYTE src_clip = m_pClipMask->GetBuffer() + (m_DestTop - m_pClipRgn->GetBox().top) *
4575                               clip_pitch + (dest_x - m_pClipRgn->GetBox().left);
4576         if (m_bFlipY) {
4577             src_clip += clip_pitch * (m_DestHeight - 1);
4578             clip_pitch = -clip_pitch;
4579         }
4580         for (i = 0; i < m_DestHeight; i ++) {
4581             clip_scan[i] = *src_clip;
4582             src_clip += clip_pitch;
4583         }
4584     }
4585     DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan, scan_extra_alpha, m_pScanlineAlphaV);
4586     src_scan = m_pScanlineV;
4587     dest_scan = dest_buf;
4588     for (i = 0; i < m_DestHeight; i ++) {
4589         for (int j = 0; j < Bpp; j ++) {
4590             dest_scan[j] = *src_scan++;
4591         }
4592         dest_scan += y_step;
4593     }
4594     src_alpha_scan = m_pScanlineAlphaV;
4595     dest_alpha_scan = dest_alpha_buf;
4596     if (dest_alpha_scan) {
4597         for (i = 0; i < m_DestHeight; i ++) {
4598             *dest_alpha_scan = *src_alpha_scan++;
4599             dest_alpha_scan += y_alpha_step;
4600         }
4601     }
4602 }