xref: /aosp_15_r20/external/pdfium/core/fxge/dib/cfx_scanlinecompositor.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2017 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxge/dib/cfx_scanlinecompositor.h"
8 
9 #include <string.h>
10 
11 #include <algorithm>
12 
13 #include "core/fxge/dib/fx_dib.h"
14 #include "third_party/base/check.h"
15 #include "third_party/base/check_op.h"
16 
17 #define FXDIB_ALPHA_UNION(dest, src) ((dest) + (src) - (dest) * (src) / 255)
18 #define FXARGB_RGBORDERCOPY(dest, src)                  \
19   *((dest) + 3) = *((src) + 3), *(dest) = *((src) + 2), \
20              *((dest) + 1) = *((src) + 1), *((dest) + 2) = *((src))
21 
22 namespace {
23 
24 const uint8_t color_sqrt[256] = {
25     0x00, 0x03, 0x07, 0x0B, 0x0F, 0x12, 0x16, 0x19, 0x1D, 0x20, 0x23, 0x26,
26     0x29, 0x2C, 0x2F, 0x32, 0x35, 0x37, 0x3A, 0x3C, 0x3F, 0x41, 0x43, 0x46,
27     0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x57, 0x59, 0x5B, 0x5C,
28     0x5E, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D,
29     0x6E, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
30     0x7B, 0x7C, 0x7D, 0x7E, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
31     0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x91,
32     0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C,
33     0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5,
34     0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE,
35     0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7,
36     0xB7, 0xB8, 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBE, 0xBF,
37     0xC0, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7,
38     0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCE,
39     0xCF, 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6,
40     0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD,
41     0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE2, 0xE3, 0xE4,
42     0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA,
43     0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE, 0xEF, 0xF0, 0xF0, 0xF1,
44     0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7,
45     0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD,
46     0xFD, 0xFE, 0xFE, 0xFF};
47 
Blend(BlendMode blend_mode,int back_color,int src_color)48 int Blend(BlendMode blend_mode, int back_color, int src_color) {
49   switch (blend_mode) {
50     case BlendMode::kNormal:
51       return src_color;
52     case BlendMode::kMultiply:
53       return src_color * back_color / 255;
54     case BlendMode::kScreen:
55       return src_color + back_color - src_color * back_color / 255;
56     case BlendMode::kOverlay:
57       return Blend(BlendMode::kHardLight, src_color, back_color);
58     case BlendMode::kDarken:
59       return src_color < back_color ? src_color : back_color;
60     case BlendMode::kLighten:
61       return src_color > back_color ? src_color : back_color;
62     case BlendMode::kColorDodge: {
63       if (src_color == 255)
64         return src_color;
65 
66       return std::min(back_color * 255 / (255 - src_color), 255);
67     }
68     case BlendMode::kColorBurn: {
69       if (src_color == 0)
70         return src_color;
71 
72       return 255 - std::min((255 - back_color) * 255 / src_color, 255);
73     }
74     case BlendMode::kHardLight:
75       if (src_color < 128)
76         return (src_color * back_color * 2) / 255;
77 
78       return Blend(BlendMode::kScreen, back_color, 2 * src_color - 255);
79     case BlendMode::kSoftLight: {
80       if (src_color < 128) {
81         return back_color - (255 - 2 * src_color) * back_color *
82                                 (255 - back_color) / 255 / 255;
83       }
84       return back_color + (2 * src_color - 255) *
85                               (color_sqrt[back_color] - back_color) / 255;
86     }
87     case BlendMode::kDifference:
88       return back_color < src_color ? src_color - back_color
89                                     : back_color - src_color;
90     case BlendMode::kExclusion:
91       return back_color + src_color - 2 * back_color * src_color / 255;
92     default:
93       return src_color;
94   }
95 }
96 
97 struct RGB {
98   int red;
99   int green;
100   int blue;
101 };
102 
Lum(RGB color)103 int Lum(RGB color) {
104   return (color.red * 30 + color.green * 59 + color.blue * 11) / 100;
105 }
106 
ClipColor(RGB color)107 RGB ClipColor(RGB color) {
108   int l = Lum(color);
109   int n = std::min(color.red, std::min(color.green, color.blue));
110   int x = std::max(color.red, std::max(color.green, color.blue));
111   if (n < 0) {
112     color.red = l + ((color.red - l) * l / (l - n));
113     color.green = l + ((color.green - l) * l / (l - n));
114     color.blue = l + ((color.blue - l) * l / (l - n));
115   }
116   if (x > 255) {
117     color.red = l + ((color.red - l) * (255 - l) / (x - l));
118     color.green = l + ((color.green - l) * (255 - l) / (x - l));
119     color.blue = l + ((color.blue - l) * (255 - l) / (x - l));
120   }
121   return color;
122 }
123 
SetLum(RGB color,int l)124 RGB SetLum(RGB color, int l) {
125   int d = l - Lum(color);
126   color.red += d;
127   color.green += d;
128   color.blue += d;
129   return ClipColor(color);
130 }
131 
Sat(RGB color)132 int Sat(RGB color) {
133   return std::max(color.red, std::max(color.green, color.blue)) -
134          std::min(color.red, std::min(color.green, color.blue));
135 }
136 
SetSat(RGB color,int s)137 RGB SetSat(RGB color, int s) {
138   int min = std::min(color.red, std::min(color.green, color.blue));
139   int max = std::max(color.red, std::max(color.green, color.blue));
140   if (min == max)
141     return {0, 0, 0};
142 
143   color.red = (color.red - min) * s / (max - min);
144   color.green = (color.green - min) * s / (max - min);
145   color.blue = (color.blue - min) * s / (max - min);
146   return color;
147 }
148 
RGB_Blend(BlendMode blend_mode,const uint8_t * src_scan,const uint8_t * dest_scan,int results[3])149 void RGB_Blend(BlendMode blend_mode,
150                const uint8_t* src_scan,
151                const uint8_t* dest_scan,
152                int results[3]) {
153   RGB result = {0, 0, 0};
154   RGB src;
155   src.red = src_scan[2];
156   src.green = src_scan[1];
157   src.blue = src_scan[0];
158   RGB back;
159   back.red = dest_scan[2];
160   back.green = dest_scan[1];
161   back.blue = dest_scan[0];
162   switch (blend_mode) {
163     case BlendMode::kHue:
164       result = SetLum(SetSat(src, Sat(back)), Lum(back));
165       break;
166     case BlendMode::kSaturation:
167       result = SetLum(SetSat(back, Sat(src)), Lum(back));
168       break;
169     case BlendMode::kColor:
170       result = SetLum(src, Lum(back));
171       break;
172     case BlendMode::kLuminosity:
173       result = SetLum(back, Lum(src));
174       break;
175     default:
176       break;
177   }
178   results[0] = result.blue;
179   results[1] = result.green;
180   results[2] = result.red;
181 }
182 
GetAlpha(uint8_t src_alpha,const uint8_t * clip_scan,int col)183 int GetAlpha(uint8_t src_alpha, const uint8_t* clip_scan, int col) {
184   return clip_scan ? clip_scan[col] * src_alpha / 255 : src_alpha;
185 }
186 
GetAlphaWithSrc(uint8_t src_alpha,const uint8_t * clip_scan,const uint8_t * src_scan,int col)187 int GetAlphaWithSrc(uint8_t src_alpha,
188                     const uint8_t* clip_scan,
189                     const uint8_t* src_scan,
190                     int col) {
191   int result = src_alpha * src_scan[col];
192   if (clip_scan) {
193     result *= clip_scan[col];
194     result /= 255;
195   }
196   return result / 255;
197 }
198 
CompositeRow_AlphaToMask(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int pixel_count,pdfium::span<const uint8_t> clip_span,uint8_t stride)199 void CompositeRow_AlphaToMask(pdfium::span<uint8_t> dest_span,
200                               pdfium::span<const uint8_t> src_span,
201                               int pixel_count,
202                               pdfium::span<const uint8_t> clip_span,
203                               uint8_t stride) {
204   uint8_t* dest_scan = dest_span.data();
205   const uint8_t* src_scan = src_span.data();
206   const uint8_t* clip_scan = clip_span.data();
207   src_scan += stride - 1;
208   for (int col = 0; col < pixel_count; ++col) {
209     int src_alpha = GetAlpha(*src_scan, clip_scan, col);
210     uint8_t back_alpha = *dest_scan;
211     if (!back_alpha)
212       *dest_scan = src_alpha;
213     else if (src_alpha)
214       *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
215     ++dest_scan;
216     src_scan += stride;
217   }
218 }
219 
CompositeRow_Rgb2Mask(pdfium::span<uint8_t> dest_span,int width,pdfium::span<const uint8_t> clip_span)220 void CompositeRow_Rgb2Mask(pdfium::span<uint8_t> dest_span,
221                            int width,
222                            pdfium::span<const uint8_t> clip_span) {
223   uint8_t* dest_scan = dest_span.data();
224   const uint8_t* clip_scan = clip_span.data();
225   if (!clip_scan) {
226     memset(dest_scan, 0xff, width);
227     return;
228   }
229   for (int i = 0; i < width; ++i) {
230     *dest_scan = FXDIB_ALPHA_UNION(*dest_scan, *clip_scan);
231     ++dest_scan;
232     ++clip_scan;
233   }
234 }
235 
IsNonSeparableBlendMode(BlendMode mode)236 bool IsNonSeparableBlendMode(BlendMode mode) {
237   switch (mode) {
238     case BlendMode::kHue:
239     case BlendMode::kSaturation:
240     case BlendMode::kColor:
241     case BlendMode::kLuminosity:
242       return true;
243     default:
244       return false;
245   }
246 }
247 
GetGray(const uint8_t * src_scan)248 uint8_t GetGray(const uint8_t* src_scan) {
249   return FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
250 }
251 
GetGrayWithBlend(const uint8_t * src_scan,const uint8_t * dest_scan,BlendMode blend_type)252 uint8_t GetGrayWithBlend(const uint8_t* src_scan,
253                          const uint8_t* dest_scan,
254                          BlendMode blend_type) {
255   uint8_t gray = GetGray(src_scan);
256   if (IsNonSeparableBlendMode(blend_type))
257     gray = blend_type == BlendMode::kLuminosity ? gray : *dest_scan;
258   else if (blend_type != BlendMode::kNormal)
259     gray = Blend(blend_type, *dest_scan, gray);
260   return gray;
261 }
262 
CompositeRow_Argb2Gray(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)263 void CompositeRow_Argb2Gray(pdfium::span<uint8_t> dest_span,
264                             pdfium::span<const uint8_t> src_span,
265                             int pixel_count,
266                             BlendMode blend_type,
267                             pdfium::span<const uint8_t> clip_span) {
268   uint8_t* dest_scan = dest_span.data();
269   const uint8_t* src_scan = src_span.data();
270   const uint8_t* clip_scan = clip_span.data();
271   constexpr size_t kOffset = 4;
272   for (int col = 0; col < pixel_count; ++col) {
273     int src_alpha = GetAlpha(src_scan[3], clip_scan, col);
274     if (src_alpha) {
275       uint8_t gray = GetGrayWithBlend(src_scan, dest_scan, blend_type);
276       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
277     }
278     ++dest_scan;
279     src_scan += kOffset;
280   }
281 }
282 
CompositeRow_Rgb2Gray(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int src_Bpp,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)283 void CompositeRow_Rgb2Gray(pdfium::span<uint8_t> dest_span,
284                            pdfium::span<const uint8_t> src_span,
285                            int src_Bpp,
286                            int pixel_count,
287                            BlendMode blend_type,
288                            pdfium::span<const uint8_t> clip_span) {
289   uint8_t* dest_scan = dest_span.data();
290   const uint8_t* src_scan = src_span.data();
291   const uint8_t* clip_scan = clip_span.data();
292   for (int col = 0; col < pixel_count; ++col) {
293     uint8_t gray = GetGrayWithBlend(src_scan, dest_scan, blend_type);
294     if (clip_scan && clip_scan[col] < 255)
295       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
296     else
297       *dest_scan = gray;
298     ++dest_scan;
299     src_scan += src_Bpp;
300   }
301 }
302 
CompositeRow_Argb2Argb(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)303 void CompositeRow_Argb2Argb(pdfium::span<uint8_t> dest_span,
304                             pdfium::span<const uint8_t> src_span,
305                             int pixel_count,
306                             BlendMode blend_type,
307                             pdfium::span<const uint8_t> clip_span) {
308   uint8_t* dest_scan = dest_span.data();
309   const uint8_t* src_scan = src_span.data();
310   const uint8_t* clip_scan = clip_span.data();
311   int blended_colors[3];
312   constexpr size_t kOffset = 4;
313   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
314   for (int col = 0; col < pixel_count; ++col) {
315     uint8_t back_alpha = dest_scan[3];
316     uint8_t src_alpha = GetAlpha(src_scan[3], clip_scan, col);
317     if (back_alpha == 0) {
318       if (clip_scan) {
319         FXARGB_SETDIB(dest_scan,
320                       (FXARGB_GETDIB(src_scan) & 0xffffff) | (src_alpha << 24));
321       } else {
322         memcpy(dest_scan, src_scan, 4);
323       }
324       dest_scan += kOffset;
325       src_scan += kOffset;
326       continue;
327     }
328     if (src_alpha == 0) {
329       dest_scan += kOffset;
330       src_scan += kOffset;
331       continue;
332     }
333     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
334     dest_scan[3] = dest_alpha;
335     int alpha_ratio = src_alpha * 255 / dest_alpha;
336     if (bNonseparableBlend)
337       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
338     for (int color = 0; color < 3; ++color) {
339       if (blend_type != BlendMode::kNormal) {
340         int blended = bNonseparableBlend
341                           ? blended_colors[color]
342                           : Blend(blend_type, *dest_scan, *src_scan);
343         blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
344         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
345       } else {
346         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
347       }
348       ++dest_scan;
349       ++src_scan;
350     }
351     ++dest_scan;
352     ++src_scan;
353   }
354 }
355 
CompositeRow_Rgb2Argb_Blend_NoClip(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int src_Bpp)356 void CompositeRow_Rgb2Argb_Blend_NoClip(pdfium::span<uint8_t> dest_span,
357                                         pdfium::span<const uint8_t> src_span,
358                                         int width,
359                                         BlendMode blend_type,
360                                         int src_Bpp) {
361   uint8_t* dest_scan = dest_span.data();
362   const uint8_t* src_scan = src_span.data();
363   int blended_colors[3];
364   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
365   int src_gap = src_Bpp - 3;
366   for (int col = 0; col < width; ++col) {
367     uint8_t* dest_alpha = &dest_scan[3];
368     uint8_t back_alpha = *dest_alpha;
369     if (back_alpha == 0) {
370       if (src_Bpp == 4) {
371         FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
372       } else {
373         FXARGB_SETDIB(dest_scan,
374                       ArgbEncode(0xff, src_scan[2], src_scan[1], src_scan[0]));
375       }
376       dest_scan += 4;
377       src_scan += src_Bpp;
378       continue;
379     }
380     *dest_alpha = 0xff;
381     if (bNonseparableBlend)
382       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
383     for (int color = 0; color < 3; ++color) {
384       int src_color = *src_scan;
385       int blended = bNonseparableBlend
386                         ? blended_colors[color]
387                         : Blend(blend_type, *dest_scan, src_color);
388       *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
389       ++dest_scan;
390       ++src_scan;
391     }
392     ++dest_scan;
393     src_scan += src_gap;
394   }
395 }
396 
CompositeRow_Rgb2Argb_Blend_Clip(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int src_Bpp,pdfium::span<const uint8_t> clip_span)397 void CompositeRow_Rgb2Argb_Blend_Clip(pdfium::span<uint8_t> dest_span,
398                                       pdfium::span<const uint8_t> src_span,
399                                       int width,
400                                       BlendMode blend_type,
401                                       int src_Bpp,
402                                       pdfium::span<const uint8_t> clip_span) {
403   uint8_t* dest_scan = dest_span.data();
404   const uint8_t* src_scan = src_span.data();
405   const uint8_t* clip_scan = clip_span.data();
406   int blended_colors[3];
407   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
408   int src_gap = src_Bpp - 3;
409   for (int col = 0; col < width; ++col) {
410     int src_alpha = *clip_scan++;
411     uint8_t back_alpha = dest_scan[3];
412     if (back_alpha == 0) {
413       memcpy(dest_scan, src_scan, 3);
414       dest_scan += 3;
415       src_scan += src_Bpp;
416       dest_scan++;
417       continue;
418     }
419     if (src_alpha == 0) {
420       dest_scan += 4;
421       src_scan += src_Bpp;
422       continue;
423     }
424     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
425     dest_scan[3] = dest_alpha;
426     int alpha_ratio = src_alpha * 255 / dest_alpha;
427     if (bNonseparableBlend)
428       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
429     for (int color = 0; color < 3; color++) {
430       int src_color = *src_scan;
431       int blended = bNonseparableBlend
432                         ? blended_colors[color]
433                         : Blend(blend_type, *dest_scan, src_color);
434       blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
435       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
436       dest_scan++;
437       src_scan++;
438     }
439     src_scan += src_gap;
440     dest_scan++;
441   }
442 }
443 
CompositeRow_Rgb2Argb_NoBlend_Clip(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int src_Bpp,pdfium::span<const uint8_t> clip_span)444 void CompositeRow_Rgb2Argb_NoBlend_Clip(pdfium::span<uint8_t> dest_span,
445                                         pdfium::span<const uint8_t> src_span,
446                                         int width,
447                                         int src_Bpp,
448                                         pdfium::span<const uint8_t> clip_span) {
449   uint8_t* dest_scan = dest_span.data();
450   const uint8_t* src_scan = src_span.data();
451   const uint8_t* clip_scan = clip_span.data();
452   int src_gap = src_Bpp - 3;
453   for (int col = 0; col < width; col++) {
454     int src_alpha = clip_scan[col];
455     if (src_alpha == 255) {
456       memcpy(dest_scan, src_scan, 3);
457       dest_scan += 3;
458       *dest_scan++ = 255;
459       src_scan += src_Bpp;
460       continue;
461     }
462     if (src_alpha == 0) {
463       dest_scan += 4;
464       src_scan += src_Bpp;
465       continue;
466     }
467     int back_alpha = dest_scan[3];
468     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
469     dest_scan[3] = dest_alpha;
470     int alpha_ratio = src_alpha * 255 / dest_alpha;
471     for (int color = 0; color < 3; color++) {
472       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
473       dest_scan++;
474       src_scan++;
475     }
476     dest_scan++;
477     src_scan += src_gap;
478   }
479 }
480 
CompositeRow_Rgb2Argb_NoBlend_NoClip(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int src_Bpp)481 void CompositeRow_Rgb2Argb_NoBlend_NoClip(pdfium::span<uint8_t> dest_span,
482                                           pdfium::span<const uint8_t> src_span,
483                                           int width,
484                                           int src_Bpp) {
485   uint8_t* dest_scan = dest_span.data();
486   const uint8_t* src_scan = src_span.data();
487   for (int col = 0; col < width; col++) {
488     if (src_Bpp == 4) {
489       FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
490     } else {
491       FXARGB_SETDIB(dest_scan,
492                     ArgbEncode(0xff, src_scan[2], src_scan[1], src_scan[0]));
493     }
494     dest_scan += 4;
495     src_scan += src_Bpp;
496   }
497 }
498 
CompositeRow_Argb2Rgb_Blend(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int dest_Bpp,pdfium::span<const uint8_t> clip_span)499 void CompositeRow_Argb2Rgb_Blend(pdfium::span<uint8_t> dest_span,
500                                  pdfium::span<const uint8_t> src_span,
501                                  int width,
502                                  BlendMode blend_type,
503                                  int dest_Bpp,
504                                  pdfium::span<const uint8_t> clip_span) {
505   uint8_t* dest_scan = dest_span.data();
506   const uint8_t* src_scan = src_span.data();
507   const uint8_t* clip_scan = clip_span.data();
508   int blended_colors[3];
509   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
510   int dest_gap = dest_Bpp - 3;
511   for (int col = 0; col < width; col++) {
512     uint8_t src_alpha;
513     if (clip_scan) {
514       src_alpha = src_scan[3] * (*clip_scan++) / 255;
515     } else {
516       src_alpha = src_scan[3];
517     }
518     if (src_alpha == 0) {
519       dest_scan += dest_Bpp;
520       src_scan += 4;
521       continue;
522     }
523     if (bNonseparableBlend) {
524       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
525     }
526     for (int color = 0; color < 3; color++) {
527       int back_color = *dest_scan;
528       int blended = bNonseparableBlend
529                         ? blended_colors[color]
530                         : Blend(blend_type, back_color, *src_scan);
531       *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
532       dest_scan++;
533       src_scan++;
534     }
535     dest_scan += dest_gap;
536     src_scan++;
537   }
538 }
539 
CompositeRow_Argb2Rgb_NoBlend(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int dest_Bpp,pdfium::span<const uint8_t> clip_span)540 void CompositeRow_Argb2Rgb_NoBlend(pdfium::span<uint8_t> dest_span,
541                                    pdfium::span<const uint8_t> src_span,
542                                    int width,
543                                    int dest_Bpp,
544                                    pdfium::span<const uint8_t> clip_span) {
545   uint8_t* dest_scan = dest_span.data();
546   const uint8_t* src_scan = src_span.data();
547   const uint8_t* clip_scan = clip_span.data();
548   int dest_gap = dest_Bpp - 3;
549   for (int col = 0; col < width; col++) {
550     uint8_t src_alpha;
551     if (clip_scan) {
552       src_alpha = src_scan[3] * (*clip_scan++) / 255;
553     } else {
554       src_alpha = src_scan[3];
555     }
556     if (src_alpha == 255) {
557       memcpy(dest_scan, src_scan, 3);
558       dest_scan += dest_Bpp;
559       src_scan += 4;
560       continue;
561     }
562     if (src_alpha == 0) {
563       dest_scan += dest_Bpp;
564       src_scan += 4;
565       continue;
566     }
567     for (int color = 0; color < 3; color++) {
568       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
569       dest_scan++;
570       src_scan++;
571     }
572     dest_scan += dest_gap;
573     src_scan++;
574   }
575 }
576 
CompositeRow_Rgb2Rgb_Blend_NoClip(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int dest_Bpp,int src_Bpp)577 void CompositeRow_Rgb2Rgb_Blend_NoClip(pdfium::span<uint8_t> dest_span,
578                                        pdfium::span<const uint8_t> src_span,
579                                        int width,
580                                        BlendMode blend_type,
581                                        int dest_Bpp,
582                                        int src_Bpp) {
583   uint8_t* dest_scan = dest_span.data();
584   const uint8_t* src_scan = src_span.data();
585   int blended_colors[3];
586   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
587   int dest_gap = dest_Bpp - 3;
588   int src_gap = src_Bpp - 3;
589   for (int col = 0; col < width; col++) {
590     if (bNonseparableBlend) {
591       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
592     }
593     for (int color = 0; color < 3; color++) {
594       int back_color = *dest_scan;
595       int src_color = *src_scan;
596       int blended = bNonseparableBlend
597                         ? blended_colors[color]
598                         : Blend(blend_type, back_color, src_color);
599       *dest_scan = blended;
600       dest_scan++;
601       src_scan++;
602     }
603     dest_scan += dest_gap;
604     src_scan += src_gap;
605   }
606 }
607 
CompositeRow_Rgb2Rgb_Blend_Clip(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int dest_Bpp,int src_Bpp,pdfium::span<const uint8_t> clip_span)608 void CompositeRow_Rgb2Rgb_Blend_Clip(pdfium::span<uint8_t> dest_span,
609                                      pdfium::span<const uint8_t> src_span,
610                                      int width,
611                                      BlendMode blend_type,
612                                      int dest_Bpp,
613                                      int src_Bpp,
614                                      pdfium::span<const uint8_t> clip_span) {
615   uint8_t* dest_scan = dest_span.data();
616   const uint8_t* src_scan = src_span.data();
617   const uint8_t* clip_scan = clip_span.data();
618   int blended_colors[3];
619   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
620   int dest_gap = dest_Bpp - 3;
621   int src_gap = src_Bpp - 3;
622   for (int col = 0; col < width; col++) {
623     uint8_t src_alpha = *clip_scan++;
624     if (src_alpha == 0) {
625       dest_scan += dest_Bpp;
626       src_scan += src_Bpp;
627       continue;
628     }
629     if (bNonseparableBlend) {
630       RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
631     }
632     for (int color = 0; color < 3; color++) {
633       int src_color = *src_scan;
634       int back_color = *dest_scan;
635       int blended = bNonseparableBlend
636                         ? blended_colors[color]
637                         : Blend(blend_type, back_color, src_color);
638       *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
639       dest_scan++;
640       src_scan++;
641     }
642     dest_scan += dest_gap;
643     src_scan += src_gap;
644   }
645 }
646 
CompositeRow_Rgb2Rgb_NoBlend_NoClip(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int dest_Bpp,int src_Bpp)647 void CompositeRow_Rgb2Rgb_NoBlend_NoClip(pdfium::span<uint8_t> dest_span,
648                                          pdfium::span<const uint8_t> src_span,
649                                          int width,
650                                          int dest_Bpp,
651                                          int src_Bpp) {
652   uint8_t* dest_scan = dest_span.data();
653   const uint8_t* src_scan = src_span.data();
654   if (dest_Bpp == src_Bpp) {
655     memcpy(dest_scan, src_scan, width * dest_Bpp);
656     return;
657   }
658   for (int col = 0; col < width; col++) {
659     memcpy(dest_scan, src_scan, 3);
660     dest_scan += dest_Bpp;
661     src_scan += src_Bpp;
662   }
663 }
664 
CompositeRow_Rgb2Rgb_NoBlend_Clip(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int dest_Bpp,int src_Bpp,pdfium::span<const uint8_t> clip_span)665 void CompositeRow_Rgb2Rgb_NoBlend_Clip(pdfium::span<uint8_t> dest_span,
666                                        pdfium::span<const uint8_t> src_span,
667                                        int width,
668                                        int dest_Bpp,
669                                        int src_Bpp,
670                                        pdfium::span<const uint8_t> clip_span) {
671   uint8_t* dest_scan = dest_span.data();
672   const uint8_t* src_scan = src_span.data();
673   const uint8_t* clip_scan = clip_span.data();
674   for (int col = 0; col < width; col++) {
675     int src_alpha = clip_scan[col];
676     if (src_alpha == 255) {
677       memcpy(dest_scan, src_scan, 3);
678     } else if (src_alpha) {
679       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
680       dest_scan++;
681       src_scan++;
682       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
683       dest_scan++;
684       src_scan++;
685       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
686       dest_scan += dest_Bpp - 2;
687       src_scan += src_Bpp - 2;
688       continue;
689     }
690     dest_scan += dest_Bpp;
691     src_scan += src_Bpp;
692   }
693 }
694 
CompositeRow_8bppPal2Gray(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,pdfium::span<const uint8_t> palette_span,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)695 void CompositeRow_8bppPal2Gray(pdfium::span<uint8_t> dest_span,
696                                pdfium::span<const uint8_t> src_span,
697                                pdfium::span<const uint8_t> palette_span,
698                                int pixel_count,
699                                BlendMode blend_type,
700                                pdfium::span<const uint8_t> clip_span) {
701   uint8_t* dest_scan = dest_span.data();
702   const uint8_t* src_scan = src_span.data();
703   const uint8_t* clip_scan = clip_span.data();
704   const uint8_t* pPalette = palette_span.data();
705   if (blend_type != BlendMode::kNormal) {
706     bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
707     for (int col = 0; col < pixel_count; col++) {
708       uint8_t gray = pPalette[*src_scan];
709       if (bNonseparableBlend)
710         gray = blend_type == BlendMode::kLuminosity ? gray : *dest_scan;
711       else
712         gray = Blend(blend_type, *dest_scan, gray);
713       if (clip_scan && clip_scan[col] < 255)
714         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
715       else
716         *dest_scan = gray;
717       dest_scan++;
718       src_scan++;
719     }
720     return;
721   }
722   for (int col = 0; col < pixel_count; col++) {
723     uint8_t gray = pPalette[*src_scan];
724     if (clip_scan && clip_scan[col] < 255)
725       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
726     else
727       *dest_scan = gray;
728     dest_scan++;
729     src_scan++;
730   }
731 }
732 
CompositeRow_1bppPal2Gray(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int src_left,pdfium::span<const uint8_t> src_palette,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)733 void CompositeRow_1bppPal2Gray(pdfium::span<uint8_t> dest_span,
734                                pdfium::span<const uint8_t> src_span,
735                                int src_left,
736                                pdfium::span<const uint8_t> src_palette,
737                                int pixel_count,
738                                BlendMode blend_type,
739                                pdfium::span<const uint8_t> clip_span) {
740   uint8_t* dest_scan = dest_span.data();
741   const uint8_t* src_scan = src_span.data();
742   const uint8_t* clip_scan = clip_span.data();
743   int reset_gray = src_palette[0];
744   int set_gray = src_palette[1];
745   if (blend_type != BlendMode::kNormal) {
746     bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
747     for (int col = 0; col < pixel_count; col++) {
748       uint8_t gray =
749           (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
750               ? set_gray
751               : reset_gray;
752       if (bNonseparableBlend)
753         gray = blend_type == BlendMode::kLuminosity ? gray : *dest_scan;
754       else
755         gray = Blend(blend_type, *dest_scan, gray);
756       if (clip_scan && clip_scan[col] < 255) {
757         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
758       } else {
759         *dest_scan = gray;
760       }
761       dest_scan++;
762     }
763     return;
764   }
765   for (int col = 0; col < pixel_count; col++) {
766     uint8_t gray =
767         (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
768             ? set_gray
769             : reset_gray;
770     if (clip_scan && clip_scan[col] < 255) {
771       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
772     } else {
773       *dest_scan = gray;
774     }
775     dest_scan++;
776   }
777 }
778 
CompositeRow_8bppRgb2Rgb_NoBlend(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,pdfium::span<const uint32_t> palette_span,int pixel_count,int DestBpp,pdfium::span<const uint8_t> clip_span)779 void CompositeRow_8bppRgb2Rgb_NoBlend(pdfium::span<uint8_t> dest_span,
780                                       pdfium::span<const uint8_t> src_span,
781                                       pdfium::span<const uint32_t> palette_span,
782                                       int pixel_count,
783                                       int DestBpp,
784                                       pdfium::span<const uint8_t> clip_span) {
785   uint8_t* dest_scan = dest_span.data();
786   const uint8_t* src_scan = src_span.data();
787   const uint8_t* clip_scan = clip_span.data();
788   const uint32_t* pPalette = palette_span.data();
789   FX_ARGB argb = 0;
790   for (int col = 0; col < pixel_count; col++) {
791     argb = pPalette[*src_scan];
792     int src_r = FXARGB_R(argb);
793     int src_g = FXARGB_G(argb);
794     int src_b = FXARGB_B(argb);
795     if (clip_scan && clip_scan[col] < 255) {
796       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]);
797       dest_scan++;
798       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]);
799       dest_scan++;
800       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]);
801       dest_scan++;
802     } else {
803       *dest_scan++ = src_b;
804       *dest_scan++ = src_g;
805       *dest_scan++ = src_r;
806     }
807     if (DestBpp == 4) {
808       dest_scan++;
809     }
810     src_scan++;
811   }
812 }
813 
CompositeRow_1bppRgb2Rgb_NoBlend(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int src_left,pdfium::span<const uint32_t> src_palette,int pixel_count,int DestBpp,pdfium::span<const uint8_t> clip_span)814 void CompositeRow_1bppRgb2Rgb_NoBlend(pdfium::span<uint8_t> dest_span,
815                                       pdfium::span<const uint8_t> src_span,
816                                       int src_left,
817                                       pdfium::span<const uint32_t> src_palette,
818                                       int pixel_count,
819                                       int DestBpp,
820                                       pdfium::span<const uint8_t> clip_span) {
821   uint8_t* dest_scan = dest_span.data();
822   const uint8_t* src_scan = src_span.data();
823   const uint8_t* clip_scan = clip_span.data();
824   int reset_r = FXARGB_R(src_palette[0]);
825   int reset_g = FXARGB_G(src_palette[0]);
826   int reset_b = FXARGB_B(src_palette[0]);
827   int set_r = FXARGB_R(src_palette[1]);
828   int set_g = FXARGB_G(src_palette[1]);
829   int set_b = FXARGB_B(src_palette[1]);
830   for (int col = 0; col < pixel_count; col++) {
831     int src_r;
832     int src_g;
833     int src_b;
834     if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
835       src_r = set_r;
836       src_g = set_g;
837       src_b = set_b;
838     } else {
839       src_r = reset_r;
840       src_g = reset_g;
841       src_b = reset_b;
842     }
843     if (clip_scan && clip_scan[col] < 255) {
844       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]);
845       dest_scan++;
846       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]);
847       dest_scan++;
848       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]);
849       dest_scan++;
850     } else {
851       *dest_scan++ = src_b;
852       *dest_scan++ = src_g;
853       *dest_scan++ = src_r;
854     }
855     if (DestBpp == 4) {
856       dest_scan++;
857     }
858   }
859 }
860 
CompositeRow_8bppRgb2Argb_NoBlend(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,pdfium::span<const uint32_t> palette_span,pdfium::span<const uint8_t> clip_span)861 void CompositeRow_8bppRgb2Argb_NoBlend(
862     pdfium::span<uint8_t> dest_span,
863     pdfium::span<const uint8_t> src_span,
864     int width,
865     pdfium::span<const uint32_t> palette_span,
866     pdfium::span<const uint8_t> clip_span) {
867   uint8_t* dest_scan = dest_span.data();
868   const uint8_t* src_scan = src_span.data();
869   const uint8_t* clip_scan = clip_span.data();
870   const uint32_t* pPalette = palette_span.data();
871   for (int col = 0; col < width; col++) {
872     FX_ARGB argb = pPalette[*src_scan];
873     int src_r = FXARGB_R(argb);
874     int src_g = FXARGB_G(argb);
875     int src_b = FXARGB_B(argb);
876     if (!clip_scan || clip_scan[col] == 255) {
877       *dest_scan++ = src_b;
878       *dest_scan++ = src_g;
879       *dest_scan++ = src_r;
880       *dest_scan++ = 255;
881       src_scan++;
882       continue;
883     }
884     int src_alpha = clip_scan[col];
885     if (src_alpha == 0) {
886       dest_scan += 4;
887       src_scan++;
888       continue;
889     }
890     int back_alpha = dest_scan[3];
891     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
892     dest_scan[3] = dest_alpha;
893     int alpha_ratio = src_alpha * 255 / dest_alpha;
894     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
895     dest_scan++;
896     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
897     dest_scan++;
898     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
899     dest_scan++;
900     dest_scan++;
901     src_scan++;
902   }
903 }
904 
CompositeRow_1bppRgb2Argb_NoBlend(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int src_left,int width,pdfium::span<const uint32_t> src_palette,pdfium::span<const uint8_t> clip_span)905 void CompositeRow_1bppRgb2Argb_NoBlend(pdfium::span<uint8_t> dest_span,
906                                        pdfium::span<const uint8_t> src_span,
907                                        int src_left,
908                                        int width,
909                                        pdfium::span<const uint32_t> src_palette,
910                                        pdfium::span<const uint8_t> clip_span) {
911   uint8_t* dest_scan = dest_span.data();
912   const uint8_t* src_scan = src_span.data();
913   const uint8_t* clip_scan = clip_span.data();
914   int reset_r = FXARGB_R(src_palette[0]);
915   int reset_g = FXARGB_G(src_palette[0]);
916   int reset_b = FXARGB_B(src_palette[0]);
917   int set_r = FXARGB_R(src_palette[1]);
918   int set_g = FXARGB_G(src_palette[1]);
919   int set_b = FXARGB_B(src_palette[1]);
920   for (int col = 0; col < width; col++) {
921     int src_r;
922     int src_g;
923     int src_b;
924     if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
925       src_r = set_r;
926       src_g = set_g;
927       src_b = set_b;
928     } else {
929       src_r = reset_r;
930       src_g = reset_g;
931       src_b = reset_b;
932     }
933     if (!clip_scan || clip_scan[col] == 255) {
934       *dest_scan++ = src_b;
935       *dest_scan++ = src_g;
936       *dest_scan++ = src_r;
937       *dest_scan++ = 255;
938       continue;
939     }
940     int src_alpha = clip_scan[col];
941     if (src_alpha == 0) {
942       dest_scan += 4;
943       continue;
944     }
945     int back_alpha = dest_scan[3];
946     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
947     dest_scan[3] = dest_alpha;
948     int alpha_ratio = src_alpha * 255 / dest_alpha;
949     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
950     dest_scan++;
951     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
952     dest_scan++;
953     *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
954     dest_scan++;
955     dest_scan++;
956   }
957 }
958 
CompositeRow_ByteMask2Argb(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_r,int src_g,int src_b,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)959 void CompositeRow_ByteMask2Argb(pdfium::span<uint8_t> dest_span,
960                                 pdfium::span<const uint8_t> src_span,
961                                 int mask_alpha,
962                                 int src_r,
963                                 int src_g,
964                                 int src_b,
965                                 int pixel_count,
966                                 BlendMode blend_type,
967                                 pdfium::span<const uint8_t> clip_span) {
968   uint8_t* dest_scan = dest_span.data();
969   const uint8_t* src_scan = src_span.data();
970   const uint8_t* clip_scan = clip_span.data();
971   for (int col = 0; col < pixel_count; col++) {
972     int src_alpha = GetAlphaWithSrc(mask_alpha, clip_scan, src_scan, col);
973     uint8_t back_alpha = dest_scan[3];
974     if (back_alpha == 0) {
975       FXARGB_SETDIB(dest_scan, ArgbEncode(src_alpha, src_r, src_g, src_b));
976       dest_scan += 4;
977       continue;
978     }
979     if (src_alpha == 0) {
980       dest_scan += 4;
981       continue;
982     }
983     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
984     dest_scan[3] = dest_alpha;
985     int alpha_ratio = src_alpha * 255 / dest_alpha;
986     if (IsNonSeparableBlendMode(blend_type)) {
987       int blended_colors[3];
988       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
989                          static_cast<uint8_t>(src_g),
990                          static_cast<uint8_t>(src_r)};
991       RGB_Blend(blend_type, scan, dest_scan, blended_colors);
992       *dest_scan =
993           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
994       dest_scan++;
995       *dest_scan =
996           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
997       dest_scan++;
998       *dest_scan =
999           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
1000     } else if (blend_type != BlendMode::kNormal) {
1001       int blended = Blend(blend_type, *dest_scan, src_b);
1002       blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
1003       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
1004       dest_scan++;
1005       blended = Blend(blend_type, *dest_scan, src_g);
1006       blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
1007       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
1008       dest_scan++;
1009       blended = Blend(blend_type, *dest_scan, src_r);
1010       blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
1011       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
1012     } else {
1013       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
1014       dest_scan++;
1015       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
1016       dest_scan++;
1017       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
1018     }
1019     dest_scan += 2;
1020   }
1021 }
1022 
CompositeRow_ByteMask2Rgb(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_r,int src_g,int src_b,int pixel_count,BlendMode blend_type,int Bpp,pdfium::span<const uint8_t> clip_span)1023 void CompositeRow_ByteMask2Rgb(pdfium::span<uint8_t> dest_span,
1024                                pdfium::span<const uint8_t> src_span,
1025                                int mask_alpha,
1026                                int src_r,
1027                                int src_g,
1028                                int src_b,
1029                                int pixel_count,
1030                                BlendMode blend_type,
1031                                int Bpp,
1032                                pdfium::span<const uint8_t> clip_span) {
1033   uint8_t* dest_scan = dest_span.data();
1034   const uint8_t* src_scan = src_span.data();
1035   const uint8_t* clip_scan = clip_span.data();
1036   for (int col = 0; col < pixel_count; col++) {
1037     int src_alpha = GetAlphaWithSrc(mask_alpha, clip_scan, src_scan, col);
1038     if (src_alpha == 0) {
1039       dest_scan += Bpp;
1040       continue;
1041     }
1042     if (IsNonSeparableBlendMode(blend_type)) {
1043       int blended_colors[3];
1044       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
1045                          static_cast<uint8_t>(src_g),
1046                          static_cast<uint8_t>(src_r)};
1047       RGB_Blend(blend_type, scan, dest_scan, blended_colors);
1048       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha);
1049       dest_scan++;
1050       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha);
1051       dest_scan++;
1052       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha);
1053     } else if (blend_type != BlendMode::kNormal) {
1054       int blended = Blend(blend_type, *dest_scan, src_b);
1055       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
1056       dest_scan++;
1057       blended = Blend(blend_type, *dest_scan, src_g);
1058       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
1059       dest_scan++;
1060       blended = Blend(blend_type, *dest_scan, src_r);
1061       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
1062     } else {
1063       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
1064       dest_scan++;
1065       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
1066       dest_scan++;
1067       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
1068     }
1069     dest_scan += Bpp - 2;
1070   }
1071 }
1072 
CompositeRow_ByteMask2Mask(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int pixel_count,pdfium::span<const uint8_t> clip_span)1073 void CompositeRow_ByteMask2Mask(pdfium::span<uint8_t> dest_span,
1074                                 pdfium::span<const uint8_t> src_span,
1075                                 int mask_alpha,
1076                                 int pixel_count,
1077                                 pdfium::span<const uint8_t> clip_span) {
1078   uint8_t* dest_scan = dest_span.data();
1079   const uint8_t* src_scan = src_span.data();
1080   const uint8_t* clip_scan = clip_span.data();
1081   for (int col = 0; col < pixel_count; col++) {
1082     int src_alpha = GetAlphaWithSrc(mask_alpha, clip_scan, src_scan, col);
1083     uint8_t back_alpha = *dest_scan;
1084     if (!back_alpha) {
1085       *dest_scan = src_alpha;
1086     } else if (src_alpha) {
1087       *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1088     }
1089     dest_scan++;
1090   }
1091 }
1092 
CompositeRow_ByteMask2Gray(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_gray,int pixel_count,pdfium::span<const uint8_t> clip_span)1093 void CompositeRow_ByteMask2Gray(pdfium::span<uint8_t> dest_span,
1094                                 pdfium::span<const uint8_t> src_span,
1095                                 int mask_alpha,
1096                                 int src_gray,
1097                                 int pixel_count,
1098                                 pdfium::span<const uint8_t> clip_span) {
1099   uint8_t* dest_scan = dest_span.data();
1100   const uint8_t* src_scan = src_span.data();
1101   const uint8_t* clip_scan = clip_span.data();
1102   for (int col = 0; col < pixel_count; col++) {
1103     int src_alpha = GetAlphaWithSrc(mask_alpha, clip_scan, src_scan, col);
1104     if (src_alpha) {
1105       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha);
1106     }
1107     dest_scan++;
1108   }
1109 }
1110 
CompositeRow_BitMask2Argb(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_r,int src_g,int src_b,int src_left,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)1111 void CompositeRow_BitMask2Argb(pdfium::span<uint8_t> dest_span,
1112                                pdfium::span<const uint8_t> src_span,
1113                                int mask_alpha,
1114                                int src_r,
1115                                int src_g,
1116                                int src_b,
1117                                int src_left,
1118                                int pixel_count,
1119                                BlendMode blend_type,
1120                                pdfium::span<const uint8_t> clip_span) {
1121   uint8_t* dest_scan = dest_span.data();
1122   const uint8_t* src_scan = src_span.data();
1123   const uint8_t* clip_scan = clip_span.data();
1124   if (blend_type == BlendMode::kNormal && !clip_scan && mask_alpha == 255) {
1125     FX_ARGB argb = ArgbEncode(0xff, src_r, src_g, src_b);
1126     for (int col = 0; col < pixel_count; col++) {
1127       if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
1128         FXARGB_SETDIB(dest_scan, argb);
1129       }
1130       dest_scan += 4;
1131     }
1132     return;
1133   }
1134   for (int col = 0; col < pixel_count; col++) {
1135     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
1136       dest_scan += 4;
1137       continue;
1138     }
1139     int src_alpha = GetAlpha(mask_alpha, clip_scan, col);
1140     uint8_t back_alpha = dest_scan[3];
1141     if (back_alpha == 0) {
1142       FXARGB_SETDIB(dest_scan, ArgbEncode(src_alpha, src_r, src_g, src_b));
1143       dest_scan += 4;
1144       continue;
1145     }
1146     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1147     dest_scan[3] = dest_alpha;
1148     int alpha_ratio = src_alpha * 255 / dest_alpha;
1149     if (IsNonSeparableBlendMode(blend_type)) {
1150       int blended_colors[3];
1151       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
1152                          static_cast<uint8_t>(src_g),
1153                          static_cast<uint8_t>(src_r)};
1154       RGB_Blend(blend_type, scan, dest_scan, blended_colors);
1155       *dest_scan =
1156           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
1157       dest_scan++;
1158       *dest_scan =
1159           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
1160       dest_scan++;
1161       *dest_scan =
1162           FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
1163     } else if (blend_type != BlendMode::kNormal) {
1164       int blended = Blend(blend_type, *dest_scan, src_b);
1165       blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
1166       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
1167       dest_scan++;
1168       blended = Blend(blend_type, *dest_scan, src_g);
1169       blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
1170       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
1171       dest_scan++;
1172       blended = Blend(blend_type, *dest_scan, src_r);
1173       blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
1174       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
1175     } else {
1176       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
1177       dest_scan++;
1178       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
1179       dest_scan++;
1180       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
1181     }
1182     dest_scan += 2;
1183   }
1184 }
1185 
CompositeRow_BitMask2Rgb(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_r,int src_g,int src_b,int src_left,int pixel_count,BlendMode blend_type,int Bpp,pdfium::span<const uint8_t> clip_span)1186 void CompositeRow_BitMask2Rgb(pdfium::span<uint8_t> dest_span,
1187                               pdfium::span<const uint8_t> src_span,
1188                               int mask_alpha,
1189                               int src_r,
1190                               int src_g,
1191                               int src_b,
1192                               int src_left,
1193                               int pixel_count,
1194                               BlendMode blend_type,
1195                               int Bpp,
1196                               pdfium::span<const uint8_t> clip_span) {
1197   uint8_t* dest_scan = dest_span.data();
1198   const uint8_t* src_scan = src_span.data();
1199   const uint8_t* clip_scan = clip_span.data();
1200   if (blend_type == BlendMode::kNormal && !clip_scan && mask_alpha == 255) {
1201     for (int col = 0; col < pixel_count; col++) {
1202       if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
1203         dest_scan[2] = src_r;
1204         dest_scan[1] = src_g;
1205         dest_scan[0] = src_b;
1206       }
1207       dest_scan += Bpp;
1208     }
1209     return;
1210   }
1211   for (int col = 0; col < pixel_count; col++) {
1212     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
1213       dest_scan += Bpp;
1214       continue;
1215     }
1216     int src_alpha = GetAlpha(mask_alpha, clip_scan, col);
1217     if (src_alpha == 0) {
1218       dest_scan += Bpp;
1219       continue;
1220     }
1221     if (IsNonSeparableBlendMode(blend_type)) {
1222       int blended_colors[3];
1223       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
1224                          static_cast<uint8_t>(src_g),
1225                          static_cast<uint8_t>(src_r)};
1226       RGB_Blend(blend_type, scan, dest_scan, blended_colors);
1227       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha);
1228       dest_scan++;
1229       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha);
1230       dest_scan++;
1231       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha);
1232     } else if (blend_type != BlendMode::kNormal) {
1233       int blended = Blend(blend_type, *dest_scan, src_b);
1234       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
1235       dest_scan++;
1236       blended = Blend(blend_type, *dest_scan, src_g);
1237       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
1238       dest_scan++;
1239       blended = Blend(blend_type, *dest_scan, src_r);
1240       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
1241     } else {
1242       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
1243       dest_scan++;
1244       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
1245       dest_scan++;
1246       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
1247     }
1248     dest_scan += Bpp - 2;
1249   }
1250 }
1251 
CompositeRow_BitMask2Mask(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_left,int pixel_count,pdfium::span<const uint8_t> clip_span)1252 void CompositeRow_BitMask2Mask(pdfium::span<uint8_t> dest_span,
1253                                pdfium::span<const uint8_t> src_span,
1254                                int mask_alpha,
1255                                int src_left,
1256                                int pixel_count,
1257                                pdfium::span<const uint8_t> clip_span) {
1258   uint8_t* dest_scan = dest_span.data();
1259   const uint8_t* src_scan = src_span.data();
1260   const uint8_t* clip_scan = clip_span.data();
1261   for (int col = 0; col < pixel_count; col++) {
1262     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
1263       dest_scan++;
1264       continue;
1265     }
1266     int src_alpha = GetAlpha(mask_alpha, clip_scan, col);
1267     uint8_t back_alpha = *dest_scan;
1268     if (!back_alpha) {
1269       *dest_scan = src_alpha;
1270     } else if (src_alpha) {
1271       *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1272     }
1273     dest_scan++;
1274   }
1275 }
1276 
CompositeRow_BitMask2Gray(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_gray,int src_left,int pixel_count,pdfium::span<const uint8_t> clip_span)1277 void CompositeRow_BitMask2Gray(pdfium::span<uint8_t> dest_span,
1278                                pdfium::span<const uint8_t> src_span,
1279                                int mask_alpha,
1280                                int src_gray,
1281                                int src_left,
1282                                int pixel_count,
1283                                pdfium::span<const uint8_t> clip_span) {
1284   uint8_t* dest_scan = dest_span.data();
1285   const uint8_t* src_scan = src_span.data();
1286   const uint8_t* clip_scan = clip_span.data();
1287   for (int col = 0; col < pixel_count; col++) {
1288     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
1289       dest_scan++;
1290       continue;
1291     }
1292     int src_alpha = GetAlpha(mask_alpha, clip_scan, col);
1293     if (src_alpha) {
1294       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha);
1295     }
1296     dest_scan++;
1297   }
1298 }
1299 
CompositeRow_Argb2Argb_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)1300 void CompositeRow_Argb2Argb_RgbByteOrder(
1301     pdfium::span<uint8_t> dest_span,
1302     pdfium::span<const uint8_t> src_span,
1303     int pixel_count,
1304     BlendMode blend_type,
1305     pdfium::span<const uint8_t> clip_span) {
1306   uint8_t* dest_scan = dest_span.data();
1307   const uint8_t* src_scan = src_span.data();
1308   const uint8_t* clip_scan = clip_span.data();
1309   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
1310   int blended_colors[3];
1311   for (int col = 0; col < pixel_count; col++) {
1312     uint8_t back_alpha = dest_scan[3];
1313     if (back_alpha == 0) {
1314       if (clip_scan) {
1315         int src_alpha = clip_scan[col] * src_scan[3] / 255;
1316         ReverseCopy3Bytes(dest_scan, src_scan);
1317         dest_scan[3] = src_alpha;
1318       } else {
1319         FXARGB_RGBORDERCOPY(dest_scan, src_scan);
1320       }
1321       dest_scan += 4;
1322       src_scan += 4;
1323       continue;
1324     }
1325     uint8_t src_alpha = GetAlpha(src_scan[3], clip_scan, col);
1326     if (src_alpha == 0) {
1327       dest_scan += 4;
1328       src_scan += 4;
1329       continue;
1330     }
1331     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1332     dest_scan[3] = dest_alpha;
1333     int alpha_ratio = src_alpha * 255 / dest_alpha;
1334     if (bNonseparableBlend) {
1335       uint8_t dest_scan_o[3];
1336       ReverseCopy3Bytes(dest_scan_o, dest_scan);
1337       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
1338     }
1339     for (int color = 0; color < 3; color++) {
1340       int index = 2 - color;
1341       if (blend_type != BlendMode::kNormal) {
1342         int blended = bNonseparableBlend
1343                           ? blended_colors[color]
1344                           : Blend(blend_type, dest_scan[index], *src_scan);
1345         blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
1346         dest_scan[index] =
1347             FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
1348       } else {
1349         dest_scan[index] =
1350             FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio);
1351       }
1352       src_scan++;
1353     }
1354     dest_scan += 4;
1355     src_scan++;
1356   }
1357 }
1358 
CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int src_Bpp)1359 void CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(
1360     pdfium::span<uint8_t> dest_span,
1361     pdfium::span<const uint8_t> src_span,
1362     int width,
1363     BlendMode blend_type,
1364     int src_Bpp) {
1365   uint8_t* dest_scan = dest_span.data();
1366   const uint8_t* src_scan = src_span.data();
1367   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
1368   int src_gap = src_Bpp - 3;
1369   int blended_colors[3];
1370   for (int col = 0; col < width; col++) {
1371     uint8_t back_alpha = dest_scan[3];
1372     if (back_alpha == 0) {
1373       if (src_Bpp == 4) {
1374         FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
1375       } else {
1376         FXARGB_SETRGBORDERDIB(
1377             dest_scan, ArgbEncode(0xff, src_scan[2], src_scan[1], src_scan[0]));
1378       }
1379       dest_scan += 4;
1380       src_scan += src_Bpp;
1381       continue;
1382     }
1383     dest_scan[3] = 0xff;
1384     if (bNonseparableBlend) {
1385       uint8_t dest_scan_o[3];
1386       ReverseCopy3Bytes(dest_scan_o, dest_scan);
1387       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
1388     }
1389     for (int color = 0; color < 3; color++) {
1390       int index = 2 - color;
1391       int src_color = *src_scan;
1392       int blended = bNonseparableBlend
1393                         ? blended_colors[color]
1394                         : Blend(blend_type, dest_scan[index], src_color);
1395       dest_scan[index] = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
1396       src_scan++;
1397     }
1398     dest_scan += 4;
1399     src_scan += src_gap;
1400   }
1401 }
1402 
CompositeRow_Argb2Rgb_Blend_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int dest_Bpp,pdfium::span<const uint8_t> clip_span)1403 void CompositeRow_Argb2Rgb_Blend_RgbByteOrder(
1404     pdfium::span<uint8_t> dest_span,
1405     pdfium::span<const uint8_t> src_span,
1406     int width,
1407     BlendMode blend_type,
1408     int dest_Bpp,
1409     pdfium::span<const uint8_t> clip_span) {
1410   int blended_colors[3];
1411   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
1412   uint8_t* dest_scan = dest_span.data();
1413   const uint8_t* src_scan = src_span.data();
1414   const uint8_t* clip_scan = clip_span.data();
1415   for (int col = 0; col < width; col++) {
1416     uint8_t src_alpha;
1417     if (clip_scan) {
1418       src_alpha = src_scan[3] * (*clip_scan++) / 255;
1419     } else {
1420       src_alpha = src_scan[3];
1421     }
1422     if (src_alpha == 0) {
1423       dest_scan += dest_Bpp;
1424       src_scan += 4;
1425       continue;
1426     }
1427     if (bNonseparableBlend) {
1428       uint8_t dest_scan_o[3];
1429       ReverseCopy3Bytes(dest_scan_o, dest_scan);
1430       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
1431     }
1432     for (int color = 0; color < 3; color++) {
1433       int index = 2 - color;
1434       int back_color = dest_scan[index];
1435       int blended = bNonseparableBlend
1436                         ? blended_colors[color]
1437                         : Blend(blend_type, back_color, *src_scan);
1438       dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
1439       src_scan++;
1440     }
1441     dest_scan += dest_Bpp;
1442     src_scan++;
1443   }
1444 }
1445 
CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int src_Bpp)1446 void CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(
1447     pdfium::span<uint8_t> dest_span,
1448     pdfium::span<const uint8_t> src_span,
1449     int width,
1450     int src_Bpp) {
1451   uint8_t* dest_scan = dest_span.data();
1452   const uint8_t* src_scan = src_span.data();
1453   for (int col = 0; col < width; col++) {
1454     if (src_Bpp == 4) {
1455       FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
1456     } else {
1457       FXARGB_SETRGBORDERDIB(
1458           dest_scan, ArgbEncode(0xff, src_scan[2], src_scan[1], src_scan[0]));
1459     }
1460     dest_scan += 4;
1461     src_scan += src_Bpp;
1462   }
1463 }
1464 
CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int dest_Bpp,int src_Bpp)1465 void CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(
1466     pdfium::span<uint8_t> dest_span,
1467     pdfium::span<const uint8_t> src_span,
1468     int width,
1469     BlendMode blend_type,
1470     int dest_Bpp,
1471     int src_Bpp) {
1472   int blended_colors[3];
1473   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
1474   uint8_t* dest_scan = dest_span.data();
1475   const uint8_t* src_scan = src_span.data();
1476   int src_gap = src_Bpp - 3;
1477   for (int col = 0; col < width; col++) {
1478     if (bNonseparableBlend) {
1479       uint8_t dest_scan_o[3];
1480       ReverseCopy3Bytes(dest_scan_o, dest_scan);
1481       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
1482     }
1483     for (int color = 0; color < 3; color++) {
1484       int index = 2 - color;
1485       int back_color = dest_scan[index];
1486       int src_color = *src_scan;
1487       int blended = bNonseparableBlend
1488                         ? blended_colors[color]
1489                         : Blend(blend_type, back_color, src_color);
1490       dest_scan[index] = blended;
1491       src_scan++;
1492     }
1493     dest_scan += dest_Bpp;
1494     src_scan += src_gap;
1495   }
1496 }
1497 
CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int dest_Bpp,pdfium::span<const uint8_t> clip_span)1498 void CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(
1499     pdfium::span<uint8_t> dest_span,
1500     pdfium::span<const uint8_t> src_span,
1501     int width,
1502     int dest_Bpp,
1503     pdfium::span<const uint8_t> clip_span) {
1504   uint8_t* dest_scan = dest_span.data();
1505   const uint8_t* src_scan = src_span.data();
1506   const uint8_t* clip_scan = clip_span.data();
1507   for (int col = 0; col < width; col++) {
1508     uint8_t src_alpha;
1509     if (clip_scan) {
1510       src_alpha = src_scan[3] * (*clip_scan++) / 255;
1511     } else {
1512       src_alpha = src_scan[3];
1513     }
1514     if (src_alpha == 255) {
1515       ReverseCopy3Bytes(dest_scan, src_scan);
1516       dest_scan += dest_Bpp;
1517       src_scan += 4;
1518       continue;
1519     }
1520     if (src_alpha == 0) {
1521       dest_scan += dest_Bpp;
1522       src_scan += 4;
1523       continue;
1524     }
1525     for (int color = 0; color < 3; color++) {
1526       int index = 2 - color;
1527       dest_scan[index] =
1528           FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, src_alpha);
1529       src_scan++;
1530     }
1531     dest_scan += dest_Bpp;
1532     src_scan++;
1533   }
1534 }
1535 
CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int dest_Bpp,int src_Bpp)1536 void CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(
1537     pdfium::span<uint8_t> dest_span,
1538     pdfium::span<const uint8_t> src_span,
1539     int width,
1540     int dest_Bpp,
1541     int src_Bpp) {
1542   uint8_t* dest_scan = dest_span.data();
1543   const uint8_t* src_scan = src_span.data();
1544   for (int col = 0; col < width; col++) {
1545     ReverseCopy3Bytes(dest_scan, src_scan);
1546     dest_scan += dest_Bpp;
1547     src_scan += src_Bpp;
1548   }
1549 }
1550 
CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int src_Bpp,pdfium::span<const uint8_t> clip_span)1551 void CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(
1552     pdfium::span<uint8_t> dest_span,
1553     pdfium::span<const uint8_t> src_span,
1554     int width,
1555     BlendMode blend_type,
1556     int src_Bpp,
1557     pdfium::span<const uint8_t> clip_span) {
1558   uint8_t* dest_scan = dest_span.data();
1559   const uint8_t* src_scan = src_span.data();
1560   const uint8_t* clip_scan = clip_span.data();
1561   int blended_colors[3];
1562   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
1563   int src_gap = src_Bpp - 3;
1564   for (int col = 0; col < width; col++) {
1565     int src_alpha = *clip_scan++;
1566     uint8_t back_alpha = dest_scan[3];
1567     if (back_alpha == 0) {
1568       ReverseCopy3Bytes(dest_scan, src_scan);
1569       src_scan += src_Bpp;
1570       dest_scan += 4;
1571       continue;
1572     }
1573     if (src_alpha == 0) {
1574       dest_scan += 4;
1575       src_scan += src_Bpp;
1576       continue;
1577     }
1578     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1579     dest_scan[3] = dest_alpha;
1580     int alpha_ratio = src_alpha * 255 / dest_alpha;
1581     if (bNonseparableBlend) {
1582       uint8_t dest_scan_o[3];
1583       ReverseCopy3Bytes(dest_scan_o, dest_scan);
1584       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
1585     }
1586     for (int color = 0; color < 3; color++) {
1587       int index = 2 - color;
1588       int src_color = *src_scan;
1589       int blended = bNonseparableBlend
1590                         ? blended_colors[color]
1591                         : Blend(blend_type, dest_scan[index], src_color);
1592       blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
1593       dest_scan[index] =
1594           FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
1595       src_scan++;
1596     }
1597     dest_scan += 4;
1598     src_scan += src_gap;
1599   }
1600 }
1601 
CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,BlendMode blend_type,int dest_Bpp,int src_Bpp,pdfium::span<const uint8_t> clip_span)1602 void CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(
1603     pdfium::span<uint8_t> dest_span,
1604     pdfium::span<const uint8_t> src_span,
1605     int width,
1606     BlendMode blend_type,
1607     int dest_Bpp,
1608     int src_Bpp,
1609     pdfium::span<const uint8_t> clip_span) {
1610   uint8_t* dest_scan = dest_span.data();
1611   const uint8_t* src_scan = src_span.data();
1612   const uint8_t* clip_scan = clip_span.data();
1613   int blended_colors[3];
1614   bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
1615   int src_gap = src_Bpp - 3;
1616   for (int col = 0; col < width; col++) {
1617     uint8_t src_alpha = *clip_scan++;
1618     if (src_alpha == 0) {
1619       dest_scan += dest_Bpp;
1620       src_scan += src_Bpp;
1621       continue;
1622     }
1623     if (bNonseparableBlend) {
1624       uint8_t dest_scan_o[3];
1625       ReverseCopy3Bytes(dest_scan_o, dest_scan);
1626       RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
1627     }
1628     for (int color = 0; color < 3; color++) {
1629       int index = 2 - color;
1630       int src_color = *src_scan;
1631       int back_color = dest_scan[index];
1632       int blended = bNonseparableBlend
1633                         ? blended_colors[color]
1634                         : Blend(blend_type, back_color, src_color);
1635       dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
1636       src_scan++;
1637     }
1638     dest_scan += dest_Bpp;
1639     src_scan += src_gap;
1640   }
1641 }
1642 
CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int src_Bpp,pdfium::span<const uint8_t> clip_span)1643 void CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(
1644     pdfium::span<uint8_t> dest_span,
1645     pdfium::span<const uint8_t> src_span,
1646     int width,
1647     int src_Bpp,
1648     pdfium::span<const uint8_t> clip_span) {
1649   uint8_t* dest_scan = dest_span.data();
1650   const uint8_t* src_scan = src_span.data();
1651   const uint8_t* clip_scan = clip_span.data();
1652   int src_gap = src_Bpp - 3;
1653   for (int col = 0; col < width; col++) {
1654     int src_alpha = clip_scan[col];
1655     if (src_alpha == 255) {
1656       ReverseCopy3Bytes(dest_scan, src_scan);
1657       dest_scan[3] = 255;
1658       dest_scan += 4;
1659       src_scan += src_Bpp;
1660       continue;
1661     }
1662     if (src_alpha == 0) {
1663       dest_scan += 4;
1664       src_scan += src_Bpp;
1665       continue;
1666     }
1667     int back_alpha = dest_scan[3];
1668     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1669     dest_scan[3] = dest_alpha;
1670     int alpha_ratio = src_alpha * 255 / dest_alpha;
1671     for (int color = 0; color < 3; color++) {
1672       int index = 2 - color;
1673       dest_scan[index] =
1674           FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio);
1675       src_scan++;
1676     }
1677     dest_scan += 4;
1678     src_scan += src_gap;
1679   }
1680 }
1681 
CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,int dest_Bpp,int src_Bpp,pdfium::span<const uint8_t> clip_span)1682 void CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(
1683     pdfium::span<uint8_t> dest_span,
1684     pdfium::span<const uint8_t> src_span,
1685     int width,
1686     int dest_Bpp,
1687     int src_Bpp,
1688     pdfium::span<const uint8_t> clip_span) {
1689   uint8_t* dest_scan = dest_span.data();
1690   const uint8_t* src_scan = src_span.data();
1691   const uint8_t* clip_scan = clip_span.data();
1692   for (int col = 0; col < width; col++) {
1693     int src_alpha = clip_scan[col];
1694     if (src_alpha == 255) {
1695       ReverseCopy3Bytes(dest_scan, src_scan);
1696     } else if (src_alpha) {
1697       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], *src_scan, src_alpha);
1698       src_scan++;
1699       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], *src_scan, src_alpha);
1700       src_scan++;
1701       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], *src_scan, src_alpha);
1702       dest_scan += dest_Bpp;
1703       src_scan += src_Bpp - 2;
1704       continue;
1705     }
1706     dest_scan += dest_Bpp;
1707     src_scan += src_Bpp;
1708   }
1709 }
1710 
CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,const FX_ARGB * pPalette,int pixel_count,int DestBpp,pdfium::span<const uint8_t> clip_span)1711 void CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(
1712     pdfium::span<uint8_t> dest_span,
1713     pdfium::span<const uint8_t> src_span,
1714     const FX_ARGB* pPalette,
1715     int pixel_count,
1716     int DestBpp,
1717     pdfium::span<const uint8_t> clip_span) {
1718   uint8_t* dest_scan = dest_span.data();
1719   const uint8_t* src_scan = src_span.data();
1720   const uint8_t* clip_scan = clip_span.data();
1721   for (int col = 0; col < pixel_count; col++) {
1722     FX_ARGB argb = pPalette ? pPalette[*src_scan]
1723                             : ArgbEncode(0, *src_scan, *src_scan, *src_scan);
1724     int src_r = FXARGB_R(argb);
1725     int src_g = FXARGB_G(argb);
1726     int src_b = FXARGB_B(argb);
1727     if (clip_scan && clip_scan[col] < 255) {
1728       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
1729       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
1730       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
1731     } else {
1732       dest_scan[2] = src_b;
1733       dest_scan[1] = src_g;
1734       dest_scan[0] = src_r;
1735     }
1736     dest_scan += DestBpp;
1737     src_scan++;
1738   }
1739 }
1740 
CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int src_left,pdfium::span<const FX_ARGB> src_palette,int pixel_count,int DestBpp,pdfium::span<const uint8_t> clip_span)1741 void CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(
1742     pdfium::span<uint8_t> dest_span,
1743     pdfium::span<const uint8_t> src_span,
1744     int src_left,
1745     pdfium::span<const FX_ARGB> src_palette,
1746     int pixel_count,
1747     int DestBpp,
1748     pdfium::span<const uint8_t> clip_span) {
1749   uint8_t* dest_scan = dest_span.data();
1750   const uint8_t* src_scan = src_span.data();
1751   const uint8_t* clip_scan = clip_span.data();
1752   int reset_r;
1753   int reset_g;
1754   int reset_b;
1755   int set_r;
1756   int set_g;
1757   int set_b;
1758   if (!src_palette.empty()) {
1759     reset_r = FXARGB_R(src_palette[0]);
1760     reset_g = FXARGB_G(src_palette[0]);
1761     reset_b = FXARGB_B(src_palette[0]);
1762     set_r = FXARGB_R(src_palette[1]);
1763     set_g = FXARGB_G(src_palette[1]);
1764     set_b = FXARGB_B(src_palette[1]);
1765   } else {
1766     reset_r = reset_g = reset_b = 0;
1767     set_r = set_g = set_b = 255;
1768   }
1769   for (int col = 0; col < pixel_count; col++) {
1770     int src_r;
1771     int src_g;
1772     int src_b;
1773     if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
1774       src_r = set_r;
1775       src_g = set_g;
1776       src_b = set_b;
1777     } else {
1778       src_r = reset_r;
1779       src_g = reset_g;
1780       src_b = reset_b;
1781     }
1782     if (clip_scan && clip_scan[col] < 255) {
1783       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
1784       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
1785       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
1786     } else {
1787       dest_scan[2] = src_b;
1788       dest_scan[1] = src_g;
1789       dest_scan[0] = src_r;
1790     }
1791     dest_scan += DestBpp;
1792   }
1793 }
1794 
CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int width,const FX_ARGB * pPalette,pdfium::span<const uint8_t> clip_span)1795 void CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(
1796     pdfium::span<uint8_t> dest_span,
1797     pdfium::span<const uint8_t> src_span,
1798     int width,
1799     const FX_ARGB* pPalette,
1800     pdfium::span<const uint8_t> clip_span) {
1801   uint8_t* dest_scan = dest_span.data();
1802   const uint8_t* src_scan = src_span.data();
1803   const uint8_t* clip_scan = clip_span.data();
1804   for (int col = 0; col < width; col++) {
1805     int src_r;
1806     int src_g;
1807     int src_b;
1808     if (pPalette) {
1809       FX_ARGB argb = pPalette[*src_scan];
1810       src_r = FXARGB_R(argb);
1811       src_g = FXARGB_G(argb);
1812       src_b = FXARGB_B(argb);
1813     } else {
1814       src_r = src_g = src_b = *src_scan;
1815     }
1816     if (!clip_scan || clip_scan[col] == 255) {
1817       dest_scan[2] = src_b;
1818       dest_scan[1] = src_g;
1819       dest_scan[0] = src_r;
1820       dest_scan[3] = 255;
1821       src_scan++;
1822       dest_scan += 4;
1823       continue;
1824     }
1825     int src_alpha = clip_scan[col];
1826     if (src_alpha == 0) {
1827       dest_scan += 4;
1828       src_scan++;
1829       continue;
1830     }
1831     int back_alpha = dest_scan[3];
1832     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1833     dest_scan[3] = dest_alpha;
1834     int alpha_ratio = src_alpha * 255 / dest_alpha;
1835     dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
1836     dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
1837     dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
1838     dest_scan += 4;
1839     src_scan++;
1840   }
1841 }
1842 
CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int src_left,int width,pdfium::span<const FX_ARGB> src_palette,pdfium::span<const uint8_t> clip_span)1843 void CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(
1844     pdfium::span<uint8_t> dest_span,
1845     pdfium::span<const uint8_t> src_span,
1846     int src_left,
1847     int width,
1848     pdfium::span<const FX_ARGB> src_palette,
1849     pdfium::span<const uint8_t> clip_span) {
1850   uint8_t* dest_scan = dest_span.data();
1851   const uint8_t* src_scan = src_span.data();
1852   const uint8_t* clip_scan = clip_span.data();
1853   int reset_r;
1854   int reset_g;
1855   int reset_b;
1856   int set_r;
1857   int set_g;
1858   int set_b;
1859   if (!src_palette.empty()) {
1860     reset_r = FXARGB_R(src_palette[0]);
1861     reset_g = FXARGB_G(src_palette[0]);
1862     reset_b = FXARGB_B(src_palette[0]);
1863     set_r = FXARGB_R(src_palette[1]);
1864     set_g = FXARGB_G(src_palette[1]);
1865     set_b = FXARGB_B(src_palette[1]);
1866   } else {
1867     reset_r = reset_g = reset_b = 0;
1868     set_r = set_g = set_b = 255;
1869   }
1870   for (int col = 0; col < width; col++) {
1871     int src_r;
1872     int src_g;
1873     int src_b;
1874     if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
1875       src_r = set_r;
1876       src_g = set_g;
1877       src_b = set_b;
1878     } else {
1879       src_r = reset_r;
1880       src_g = reset_g;
1881       src_b = reset_b;
1882     }
1883     if (!clip_scan || clip_scan[col] == 255) {
1884       dest_scan[2] = src_b;
1885       dest_scan[1] = src_g;
1886       dest_scan[0] = src_r;
1887       dest_scan[3] = 255;
1888       dest_scan += 4;
1889       continue;
1890     }
1891     int src_alpha = clip_scan[col];
1892     if (src_alpha == 0) {
1893       dest_scan += 4;
1894       continue;
1895     }
1896     int back_alpha = dest_scan[3];
1897     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1898     dest_scan[3] = dest_alpha;
1899     int alpha_ratio = src_alpha * 255 / dest_alpha;
1900     dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
1901     dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
1902     dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
1903     dest_scan += 4;
1904   }
1905 }
1906 
CompositeRow_ByteMask2Argb_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_r,int src_g,int src_b,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)1907 void CompositeRow_ByteMask2Argb_RgbByteOrder(
1908     pdfium::span<uint8_t> dest_span,
1909     pdfium::span<const uint8_t> src_span,
1910     int mask_alpha,
1911     int src_r,
1912     int src_g,
1913     int src_b,
1914     int pixel_count,
1915     BlendMode blend_type,
1916     pdfium::span<const uint8_t> clip_span) {
1917   uint8_t* dest_scan = dest_span.data();
1918   const uint8_t* src_scan = src_span.data();
1919   const uint8_t* clip_scan = clip_span.data();
1920   for (int col = 0; col < pixel_count; col++) {
1921     int src_alpha = GetAlphaWithSrc(mask_alpha, clip_scan, src_scan, col);
1922     uint8_t back_alpha = dest_scan[3];
1923     if (back_alpha == 0) {
1924       FXARGB_SETRGBORDERDIB(dest_scan,
1925                             ArgbEncode(src_alpha, src_r, src_g, src_b));
1926       dest_scan += 4;
1927       continue;
1928     }
1929     if (src_alpha == 0) {
1930       dest_scan += 4;
1931       continue;
1932     }
1933     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1934     dest_scan[3] = dest_alpha;
1935     int alpha_ratio = src_alpha * 255 / dest_alpha;
1936     if (IsNonSeparableBlendMode(blend_type)) {
1937       int blended_colors[3];
1938       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
1939                          static_cast<uint8_t>(src_g),
1940                          static_cast<uint8_t>(src_r)};
1941       uint8_t dest_scan_o[3];
1942       ReverseCopy3Bytes(dest_scan_o, dest_scan);
1943       RGB_Blend(blend_type, scan, dest_scan_o, blended_colors);
1944       dest_scan[2] =
1945           FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
1946       dest_scan[1] =
1947           FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
1948       dest_scan[0] =
1949           FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
1950     } else if (blend_type != BlendMode::kNormal) {
1951       int blended = Blend(blend_type, dest_scan[2], src_b);
1952       blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
1953       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
1954       blended = Blend(blend_type, dest_scan[1], src_g);
1955       blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
1956       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
1957       blended = Blend(blend_type, dest_scan[0], src_r);
1958       blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
1959       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
1960     } else {
1961       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
1962       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
1963       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
1964     }
1965     dest_scan += 4;
1966   }
1967 }
1968 
CompositeRow_ByteMask2Rgb_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_r,int src_g,int src_b,int pixel_count,BlendMode blend_type,int Bpp,pdfium::span<const uint8_t> clip_span)1969 void CompositeRow_ByteMask2Rgb_RgbByteOrder(
1970     pdfium::span<uint8_t> dest_span,
1971     pdfium::span<const uint8_t> src_span,
1972     int mask_alpha,
1973     int src_r,
1974     int src_g,
1975     int src_b,
1976     int pixel_count,
1977     BlendMode blend_type,
1978     int Bpp,
1979     pdfium::span<const uint8_t> clip_span) {
1980   uint8_t* dest_scan = dest_span.data();
1981   const uint8_t* src_scan = src_span.data();
1982   const uint8_t* clip_scan = clip_span.data();
1983   for (int col = 0; col < pixel_count; col++) {
1984     int src_alpha = GetAlphaWithSrc(mask_alpha, clip_scan, src_scan, col);
1985     if (src_alpha == 0) {
1986       dest_scan += Bpp;
1987       continue;
1988     }
1989     if (IsNonSeparableBlendMode(blend_type)) {
1990       int blended_colors[3];
1991       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
1992                          static_cast<uint8_t>(src_g),
1993                          static_cast<uint8_t>(src_r)};
1994       uint8_t dest_scan_o[3];
1995       ReverseCopy3Bytes(dest_scan_o, dest_scan);
1996       RGB_Blend(blend_type, scan, dest_scan_o, blended_colors);
1997       dest_scan[2] =
1998           FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
1999       dest_scan[1] =
2000           FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
2001       dest_scan[0] =
2002           FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
2003     } else if (blend_type != BlendMode::kNormal) {
2004       int blended = Blend(blend_type, dest_scan[2], src_b);
2005       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha);
2006       blended = Blend(blend_type, dest_scan[1], src_g);
2007       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha);
2008       blended = Blend(blend_type, dest_scan[0], src_r);
2009       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha);
2010     } else {
2011       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha);
2012       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha);
2013       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha);
2014     }
2015     dest_scan += Bpp;
2016   }
2017 }
2018 
CompositeRow_BitMask2Argb_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_r,int src_g,int src_b,int src_left,int pixel_count,BlendMode blend_type,pdfium::span<const uint8_t> clip_span)2019 void CompositeRow_BitMask2Argb_RgbByteOrder(
2020     pdfium::span<uint8_t> dest_span,
2021     pdfium::span<const uint8_t> src_span,
2022     int mask_alpha,
2023     int src_r,
2024     int src_g,
2025     int src_b,
2026     int src_left,
2027     int pixel_count,
2028     BlendMode blend_type,
2029     pdfium::span<const uint8_t> clip_span) {
2030   uint8_t* dest_scan = dest_span.data();
2031   const uint8_t* src_scan = src_span.data();
2032   const uint8_t* clip_scan = clip_span.data();
2033   if (blend_type == BlendMode::kNormal && !clip_scan && mask_alpha == 255) {
2034     FX_ARGB argb = ArgbEncode(0xff, src_r, src_g, src_b);
2035     for (int col = 0; col < pixel_count; col++) {
2036       if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
2037         FXARGB_SETRGBORDERDIB(dest_scan, argb);
2038       }
2039       dest_scan += 4;
2040     }
2041     return;
2042   }
2043   for (int col = 0; col < pixel_count; col++) {
2044     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
2045       dest_scan += 4;
2046       continue;
2047     }
2048     int src_alpha = GetAlpha(mask_alpha, clip_scan, col);
2049     uint8_t back_alpha = dest_scan[3];
2050     if (back_alpha == 0) {
2051       FXARGB_SETRGBORDERDIB(dest_scan,
2052                             ArgbEncode(src_alpha, src_r, src_g, src_b));
2053       dest_scan += 4;
2054       continue;
2055     }
2056     uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
2057     dest_scan[3] = dest_alpha;
2058     int alpha_ratio = src_alpha * 255 / dest_alpha;
2059     if (IsNonSeparableBlendMode(blend_type)) {
2060       int blended_colors[3];
2061       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
2062                          static_cast<uint8_t>(src_g),
2063                          static_cast<uint8_t>(src_r)};
2064       uint8_t dest_scan_o[3];
2065       ReverseCopy3Bytes(dest_scan_o, dest_scan);
2066       RGB_Blend(blend_type, scan, dest_scan_o, blended_colors);
2067       dest_scan[2] =
2068           FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
2069       dest_scan[1] =
2070           FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
2071       dest_scan[0] =
2072           FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
2073     } else if (blend_type != BlendMode::kNormal) {
2074       int blended = Blend(blend_type, dest_scan[2], src_b);
2075       blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
2076       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
2077       blended = Blend(blend_type, dest_scan[1], src_g);
2078       blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
2079       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
2080       blended = Blend(blend_type, dest_scan[0], src_r);
2081       blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
2082       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
2083     } else {
2084       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
2085       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
2086       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
2087     }
2088     dest_scan += 4;
2089   }
2090 }
2091 
CompositeRow_BitMask2Rgb_RgbByteOrder(pdfium::span<uint8_t> dest_span,pdfium::span<const uint8_t> src_span,int mask_alpha,int src_r,int src_g,int src_b,int src_left,int pixel_count,BlendMode blend_type,int Bpp,pdfium::span<const uint8_t> clip_span)2092 void CompositeRow_BitMask2Rgb_RgbByteOrder(
2093     pdfium::span<uint8_t> dest_span,
2094     pdfium::span<const uint8_t> src_span,
2095     int mask_alpha,
2096     int src_r,
2097     int src_g,
2098     int src_b,
2099     int src_left,
2100     int pixel_count,
2101     BlendMode blend_type,
2102     int Bpp,
2103     pdfium::span<const uint8_t> clip_span) {
2104   uint8_t* dest_scan = dest_span.data();
2105   const uint8_t* src_scan = src_span.data();
2106   const uint8_t* clip_scan = clip_span.data();
2107   if (blend_type == BlendMode::kNormal && !clip_scan && mask_alpha == 255) {
2108     for (int col = 0; col < pixel_count; col++) {
2109       if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
2110         dest_scan[2] = src_b;
2111         dest_scan[1] = src_g;
2112         dest_scan[0] = src_r;
2113       }
2114       dest_scan += Bpp;
2115     }
2116     return;
2117   }
2118   for (int col = 0; col < pixel_count; col++) {
2119     if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
2120       dest_scan += Bpp;
2121       continue;
2122     }
2123     int src_alpha = GetAlpha(mask_alpha, clip_scan, col);
2124     if (src_alpha == 0) {
2125       dest_scan += Bpp;
2126       continue;
2127     }
2128     if (IsNonSeparableBlendMode(blend_type)) {
2129       int blended_colors[3];
2130       uint8_t scan[3] = {static_cast<uint8_t>(src_b),
2131                          static_cast<uint8_t>(src_g),
2132                          static_cast<uint8_t>(src_r)};
2133       uint8_t dest_scan_o[3];
2134       ReverseCopy3Bytes(dest_scan_o, dest_scan);
2135       RGB_Blend(blend_type, scan, dest_scan_o, blended_colors);
2136       dest_scan[2] =
2137           FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
2138       dest_scan[1] =
2139           FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
2140       dest_scan[0] =
2141           FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
2142     } else if (blend_type != BlendMode::kNormal) {
2143       int back_color = dest_scan[2];
2144       int blended = Blend(blend_type, back_color, src_b);
2145       dest_scan[2] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
2146       back_color = dest_scan[1];
2147       blended = Blend(blend_type, back_color, src_g);
2148       dest_scan[1] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
2149       back_color = dest_scan[0];
2150       blended = Blend(blend_type, back_color, src_r);
2151       dest_scan[0] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
2152     } else {
2153       dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha);
2154       dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha);
2155       dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha);
2156     }
2157     dest_scan += Bpp;
2158   }
2159 }
2160 
2161 }  // namespace
2162 
2163 CFX_ScanlineCompositor::CFX_ScanlineCompositor() = default;
2164 
2165 CFX_ScanlineCompositor::~CFX_ScanlineCompositor() = default;
2166 
Init(FXDIB_Format dest_format,FXDIB_Format src_format,pdfium::span<const uint32_t> src_palette,uint32_t mask_color,BlendMode blend_type,bool bClip,bool bRgbByteOrder)2167 bool CFX_ScanlineCompositor::Init(FXDIB_Format dest_format,
2168                                   FXDIB_Format src_format,
2169                                   pdfium::span<const uint32_t> src_palette,
2170                                   uint32_t mask_color,
2171                                   BlendMode blend_type,
2172                                   bool bClip,
2173                                   bool bRgbByteOrder) {
2174   m_SrcFormat = src_format;
2175   m_DestFormat = dest_format;
2176   m_BlendType = blend_type;
2177   m_bRgbByteOrder = bRgbByteOrder;
2178   m_bClip = bClip;
2179   if (m_DestFormat == FXDIB_Format::k1bppMask ||
2180       m_DestFormat == FXDIB_Format::k1bppRgb) {
2181     return false;
2182   }
2183 
2184   if (m_bRgbByteOrder && (m_DestFormat == FXDIB_Format::k8bppMask ||
2185                           m_DestFormat == FXDIB_Format::k8bppRgb)) {
2186     return false;
2187   }
2188 
2189   if (m_SrcFormat == FXDIB_Format::k1bppMask ||
2190       m_SrcFormat == FXDIB_Format::k8bppMask) {
2191     InitSourceMask(mask_color);
2192     return true;
2193   }
2194   if ((m_SrcFormat == FXDIB_Format::k1bppRgb ||
2195        m_SrcFormat == FXDIB_Format::k8bppRgb) &&
2196       m_DestFormat != FXDIB_Format::k8bppMask) {
2197     InitSourcePalette(src_palette);
2198   }
2199   return true;
2200 }
2201 
InitSourceMask(uint32_t mask_color)2202 void CFX_ScanlineCompositor::InitSourceMask(uint32_t mask_color) {
2203   m_MaskAlpha = FXARGB_A(mask_color);
2204   m_MaskRed = FXARGB_R(mask_color);
2205   m_MaskGreen = FXARGB_G(mask_color);
2206   m_MaskBlue = FXARGB_B(mask_color);
2207   if (m_DestFormat == FXDIB_Format::k8bppMask)
2208     return;
2209 
2210   if (m_DestFormat == FXDIB_Format::k8bppRgb)
2211     m_MaskRed = FXRGB2GRAY(m_MaskRed, m_MaskGreen, m_MaskBlue);
2212 }
2213 
InitSourcePalette(pdfium::span<const uint32_t> src_palette)2214 void CFX_ScanlineCompositor::InitSourcePalette(
2215     pdfium::span<const uint32_t> src_palette) {
2216   DCHECK_NE(m_DestFormat, FXDIB_Format::k8bppMask);
2217 
2218   m_SrcPalette.Reset();
2219   const bool bIsDestBpp8 = m_DestFormat == FXDIB_Format::k8bppRgb;
2220   const size_t pal_count = static_cast<size_t>(1)
2221                            << GetBppFromFormat(m_SrcFormat);
2222 
2223   if (!src_palette.empty()) {
2224     if (bIsDestBpp8) {
2225       pdfium::span<uint8_t> gray_pal = m_SrcPalette.Make8BitPalette(pal_count);
2226       for (size_t i = 0; i < pal_count; ++i) {
2227         FX_ARGB argb = src_palette[i];
2228         gray_pal[i] =
2229             FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
2230       }
2231       return;
2232     }
2233     pdfium::span<uint32_t> pPalette = m_SrcPalette.Make32BitPalette(pal_count);
2234     for (size_t i = 0; i < pal_count; ++i)
2235       pPalette[i] = src_palette[i];
2236     return;
2237   }
2238   if (bIsDestBpp8) {
2239     pdfium::span<uint8_t> gray_pal = m_SrcPalette.Make8BitPalette(pal_count);
2240     if (pal_count == 2) {
2241       gray_pal[0] = 0;
2242       gray_pal[1] = 255;
2243     } else {
2244       for (size_t i = 0; i < pal_count; ++i)
2245         gray_pal[i] = i;
2246     }
2247     return;
2248   }
2249   pdfium::span<uint32_t> pPalette = m_SrcPalette.Make32BitPalette(pal_count);
2250   if (pal_count == 2) {
2251     pPalette[0] = 0xff000000;
2252     pPalette[1] = 0xffffffff;
2253   } else {
2254     for (size_t i = 0; i < pal_count; ++i) {
2255       uint32_t v = static_cast<uint32_t>(i);
2256       pPalette[i] = ArgbEncode(0, v, v, v);
2257     }
2258   }
2259 }
2260 
CompositeRgbBitmapLine(pdfium::span<uint8_t> dest_scan,pdfium::span<const uint8_t> src_scan,int width,pdfium::span<const uint8_t> clip_scan) const2261 void CFX_ScanlineCompositor::CompositeRgbBitmapLine(
2262     pdfium::span<uint8_t> dest_scan,
2263     pdfium::span<const uint8_t> src_scan,
2264     int width,
2265     pdfium::span<const uint8_t> clip_scan) const {
2266   DCHECK(m_SrcFormat == FXDIB_Format::kRgb ||
2267          m_SrcFormat == FXDIB_Format::kRgb32 ||
2268          m_SrcFormat == FXDIB_Format::kArgb);
2269 
2270   int src_Bpp = GetCompsFromFormat(m_SrcFormat);
2271   int dest_Bpp = GetCompsFromFormat(m_DestFormat);
2272   if (m_bRgbByteOrder) {
2273     if (m_SrcFormat == FXDIB_Format::kArgb) {
2274       if (m_DestFormat == FXDIB_Format::kArgb) {
2275         CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width,
2276                                             m_BlendType, clip_scan);
2277         return;
2278       }
2279       if (m_BlendType == BlendMode::kNormal) {
2280         CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width,
2281                                                    dest_Bpp, clip_scan);
2282         return;
2283       }
2284       CompositeRow_Argb2Rgb_Blend_RgbByteOrder(
2285           dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan);
2286       return;
2287     }
2288 
2289     if (m_DestFormat == FXDIB_Format::kArgb) {
2290       if (m_BlendType == BlendMode::kNormal) {
2291         if (m_bClip) {
2292           CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(
2293               dest_scan, src_scan, width, src_Bpp, clip_scan);
2294           return;
2295         }
2296         CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan,
2297                                                           width, src_Bpp);
2298         return;
2299       }
2300       if (m_bClip) {
2301         CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(
2302             dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan);
2303         return;
2304       }
2305       CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(
2306           dest_scan, src_scan, width, m_BlendType, src_Bpp);
2307       return;
2308     }
2309 
2310     if (m_BlendType == BlendMode::kNormal) {
2311       if (m_bClip) {
2312         CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(
2313             dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan);
2314         return;
2315       }
2316       CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(
2317           dest_scan, src_scan, width, dest_Bpp, src_Bpp);
2318       return;
2319     }
2320     if (m_bClip) {
2321       CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(dest_scan, src_scan, width,
2322                                                    m_BlendType, dest_Bpp,
2323                                                    src_Bpp, clip_scan);
2324       return;
2325     }
2326     CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(
2327         dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp);
2328     return;
2329   }
2330 
2331   if (m_DestFormat == FXDIB_Format::k8bppMask) {
2332     if (m_SrcFormat == FXDIB_Format::kArgb) {
2333       CompositeRow_AlphaToMask(dest_scan, src_scan, width, clip_scan, 4);
2334     } else {
2335       CompositeRow_Rgb2Mask(dest_scan, width, clip_scan);
2336     }
2337     return;
2338   }
2339 
2340   if (m_DestFormat == FXDIB_Format::k8bppRgb) {
2341     if (m_SrcFormat == FXDIB_Format::kArgb) {
2342       CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType,
2343                              clip_scan);
2344     } else {
2345       CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType,
2346                             clip_scan);
2347     }
2348     return;
2349   }
2350 
2351   // TODO(thestig): Tighten this check.
2352   DCHECK_NE(GetBppFromFormat(m_DestFormat), 8);
2353 
2354   if (m_SrcFormat == FXDIB_Format::kArgb) {
2355     if (m_DestFormat == FXDIB_Format::kArgb) {
2356       CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType,
2357                              clip_scan);
2358       return;
2359     }
2360     if (m_BlendType == BlendMode::kNormal) {
2361       CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp,
2362                                     clip_scan);
2363       return;
2364     }
2365     CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType,
2366                                 dest_Bpp, clip_scan);
2367     return;
2368   }
2369 
2370   if (m_DestFormat == FXDIB_Format::kArgb) {
2371     if (m_BlendType == BlendMode::kNormal) {
2372       if (m_bClip) {
2373         CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp,
2374                                            clip_scan);
2375         return;
2376       }
2377       CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width, src_Bpp);
2378       return;
2379     }
2380     if (m_bClip) {
2381       CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width, m_BlendType,
2382                                        src_Bpp, clip_scan);
2383       return;
2384     }
2385     CompositeRow_Rgb2Argb_Blend_NoClip(dest_scan, src_scan, width, m_BlendType,
2386                                        src_Bpp);
2387     return;
2388   }
2389 
2390   if (m_BlendType == BlendMode::kNormal) {
2391     if (m_bClip) {
2392       CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp,
2393                                         src_Bpp, clip_scan);
2394       return;
2395     }
2396     CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width, dest_Bpp,
2397                                         src_Bpp);
2398     return;
2399   }
2400   if (m_bClip) {
2401     CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width, m_BlendType,
2402                                     dest_Bpp, src_Bpp, clip_scan);
2403     return;
2404   }
2405   CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width, m_BlendType,
2406                                     dest_Bpp, src_Bpp);
2407 }
2408 
CompositePalBitmapLine(pdfium::span<uint8_t> dest_scan,pdfium::span<const uint8_t> src_scan,int src_left,int width,pdfium::span<const uint8_t> clip_scan) const2409 void CFX_ScanlineCompositor::CompositePalBitmapLine(
2410     pdfium::span<uint8_t> dest_scan,
2411     pdfium::span<const uint8_t> src_scan,
2412     int src_left,
2413     int width,
2414     pdfium::span<const uint8_t> clip_scan) const {
2415   DCHECK(m_SrcFormat == FXDIB_Format::k1bppRgb ||
2416          m_SrcFormat == FXDIB_Format::k8bppRgb);
2417 
2418   if (m_bRgbByteOrder) {
2419     if (m_SrcFormat == FXDIB_Format::k1bppRgb) {
2420       if (m_DestFormat == FXDIB_Format::k8bppRgb) {
2421         return;
2422       }
2423       if (m_DestFormat == FXDIB_Format::kArgb) {
2424         CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(
2425             dest_scan, src_scan, src_left, width,
2426             m_SrcPalette.Get32BitPalette(), clip_scan);
2427       } else {
2428         CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(
2429             dest_scan, src_scan, src_left, m_SrcPalette.Get32BitPalette(),
2430             width, GetCompsFromFormat(m_DestFormat), clip_scan);
2431       }
2432     } else {
2433       if (m_DestFormat == FXDIB_Format::k8bppRgb) {
2434         return;
2435       }
2436       if (m_DestFormat == FXDIB_Format::kArgb) {
2437         CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(
2438             dest_scan, src_scan, width, m_SrcPalette.Get32BitPalette().data(),
2439             clip_scan);
2440       } else {
2441         CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(
2442             dest_scan, src_scan, m_SrcPalette.Get32BitPalette().data(), width,
2443             GetCompsFromFormat(m_DestFormat), clip_scan);
2444       }
2445     }
2446     return;
2447   }
2448 
2449   if (m_DestFormat == FXDIB_Format::k8bppMask) {
2450     CompositeRow_Rgb2Mask(dest_scan, width, clip_scan);
2451     return;
2452   }
2453 
2454   if (m_DestFormat == FXDIB_Format::k8bppRgb) {
2455     if (m_SrcFormat == FXDIB_Format::k1bppRgb) {
2456       CompositeRow_1bppPal2Gray(dest_scan, src_scan, src_left,
2457                                 m_SrcPalette.Get8BitPalette(), width,
2458                                 m_BlendType, clip_scan);
2459       return;
2460     }
2461     CompositeRow_8bppPal2Gray(dest_scan, src_scan,
2462                               m_SrcPalette.Get8BitPalette(), width, m_BlendType,
2463                               clip_scan);
2464     return;
2465   }
2466 
2467   // TODO(thestig): Tighten this check.
2468   DCHECK_NE(GetBppFromFormat(m_DestFormat), 8);
2469 
2470   if (m_DestFormat == FXDIB_Format::kArgb) {
2471     if (m_SrcFormat == FXDIB_Format::k1bppRgb) {
2472       CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width,
2473                                         m_SrcPalette.Get32BitPalette(),
2474                                         clip_scan);
2475       return;
2476     }
2477     CompositeRow_8bppRgb2Argb_NoBlend(
2478         dest_scan, src_scan, width, m_SrcPalette.Get32BitPalette(), clip_scan);
2479     return;
2480   }
2481 
2482   if (m_SrcFormat == FXDIB_Format::k8bppRgb) {
2483     CompositeRow_8bppRgb2Rgb_NoBlend(
2484         dest_scan, src_scan, m_SrcPalette.Get32BitPalette(), width,
2485         GetCompsFromFormat(m_DestFormat), clip_scan);
2486     return;
2487   }
2488 
2489   CompositeRow_1bppRgb2Rgb_NoBlend(dest_scan, src_scan, src_left,
2490                                    m_SrcPalette.Get32BitPalette(), width,
2491                                    GetCompsFromFormat(m_DestFormat), clip_scan);
2492 }
2493 
CompositeByteMaskLine(pdfium::span<uint8_t> dest_scan,pdfium::span<const uint8_t> src_scan,int width,pdfium::span<const uint8_t> clip_scan) const2494 void CFX_ScanlineCompositor::CompositeByteMaskLine(
2495     pdfium::span<uint8_t> dest_scan,
2496     pdfium::span<const uint8_t> src_scan,
2497     int width,
2498     pdfium::span<const uint8_t> clip_scan) const {
2499   if (m_DestFormat == FXDIB_Format::k8bppMask) {
2500     CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width,
2501                                clip_scan);
2502     return;
2503   }
2504   if (m_DestFormat == FXDIB_Format::k8bppRgb) {
2505     CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
2506                                width, clip_scan);
2507     return;
2508   }
2509 
2510   // TODO(thestig): Tighten this check.
2511   DCHECK_NE(GetBppFromFormat(m_DestFormat), 8);
2512 
2513   if (m_bRgbByteOrder) {
2514     if (m_DestFormat == FXDIB_Format::kArgb) {
2515       CompositeRow_ByteMask2Argb_RgbByteOrder(
2516           dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
2517           width, m_BlendType, clip_scan);
2518     } else {
2519       CompositeRow_ByteMask2Rgb_RgbByteOrder(
2520           dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
2521           width, m_BlendType, GetCompsFromFormat(m_DestFormat), clip_scan);
2522     }
2523     return;
2524   }
2525 
2526   if (m_DestFormat == FXDIB_Format::kArgb) {
2527     CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
2528                                m_MaskGreen, m_MaskBlue, width, m_BlendType,
2529                                clip_scan);
2530     return;
2531   }
2532 
2533   if (m_DestFormat == FXDIB_Format::kRgb ||
2534       m_DestFormat == FXDIB_Format::kRgb32) {
2535     CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
2536                               m_MaskGreen, m_MaskBlue, width, m_BlendType,
2537                               GetCompsFromFormat(m_DestFormat), clip_scan);
2538     return;
2539   }
2540 
2541   // TODO(thestig): Is this line reachable?
2542 }
2543 
CompositeBitMaskLine(pdfium::span<uint8_t> dest_scan,pdfium::span<const uint8_t> src_scan,int src_left,int width,pdfium::span<const uint8_t> clip_scan) const2544 void CFX_ScanlineCompositor::CompositeBitMaskLine(
2545     pdfium::span<uint8_t> dest_scan,
2546     pdfium::span<const uint8_t> src_scan,
2547     int src_left,
2548     int width,
2549     pdfium::span<const uint8_t> clip_scan) const {
2550   if (m_DestFormat == FXDIB_Format::k8bppMask) {
2551     CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left, width,
2552                               clip_scan);
2553     return;
2554   }
2555 
2556   if (m_DestFormat == FXDIB_Format::k8bppRgb) {
2557     CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
2558                               src_left, width, clip_scan);
2559     return;
2560   }
2561 
2562   // TODO(thestig): Tighten this check.
2563   DCHECK_NE(GetBppFromFormat(m_DestFormat), 8);
2564 
2565   if (m_bRgbByteOrder) {
2566     if (m_DestFormat == FXDIB_Format::kArgb) {
2567       CompositeRow_BitMask2Argb_RgbByteOrder(
2568           dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
2569           src_left, width, m_BlendType, clip_scan);
2570     } else {
2571       CompositeRow_BitMask2Rgb_RgbByteOrder(
2572           dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
2573           src_left, width, m_BlendType, GetCompsFromFormat(m_DestFormat),
2574           clip_scan);
2575     }
2576     return;
2577   }
2578 
2579   if (m_DestFormat == FXDIB_Format::kArgb) {
2580     CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
2581                               m_MaskGreen, m_MaskBlue, src_left, width,
2582                               m_BlendType, clip_scan);
2583     return;
2584   }
2585 
2586   if (m_DestFormat == FXDIB_Format::kRgb ||
2587       m_DestFormat == FXDIB_Format::kRgb32) {
2588     CompositeRow_BitMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
2589                              m_MaskGreen, m_MaskBlue, src_left, width,
2590                              m_BlendType, GetCompsFromFormat(m_DestFormat),
2591                              clip_scan);
2592     return;
2593   }
2594 
2595   // TODO(thestig): Is this line reachable?
2596 }
2597 
2598 CFX_ScanlineCompositor::Palette::Palette() = default;
2599 
2600 CFX_ScanlineCompositor::Palette::~Palette() = default;
2601 
Reset()2602 void CFX_ScanlineCompositor::Palette::Reset() {
2603   m_Width = 0;
2604   m_nElements = 0;
2605   m_pData.reset();
2606 }
2607 
Make8BitPalette(size_t nElements)2608 pdfium::span<uint8_t> CFX_ScanlineCompositor::Palette::Make8BitPalette(
2609     size_t nElements) {
2610   m_Width = sizeof(uint8_t);
2611   m_nElements = nElements;
2612   m_pData.reset(reinterpret_cast<uint32_t*>(FX_Alloc(uint8_t, m_nElements)));
2613   return {reinterpret_cast<uint8_t*>(m_pData.get()), m_nElements};
2614 }
2615 
Make32BitPalette(size_t nElements)2616 pdfium::span<uint32_t> CFX_ScanlineCompositor::Palette::Make32BitPalette(
2617     size_t nElements) {
2618   m_Width = sizeof(uint32_t);
2619   m_nElements = nElements;
2620   m_pData.reset(FX_Alloc(uint32_t, m_nElements));
2621   return {m_pData.get(), m_nElements};
2622 }
2623 
Get8BitPalette() const2624 pdfium::span<const uint8_t> CFX_ScanlineCompositor::Palette::Get8BitPalette()
2625     const {
2626   CHECK(!m_pData || m_Width == sizeof(uint8_t));
2627   return {reinterpret_cast<const uint8_t*>(m_pData.get()), m_nElements};
2628 }
2629 
Get32BitPalette() const2630 pdfium::span<const uint32_t> CFX_ScanlineCompositor::Palette::Get32BitPalette()
2631     const {
2632   CHECK(!m_pData || m_Width == sizeof(uint32_t));
2633   return {m_pData.get(), m_nElements};
2634 }
2635