Take advantage of spans more in PNG_Predictor()
- Use span sizes as indicators of how much data is remaining, instead of
keeping track of it separately.
- Adjust spans so they do not have to be accessed at an offset, like in
PNG_PredictLine().
- Use spancpy() in the default case, and remove the special 0 value
handling, like in PNG_PredictLine().
Change-Id: Ibf8e7cd00dddc89fd46d029fd1adad86967e78fe
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119315
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcodec/flate/flatemodule.cpp b/core/fxcodec/flate/flatemodule.cpp
index 23e4660..c5372a2 100644
--- a/core/fxcodec/flate/flatemodule.cpp
+++ b/core/fxcodec/flate/flatemodule.cpp
@@ -24,6 +24,7 @@
#include "core/fxcrt/check.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fixed_size_data_vector.h"
+#include "core/fxcrt/fx_2d_size.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_safe_types.h"
@@ -403,87 +404,67 @@
}
const uint32_t last_row_size = src_span.size() % src_row_size;
+ size_t dest_size = Fx2DSizeOrDie(row_size, row_count);
+ if (last_row_size) {
+ dest_size -= src_row_size - last_row_size;
+ }
std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf(
- FX_Alloc2D(uint8_t, row_size, row_count));
- size_t byte_count = 0;
+ FX_Alloc(uint8_t, dest_size));
pdfium::span<const uint8_t> remaining_src_span = src_span;
pdfium::span<uint8_t> remaining_dest_span =
- pdfium::make_span(dest_buf.get(), row_size * row_count);
+ pdfium::make_span(dest_buf.get(), dest_size);
pdfium::span<uint8_t> prev_dest_span;
+ const uint32_t bytes_per_pixel = (Colors * BitsPerComponent + 7) / 8;
for (size_t row = 0; row < row_count; row++) {
const uint8_t tag = remaining_src_span.front();
- byte_count++;
- if (tag == 0) {
- uint32_t move_size = row_size;
- if (last_row_size != 0 && (row + 1) * (move_size + 1) > src_span.size()) {
- move_size = last_row_size - 1;
- }
- fxcrt::spancpy(remaining_dest_span,
- remaining_src_span.subspan(1, move_size));
- remaining_src_span = remaining_src_span.subspan(move_size + 1);
- prev_dest_span = remaining_dest_span;
- remaining_dest_span = remaining_dest_span.subspan(move_size);
- byte_count += move_size;
- continue;
- }
-
- const uint32_t bytes_per_pixel = (Colors * BitsPerComponent + 7) / 8;
+ remaining_src_span = remaining_src_span.subspan(1);
+ const size_t remaining_row_size =
+ std::min<size_t>(row_size, remaining_src_span.size());
switch (tag) {
case 1: {
- for (uint32_t i = 0; i < row_size && byte_count < src_span.size();
- ++i, ++byte_count) {
+ for (uint32_t i = 0; i < remaining_row_size; ++i) {
uint8_t left = GetLeftValue(remaining_dest_span, i, bytes_per_pixel);
- remaining_dest_span[i] = remaining_src_span[i + 1] + left;
+ remaining_dest_span[i] = remaining_src_span[i] + left;
}
break;
}
case 2: {
- for (uint32_t i = 0; i < row_size && byte_count < src_span.size();
- ++i, ++byte_count) {
+ for (uint32_t i = 0; i < remaining_row_size; ++i) {
uint8_t up = GetUpValue(prev_dest_span, i);
- remaining_dest_span[i] = remaining_src_span[i + 1] + up;
+ remaining_dest_span[i] = remaining_src_span[i] + up;
}
break;
}
case 3: {
- for (uint32_t i = 0; i < row_size && byte_count < src_span.size();
- ++i, ++byte_count) {
+ for (uint32_t i = 0; i < remaining_row_size; ++i) {
uint8_t left = GetLeftValue(remaining_dest_span, i, bytes_per_pixel);
uint8_t up = GetUpValue(prev_dest_span, i);
- remaining_dest_span[i] = remaining_src_span[i + 1] + (up + left) / 2;
+ remaining_dest_span[i] = remaining_src_span[i] + (up + left) / 2;
}
break;
}
case 4: {
- for (uint32_t i = 0; i < row_size && byte_count < src_span.size();
- ++i, ++byte_count) {
+ for (uint32_t i = 0; i < remaining_row_size; ++i) {
uint8_t left = GetLeftValue(remaining_dest_span, i, bytes_per_pixel);
uint8_t up = GetUpValue(prev_dest_span, i);
uint8_t upper_left =
GetUpperLeftValue(prev_dest_span, i, bytes_per_pixel);
remaining_dest_span[i] =
- remaining_src_span[i + 1] + PathPredictor(left, up, upper_left);
+ remaining_src_span[i] + PathPredictor(left, up, upper_left);
}
break;
}
default: {
- for (uint32_t i = 0; i < row_size && byte_count < src_span.size();
- ++i, ++byte_count) {
- remaining_dest_span[i] = remaining_src_span[i + 1];
- }
+ fxcrt::spancpy(remaining_dest_span,
+ remaining_src_span.first(remaining_row_size));
break;
}
}
- size_t remaining_size = (last_row_size == 0 || row + 1 < row_count)
- ? src_row_size
- : last_row_size;
- remaining_src_span = remaining_src_span.subspan(remaining_size);
+ remaining_src_span = remaining_src_span.subspan(remaining_row_size);
prev_dest_span = remaining_dest_span;
- remaining_dest_span = remaining_dest_span.subspan(remaining_size - 1);
+ remaining_dest_span = remaining_dest_span.subspan(remaining_row_size);
}
*result_buf = std::move(dest_buf);
- size_t dest_size = row_size * row_count -
- (last_row_size > 0 ? (src_row_size - last_row_size) : 0);
*result_size = pdfium::checked_cast<uint32_t>(dest_size);
return true;
}