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