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