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