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