1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 02:57:36 +00:00

LibDraw: Have the PNGImageLoaderPlugin remember if it failed to decode

Instead of trying again when asked repeatedly, just remember if it
didn't work out the first time.
This commit is contained in:
Andreas Kling 2019-10-19 17:43:47 +02:00
parent fed668f20f
commit 8acc61f19a

View file

@ -65,6 +65,7 @@ struct [[gnu::packed]] Quad16
struct PNGLoadingContext { struct PNGLoadingContext {
enum State { enum State {
NotDecoded = 0, NotDecoded = 0,
Error,
HeaderDecoded, HeaderDecoded,
SizeDecoded, SizeDecoded,
ChunksDecoded, ChunksDecoded,
@ -401,6 +402,7 @@ static bool decode_png_header(PNGLoadingContext& context)
if (memcmp(context.data, png_header, sizeof(png_header)) != 0) { if (memcmp(context.data, png_header, sizeof(png_header)) != 0) {
dbg() << "Invalid PNG header"; dbg() << "Invalid PNG header";
context.state = PNGLoadingContext::State::Error;
return false; return false;
} }
@ -424,6 +426,7 @@ static bool decode_png_size(PNGLoadingContext& context)
Streamer streamer(data_ptr, data_remaining); Streamer streamer(data_ptr, data_remaining);
while (!streamer.at_end()) { while (!streamer.at_end()) {
if (!process_chunk(streamer, context, true)) { if (!process_chunk(streamer, context, true)) {
context.state = PNGLoadingContext::State::Error;
return false; return false;
} }
if (context.width && context.height) { if (context.width && context.height) {
@ -453,6 +456,7 @@ static bool decode_png_chunks(PNGLoadingContext& context)
Streamer streamer(data_ptr, data_remaining); Streamer streamer(data_ptr, data_remaining);
while (!streamer.at_end()) { while (!streamer.at_end()) {
if (!process_chunk(streamer, context, false)) { if (!process_chunk(streamer, context, false)) {
context.state = PNGLoadingContext::State::Error;
return false; return false;
} }
} }
@ -478,8 +482,10 @@ static bool decode_png_bitmap(PNGLoadingContext& context)
unsigned long srclen = context.compressed_data.size() - 6; unsigned long srclen = context.compressed_data.size() - 6;
unsigned long destlen = context.decompression_buffer_size; unsigned long destlen = context.decompression_buffer_size;
int ret = puff(context.decompression_buffer, &destlen, context.compressed_data.data() + 2, &srclen); int ret = puff(context.decompression_buffer, &destlen, context.compressed_data.data() + 2, &srclen);
if (ret < 0) if (ret < 0) {
context.state = PNGLoadingContext::State::Error;
return false; return false;
}
context.compressed_data.clear(); context.compressed_data.clear();
} }
@ -491,13 +497,17 @@ static bool decode_png_bitmap(PNGLoadingContext& context)
Streamer streamer(context.decompression_buffer, context.decompression_buffer_size); Streamer streamer(context.decompression_buffer, context.decompression_buffer_size);
for (int y = 0; y < context.height; ++y) { for (int y = 0; y < context.height; ++y) {
u8 filter; u8 filter;
if (!streamer.read(filter)) if (!streamer.read(filter)) {
context.state = PNGLoadingContext::State::Error;
return false; return false;
}
context.scanlines.append({ filter }); context.scanlines.append({ filter });
auto& scanline_buffer = context.scanlines.last().data; auto& scanline_buffer = context.scanlines.last().data;
if (!streamer.wrap_bytes(scanline_buffer, context.width * context.bytes_per_pixel)) if (!streamer.wrap_bytes(scanline_buffer, context.width * context.bytes_per_pixel)) {
context.state = PNGLoadingContext::State::Error;
return false; return false;
}
} }
} }
@ -664,9 +674,13 @@ PNGImageLoaderPlugin::~PNGImageLoaderPlugin()
Size PNGImageLoaderPlugin::size() Size PNGImageLoaderPlugin::size()
{ {
if (m_context->state == PNGLoadingContext::State::Error)
return {};
if (m_context->state < PNGLoadingContext::State::SizeDecoded) { if (m_context->state < PNGLoadingContext::State::SizeDecoded) {
bool success = decode_png_size(*m_context); bool success = decode_png_size(*m_context);
ASSERT(success); if (!success)
return {};
} }
return { m_context->width, m_context->height }; return { m_context->width, m_context->height };
@ -674,10 +688,14 @@ Size PNGImageLoaderPlugin::size()
RefPtr<GraphicsBitmap> PNGImageLoaderPlugin::bitmap() RefPtr<GraphicsBitmap> PNGImageLoaderPlugin::bitmap()
{ {
if (m_context->state == PNGLoadingContext::State::Error)
return nullptr;
if (m_context->state < PNGLoadingContext::State::BitmapDecoded) { if (m_context->state < PNGLoadingContext::State::BitmapDecoded) {
// NOTE: This forces the chunk decoding to happen. // NOTE: This forces the chunk decoding to happen.
bool success = decode_png_bitmap(*m_context); bool success = decode_png_bitmap(*m_context);
ASSERT(success); if (!success)
return nullptr;
} }
ASSERT(m_context->bitmap); ASSERT(m_context->bitmap);