Remove UNSAFE_TODO() from RgbByteOrderCompositeRect()
Consistently use spans. Add a templated DoAlphaMerge() helper to work
with both FX_RGBA_STRUCT and FX_RGB_STRUCT.
Change-Id: Idb9c004ea7dc3c7be5a5b90b9f70485bf38be0c4
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/121221
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/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp
index 9f8396f..e940c82 100644
--- a/core/fxge/agg/fx_agg_driver.cpp
+++ b/core/fxge/agg/fx_agg_driver.cpp
@@ -20,6 +20,7 @@
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/notreached.h"
#include "core/fxcrt/span.h"
+#include "core/fxcrt/stl_util.h"
#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "core/fxge/cfx_cliprgn.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
@@ -57,96 +58,92 @@
std::clamp(pos.y, -kMaxPos, kMaxPos));
}
-void RgbByteOrderCompositeRect(const RetainPtr<CFX_DIBitmap>& pBitmap,
+template <typename T>
+void DoAlphaMerge(T& pixel, int src_r, int src_g, int src_b, int src_alpha) {
+ pixel.red = FXDIB_ALPHA_MERGE(pixel.red, src_r, src_alpha);
+ pixel.green = FXDIB_ALPHA_MERGE(pixel.green, src_g, src_alpha);
+ pixel.blue = FXDIB_ALPHA_MERGE(pixel.blue, src_b, src_alpha);
+}
+
+void RgbByteOrderCompositeRect(const RetainPtr<CFX_DIBitmap>& bitmap,
int left,
int top,
int width,
int height,
- FX_ARGB argb) {
- int src_alpha = FXARGB_A(argb);
- if (src_alpha == 0)
+ FX_ARGB src_argb) {
+ int src_alpha = FXARGB_A(src_argb);
+ if (src_alpha == 0) {
return;
+ }
FX_RECT rect(left, top, left + width, top + height);
- rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
+ rect.Intersect(0, 0, bitmap->GetWidth(), bitmap->GetHeight());
width = rect.Width();
- int src_r = FXARGB_R(argb);
- int src_g = FXARGB_G(argb);
- int src_b = FXARGB_B(argb);
- int Bpp = pBitmap->GetBPP() / 8;
- int dib_argb = FXARGB_TOBGRORDERDIB(argb);
- pdfium::span<uint8_t> pBuffer = pBitmap->GetWritableBuffer();
+ const int src_r = FXARGB_R(src_argb);
+ const int src_g = FXARGB_G(src_argb);
+ const int src_b = FXARGB_B(src_argb);
+ const int Bpp = bitmap->GetBPP() / 8;
if (src_alpha == 255) {
if (Bpp == 4) {
+ const int src_abgr = FXARGB_TOBGRORDERDIB(src_argb);
for (int row = rect.top; row < rect.bottom; row++) {
- UNSAFE_TODO({
- uint8_t* dest_scan =
- pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp)
- .data();
- std::fill_n(reinterpret_cast<uint32_t*>(dest_scan), width, dib_argb);
- });
+ auto dest_row_span = bitmap->GetWritableScanlineAs<uint32_t>(row);
+ fxcrt::Fill(dest_row_span.subspan(rect.left, width), src_abgr);
}
return;
}
for (int row = rect.top; row < rect.bottom; row++) {
- UNSAFE_TODO({
- uint8_t* dest_scan =
- pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data();
- for (int col = 0; col < width; col++) {
- *dest_scan++ = src_r;
- *dest_scan++ = src_g;
- *dest_scan++ = src_b;
- }
- });
+ auto dest_row_span =
+ bitmap->GetWritableScanlineAs<FX_RGB_STRUCT<uint8_t>>(row);
+ for (auto& rgb : dest_row_span.subspan(rect.left, width)) {
+ rgb.red = src_r;
+ rgb.green = src_g;
+ rgb.blue = src_b;
+ }
}
return;
}
- if (pBitmap->IsAlphaFormat()) {
+ if (bitmap->IsAlphaFormat()) {
for (int row = rect.top; row < rect.bottom; row++) {
- UNSAFE_TODO({
- uint8_t* dest_scan =
- pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data();
- for (int col = 0; col < width; col++) {
- uint8_t back_alpha = dest_scan[3];
- if (back_alpha == 0) {
- FXARGB_SetRGBOrderDIB(dest_scan, argb);
- dest_scan += 4;
- continue;
- }
- uint8_t dest_alpha =
- back_alpha + src_alpha - back_alpha * src_alpha / 255;
- dest_scan[3] = dest_alpha;
- int alpha_ratio = src_alpha * 255 / dest_alpha;
- *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
- dest_scan++;
- *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
- dest_scan++;
- *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
- dest_scan += 2;
+ auto dest_row_span =
+ bitmap->GetWritableScanlineAs<FX_RGBA_STRUCT<uint8_t>>(row);
+ for (auto& rgba : dest_row_span.subspan(rect.left, width)) {
+ if (rgba.alpha == 0) {
+ rgba.red = src_r;
+ rgba.green = src_g;
+ rgba.blue = src_b;
+ rgba.alpha = src_alpha;
+ continue;
}
- });
+
+ const uint8_t dest_alpha =
+ rgba.alpha + src_alpha - rgba.alpha * src_alpha / 255;
+ const int alpha_ratio = src_alpha * 255 / dest_alpha;
+ DoAlphaMerge(rgba, src_r, src_g, src_b, alpha_ratio);
+ }
+ }
+ return;
+ }
+
+ if (Bpp == 4) {
+ for (int row = rect.top; row < rect.bottom; row++) {
+ auto dest_row_span =
+ bitmap->GetWritableScanlineAs<FX_RGBA_STRUCT<uint8_t>>(row);
+ for (auto& rgba : dest_row_span.subspan(rect.left, width)) {
+ DoAlphaMerge(rgba, src_r, src_g, src_b, src_alpha);
+ }
}
return;
}
for (int row = rect.top; row < rect.bottom; row++) {
- UNSAFE_TODO({
- uint8_t* dest_scan =
- pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data();
- for (int col = 0; col < width; col++) {
- *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
- dest_scan++;
- *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
- dest_scan++;
- *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
- dest_scan++;
- if (Bpp == 4) {
- dest_scan++;
- }
- }
- });
+ auto dest_row_span =
+ bitmap->GetWritableScanlineAs<FX_RGB_STRUCT<uint8_t>>(row);
+ for (auto& rgb : dest_row_span.subspan(rect.left, width)) {
+ DoAlphaMerge(rgb, src_r, src_g, src_b, src_alpha);
+ }
}
}