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