From bb19dc00af047b0da821a33dde843e46f9df6869 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sun, 12 Feb 2023 09:47:19 -0500 Subject: [PATCH] LibGfx: Add a size-less ParametricCurveTagData::from_bytes() overload The curve data in lutAToBType and lutBToAType can store 'para' data, but other than in the main ICC tag table, the size of the tag data isn't explicitly stored. So it must be computed from the data contents. Extract the function body into a helper can call that from both variants. --- Userland/Libraries/LibGfx/ICC/TagTypes.cpp | 35 ++++++++++++++++++---- Userland/Libraries/LibGfx/ICC/TagTypes.h | 1 + 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Userland/Libraries/LibGfx/ICC/TagTypes.cpp b/Userland/Libraries/LibGfx/ICC/TagTypes.cpp index fe7b0d9e0a..338ed4c5ac 100644 --- a/Userland/Libraries/LibGfx/ICC/TagTypes.cpp +++ b/Userland/Libraries/LibGfx/ICC/TagTypes.cpp @@ -805,10 +805,18 @@ ErrorOr NamedColor2TagData::color_name(u32 index) return builder.to_string(); } -ErrorOr> ParametricCurveTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size) +namespace { + +struct ParametricCurveData { + u32 computed_size; + ParametricCurveTagData::FunctionType function_type; + Array parameters; +}; + +ErrorOr parametric_curve_data_from_bytes(ReadonlyBytes bytes) { // ICC v4, 10.18 parametricCurveType - VERIFY(tag_type(bytes) == Type); + VERIFY(tag_type(bytes) == ParametricCurveTagData::Type); TRY(check_reserved(bytes)); // "The parametricCurveType describes a one-dimensional curve by specifying one of a predefined set of functions @@ -825,10 +833,11 @@ ErrorOr> ParametricCurveTagData::from_byte if (raw_function_type > 4) return Error::from_string_literal("ICC::Profile: parametricCurveType unknown function type"); - FunctionType function_type = (FunctionType)raw_function_type; - unsigned count = parameter_count(function_type); + auto function_type = (ParametricCurveTagData::FunctionType)raw_function_type; + unsigned count = ParametricCurveTagData::parameter_count(function_type); - if (bytes.size() < 2 * sizeof(u32) + 2 * sizeof(u16) + count * sizeof(s15Fixed16Number)) + u32 computed_size = 2 * sizeof(u32) + 2 * sizeof(u16) + count * sizeof(s15Fixed16Number); + if (bytes.size() < computed_size) return Error::from_string_literal("ICC::Profile: parametricCurveType has not enough data for parameters"); auto* raw_parameters = bit_cast const*>(bytes.data() + 12); @@ -837,7 +846,21 @@ ErrorOr> ParametricCurveTagData::from_byte for (size_t i = 0; i < count; ++i) parameters[i] = S15Fixed16::create_raw(raw_parameters[i]); - return try_make_ref_counted(offset, size, function_type, move(parameters)); + return ParametricCurveData { computed_size, function_type, move(parameters) }; +} + +} + +ErrorOr> ParametricCurveTagData::from_bytes(ReadonlyBytes bytes, u32 offset) +{ + auto curve_data = TRY(parametric_curve_data_from_bytes(bytes)); + return try_make_ref_counted(offset, curve_data.computed_size, curve_data.function_type, move(curve_data.parameters)); +} + +ErrorOr> ParametricCurveTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size) +{ + auto curve_data = TRY(parametric_curve_data_from_bytes(bytes)); + return try_make_ref_counted(offset, size, curve_data.function_type, move(curve_data.parameters)); } ErrorOr> S15Fixed16ArrayTagData::from_bytes(ReadonlyBytes bytes, u32 offset, u32 size) diff --git a/Userland/Libraries/LibGfx/ICC/TagTypes.h b/Userland/Libraries/LibGfx/ICC/TagTypes.h index 41ae8e1ee5..05fcba3dee 100644 --- a/Userland/Libraries/LibGfx/ICC/TagTypes.h +++ b/Userland/Libraries/LibGfx/ICC/TagTypes.h @@ -608,6 +608,7 @@ public: static constexpr TagTypeSignature Type { 0x70617261 }; // 'para' + static ErrorOr> from_bytes(ReadonlyBytes, u32 offset); static ErrorOr> from_bytes(ReadonlyBytes, u32 offset, u32 size); ParametricCurveTagData(u32 offset, u32 size, FunctionType function_type, Array parameters)