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