Get rid of UNSAFE_TODOs in CompositeRow_Argb2Rgb* functions
Use Zip() and color structs instead. CompositeRow_Foo_RgbByteOrder() can
be combined with CompositeRow_Foo(), as the functions are now templated
and can take both RGB and BGR color struct types in the output param.
Bug: 42271176
Change-Id: I67086142a1078287739aa3456f184e87a11a6cf5
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/123073
Reviewed-by: Tom Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxge/dib/cfx_scanlinecompositor.cpp b/core/fxge/dib/cfx_scanlinecompositor.cpp
index a12aba0..6ee6d70 100644
--- a/core/fxge/dib/cfx_scanlinecompositor.cpp
+++ b/core/fxge/dib/cfx_scanlinecompositor.cpp
@@ -13,7 +13,9 @@
#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/notreached.h"
+#include "core/fxcrt/span_util.h"
#include "core/fxcrt/stl_util.h"
+#include "core/fxcrt/zip.h"
#include "core/fxge/dib/blend.h"
#include "core/fxge/dib/fx_dib.h"
@@ -133,6 +135,13 @@
return result / 255;
}
+template <typename T, typename U>
+void AlphaMerge(const T& input, U& output, uint8_t alpha) {
+ output.blue = FXDIB_ALPHA_MERGE(output.blue, input.blue, alpha);
+ output.green = FXDIB_ALPHA_MERGE(output.green, input.green, alpha);
+ output.red = FXDIB_ALPHA_MERGE(output.red, input.red, alpha);
+}
+
void CompositeRow_AlphaToMask(pdfium::span<uint8_t> dest_span,
pdfium::span<const uint8_t> src_span,
int pixel_count,
@@ -459,86 +468,106 @@
});
}
-void CompositeRow_Argb2Rgb_Blend(pdfium::span<uint8_t> dest_span,
- pdfium::span<const uint8_t> src_span,
- int width,
- BlendMode blend_type,
- int dest_Bpp,
- pdfium::span<const uint8_t> clip_span) {
- uint8_t* dest_scan = dest_span.data();
- const uint8_t* src_scan = src_span.data();
- const uint8_t* clip_scan = clip_span.data();
- int blended_colors[3];
- bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
- int dest_gap = dest_Bpp - 3;
- UNSAFE_TODO({
- for (int col = 0; col < width; col++) {
- uint8_t src_alpha;
- if (clip_scan) {
- src_alpha = src_scan[3] * (*clip_scan++) / 255;
- } else {
- src_alpha = src_scan[3];
- }
- if (src_alpha == 0) {
- dest_scan += dest_Bpp;
- src_scan += 4;
- continue;
- }
- if (bNonseparableBlend) {
- RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
- }
- for (int color = 0; color < 3; color++) {
- int back_color = *dest_scan;
- int blended = bNonseparableBlend
- ? blended_colors[color]
- : Blend(blend_type, back_color, *src_scan);
- *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
- dest_scan++;
- src_scan++;
- }
- dest_scan += dest_gap;
- src_scan++;
- }
- });
+template <typename DestPixelStruct>
+void CompositePixelArgb2RgbNonSeparableBlend(
+ const FX_BGRA_STRUCT<uint8_t>& input,
+ uint8_t clip,
+ DestPixelStruct& output,
+ BlendMode blend_type) {
+ const uint8_t src_alpha = input.alpha * clip / 255;
+ if (src_alpha == 0) {
+ return;
+ }
+
+ FX_RGB_STRUCT<int> blended_color = RgbBlend(blend_type, input, output);
+ AlphaMerge(blended_color, output, src_alpha);
}
-void CompositeRow_Argb2Rgb_NoBlend(pdfium::span<uint8_t> dest_span,
- pdfium::span<const uint8_t> src_span,
- int width,
- int dest_Bpp,
- pdfium::span<const uint8_t> clip_span) {
- uint8_t* dest_scan = dest_span.data();
- const uint8_t* src_scan = src_span.data();
- const uint8_t* clip_scan = clip_span.data();
- int dest_gap = dest_Bpp - 3;
- UNSAFE_TODO({
- for (int col = 0; col < width; col++) {
- uint8_t src_alpha;
- if (clip_scan) {
- src_alpha = src_scan[3] * (*clip_scan++) / 255;
- } else {
- src_alpha = src_scan[3];
+template <typename DestPixelStruct>
+void CompositePixelArgb2RgbBlend(const FX_BGRA_STRUCT<uint8_t>& input,
+ uint8_t clip,
+ DestPixelStruct& output,
+ BlendMode blend_type) {
+ const uint8_t src_alpha = input.alpha * clip / 255;
+ if (src_alpha == 0) {
+ return;
+ }
+
+ FX_RGB_STRUCT<int> blended_color = {
+ .red = Blend(blend_type, output.red, input.red),
+ .green = Blend(blend_type, output.green, input.green),
+ .blue = Blend(blend_type, output.blue, input.blue),
+ };
+ AlphaMerge(blended_color, output, src_alpha);
+}
+
+template <typename DestPixelStruct>
+void CompositePixelArgb2RgbNoBlend(const FX_BGRA_STRUCT<uint8_t>& input,
+ uint8_t clip,
+ DestPixelStruct& output) {
+ const uint8_t src_alpha = input.alpha * clip / 255;
+ if (src_alpha == 255) {
+ output.blue = input.blue;
+ output.green = input.green;
+ output.red = input.red;
+ return;
+ }
+ if (src_alpha == 0) {
+ return;
+ }
+ AlphaMerge(input, output, src_alpha);
+}
+
+template <typename DestPixelStruct>
+void CompositeRowArgb2RgbBlend(
+ pdfium::span<const FX_BGRA_STRUCT<uint8_t>> src_span,
+ pdfium::span<const uint8_t> clip_span,
+ pdfium::span<DestPixelStruct> dest_span,
+ BlendMode blend_type) {
+ const bool non_separable_blend = IsNonSeparableBlendMode(blend_type);
+ if (clip_span.empty()) {
+ if (non_separable_blend) {
+ for (auto [input, output] : fxcrt::Zip(src_span, dest_span)) {
+ CompositePixelArgb2RgbNonSeparableBlend(input, /*clip=*/255, output,
+ blend_type);
}
- if (src_alpha == 255) {
- FXSYS_memcpy(dest_scan, src_scan, 3);
- dest_scan += dest_Bpp;
- src_scan += 4;
- continue;
- }
- if (src_alpha == 0) {
- dest_scan += dest_Bpp;
- src_scan += 4;
- continue;
- }
- for (int color = 0; color < 3; color++) {
- *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
- dest_scan++;
- src_scan++;
- }
- dest_scan += dest_gap;
- src_scan++;
+ return;
}
- });
+ for (auto [input, output] : fxcrt::Zip(src_span, dest_span)) {
+ CompositePixelArgb2RgbBlend(input, /*clip=*/255, output, blend_type);
+ }
+ return;
+ }
+
+ if (non_separable_blend) {
+ for (auto [input, clip, output] :
+ fxcrt::Zip(src_span, clip_span, dest_span)) {
+ CompositePixelArgb2RgbNonSeparableBlend(input, clip, output, blend_type);
+ }
+ return;
+ }
+ for (auto [input, clip, output] :
+ fxcrt::Zip(src_span, clip_span, dest_span)) {
+ CompositePixelArgb2RgbBlend(input, clip, output, blend_type);
+ }
+}
+
+template <typename DestPixelStruct>
+void CompositeRowArgb2RgbNoBlend(
+ pdfium::span<const FX_BGRA_STRUCT<uint8_t>> src_span,
+ pdfium::span<const uint8_t> clip_span,
+ pdfium::span<DestPixelStruct> dest_span) {
+ if (clip_span.empty()) {
+ for (auto [input, output] : fxcrt::Zip(src_span, dest_span)) {
+ CompositePixelArgb2RgbNoBlend(input, /*clip=*/255, output);
+ }
+ return;
+ }
+
+ for (auto [input, clip, output] :
+ fxcrt::Zip(src_span, clip_span, dest_span)) {
+ CompositePixelArgb2RgbNoBlend(input, clip, output);
+ }
}
void CompositeRow_Rgb2Rgb_Blend_NoClip(pdfium::span<uint8_t> dest_span,
@@ -1417,51 +1446,6 @@
});
}
-void CompositeRow_Argb2Rgb_Blend_RgbByteOrder(
- pdfium::span<uint8_t> dest_span,
- pdfium::span<const uint8_t> src_span,
- int width,
- BlendMode blend_type,
- int dest_Bpp,
- pdfium::span<const uint8_t> clip_span) {
- int blended_colors[3];
- bool bNonseparableBlend = IsNonSeparableBlendMode(blend_type);
- uint8_t* dest_scan = dest_span.data();
- const uint8_t* src_scan = src_span.data();
- const uint8_t* clip_scan = clip_span.data();
- UNSAFE_TODO({
- for (int col = 0; col < width; col++) {
- uint8_t src_alpha;
- if (clip_scan) {
- src_alpha = src_scan[3] * (*clip_scan++) / 255;
- } else {
- src_alpha = src_scan[3];
- }
- if (src_alpha == 0) {
- dest_scan += dest_Bpp;
- src_scan += 4;
- continue;
- }
- if (bNonseparableBlend) {
- uint8_t dest_scan_o[3];
- ReverseCopy3Bytes(dest_scan_o, dest_scan);
- RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
- }
- for (int color = 0; color < 3; color++) {
- int index = 2 - color;
- int back_color = dest_scan[index];
- int blended = bNonseparableBlend
- ? blended_colors[color]
- : Blend(blend_type, back_color, *src_scan);
- dest_scan[index] = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
- src_scan++;
- }
- dest_scan += dest_Bpp;
- src_scan++;
- }
- });
-}
-
void CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(
pdfium::span<uint8_t> dest_span,
pdfium::span<const uint8_t> src_span,
@@ -1518,46 +1502,6 @@
});
}
-void CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(
- pdfium::span<uint8_t> dest_span,
- pdfium::span<const uint8_t> src_span,
- int width,
- int dest_Bpp,
- pdfium::span<const uint8_t> clip_span) {
- uint8_t* dest_scan = dest_span.data();
- const uint8_t* src_scan = src_span.data();
- const uint8_t* clip_scan = clip_span.data();
- UNSAFE_TODO({
- for (int col = 0; col < width; col++) {
- uint8_t src_alpha;
- if (clip_scan) {
- src_alpha = src_scan[3] * (*clip_scan++) / 255;
- } else {
- src_alpha = src_scan[3];
- }
- if (src_alpha == 255) {
- ReverseCopy3Bytes(dest_scan, src_scan);
- dest_scan += dest_Bpp;
- src_scan += 4;
- continue;
- }
- if (src_alpha == 0) {
- dest_scan += dest_Bpp;
- src_scan += 4;
- continue;
- }
- for (int color = 0; color < 3; color++) {
- int index = 2 - color;
- dest_scan[index] =
- FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, src_alpha);
- src_scan++;
- }
- dest_scan += dest_Bpp;
- src_scan++;
- }
- });
-}
-
void CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(
pdfium::span<uint8_t> dest_span,
pdfium::span<const uint8_t> src_span,
@@ -2473,27 +2417,52 @@
CompositeRow_AlphaToMask(dest_scan, src_scan, width, clip_scan, 4);
return;
}
- case FXDIB_Format::kRgb:
- case FXDIB_Format::kRgb32: {
- const int dest_Bpp = GetCompsFromFormat(m_DestFormat);
+ case FXDIB_Format::kRgb: {
+ auto src_span =
+ fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_scan)
+ .first(width);
if (m_bRgbByteOrder) {
+ auto dest_span =
+ fxcrt::reinterpret_span<FX_RGB_STRUCT<uint8_t>>(dest_scan);
if (m_BlendType == BlendMode::kNormal) {
- CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width,
- dest_Bpp, clip_scan);
+ CompositeRowArgb2RgbNoBlend(src_span, clip_scan, dest_span);
return;
}
- CompositeRow_Argb2Rgb_Blend_RgbByteOrder(
- dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan);
+ CompositeRowArgb2RgbBlend(src_span, clip_scan, dest_span, m_BlendType);
return;
}
+ auto dest_span =
+ fxcrt::reinterpret_span<FX_BGR_STRUCT<uint8_t>>(dest_scan);
if (m_BlendType == BlendMode::kNormal) {
- CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp,
- clip_scan);
+ CompositeRowArgb2RgbNoBlend(src_span, clip_scan, dest_span);
return;
}
- CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType,
- dest_Bpp, clip_scan);
+ CompositeRowArgb2RgbBlend(src_span, clip_scan, dest_span, m_BlendType);
+ return;
+ }
+ case FXDIB_Format::kRgb32: {
+ auto src_span =
+ fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_scan)
+ .first(width);
+ if (m_bRgbByteOrder) {
+ auto dest_span =
+ fxcrt::reinterpret_span<FX_RGBA_STRUCT<uint8_t>>(dest_scan);
+ if (m_BlendType == BlendMode::kNormal) {
+ CompositeRowArgb2RgbNoBlend(src_span, clip_scan, dest_span);
+ return;
+ }
+ CompositeRowArgb2RgbBlend(src_span, clip_scan, dest_span, m_BlendType);
+ return;
+ }
+
+ auto dest_span =
+ fxcrt::reinterpret_span<FX_BGRA_STRUCT<uint8_t>>(dest_scan);
+ if (m_BlendType == BlendMode::kNormal) {
+ CompositeRowArgb2RgbNoBlend(src_span, clip_scan, dest_span);
+ return;
+ }
+ CompositeRowArgb2RgbBlend(src_span, clip_scan, dest_span, m_BlendType);
return;
}
case FXDIB_Format::kArgb: {