summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2023-02-17 16:21:47 -0500
committerAndreas Kling <kling@serenityos.org>2023-02-19 00:01:44 +0100
commit4e72a353988bd341d321c554ca96c17fe15e2546 (patch)
tree773662b040038851392adc77e03b20b2a4ca5f74
parent1457e36b791a3a537454ac52f60291d32757c0ab (diff)
downloadserenity-4e72a353988bd341d321c554ca96c17fe15e2546.zip
LibGfx: Add scaffolding for writing tag data
This doesn't deduplicate identical TagDatas yet. It also doesn't implement actual serialization of TagData yet.
-rw-r--r--Userland/Libraries/LibGfx/ICC/BinaryWriter.cpp61
1 files changed, 50 insertions, 11 deletions
diff --git a/Userland/Libraries/LibGfx/ICC/BinaryWriter.cpp b/Userland/Libraries/LibGfx/ICC/BinaryWriter.cpp
index 17f7aa8def..d1b1ff5aed 100644
--- a/Userland/Libraries/LibGfx/ICC/BinaryWriter.cpp
+++ b/Userland/Libraries/LibGfx/ICC/BinaryWriter.cpp
@@ -13,18 +13,39 @@
namespace Gfx::ICC {
-static ErrorOr<void> encode_tag_table(ByteBuffer& bytes, Profile const& profile)
+static ErrorOr<ByteBuffer> encode_tag_data(TagData const& tag_data)
+{
+ (void)tag_data;
+ return ByteBuffer {};
+}
+
+static ErrorOr<Vector<ByteBuffer>> encode_tag_datas(Profile const& profile)
+{
+ Vector<ByteBuffer> tag_data_bytes;
+
+ // FIXME: If two tags refer to the same TagData object, write it just once to the output.
+ TRY(tag_data_bytes.try_resize(profile.tag_count()));
+ size_t i = 0;
+ profile.for_each_tag([&](auto, auto tag_data) {
+ // FIXME: Come up with a way to allow TRY instead of MUST here.
+ tag_data_bytes[i++] = MUST(encode_tag_data(tag_data));
+ });
+ return tag_data_bytes;
+}
+
+static ErrorOr<void> encode_tag_table(ByteBuffer& bytes, Profile const& profile, Vector<size_t> const& offsets, Vector<ByteBuffer> const& tag_data_bytes)
{
VERIFY(bytes.size() >= sizeof(ICCHeader) + sizeof(u32) + profile.tag_count() * sizeof(TagTableEntry));
*bit_cast<BigEndian<u32>*>(bytes.data() + sizeof(ICCHeader)) = profile.tag_count();
- TagTableEntry* tag_table_entry = bit_cast<TagTableEntry*>(bytes.data() + sizeof(ICCHeader) + sizeof(u32));
- profile.for_each_tag([&tag_table_entry](auto tag_signature, auto) {
- tag_table_entry->tag_signature = tag_signature;
- tag_table_entry->offset_to_beginning_of_tag_data_element = 0; // FIXME
- tag_table_entry->size_of_tag_data_element = 0; // FIXME
- ++tag_table_entry;
+ TagTableEntry* tag_table_entries = bit_cast<TagTableEntry*>(bytes.data() + sizeof(ICCHeader) + sizeof(u32));
+ int i = 0;
+ profile.for_each_tag([&](auto tag_signature, auto) {
+ tag_table_entries[i].tag_signature = tag_signature;
+ tag_table_entries[i].offset_to_beginning_of_tag_data_element = offsets[i];
+ tag_table_entries[i].size_of_tag_data_element = tag_data_bytes[i].size();
+ ++i;
});
return {};
@@ -81,12 +102,30 @@ static ErrorOr<void> encode_header(ByteBuffer& bytes, Profile const& profile)
ErrorOr<ByteBuffer> encode(Profile const& profile)
{
- // Leaves enough room for the profile header and the tag table count.
- // FIXME: Serialize tag data and write tag data too.
+ // Valid profiles always have tags. Profile only represents valid profiles.
+ VERIFY(profile.tag_count() > 0);
+
+ Vector<ByteBuffer> tag_data_bytes = TRY(encode_tag_datas(profile));
+
size_t tag_table_size = sizeof(u32) + profile.tag_count() * sizeof(TagTableEntry);
- auto bytes = TRY(ByteBuffer::create_zeroed(sizeof(ICCHeader) + tag_table_size));
+ size_t offset = sizeof(ICCHeader) + tag_table_size;
+ Vector<size_t> offsets;
+ for (auto const& bytes : tag_data_bytes) {
+ TRY(offsets.try_append(offset));
+ offset += align_up_to(bytes.size(), 4);
+ }
+
+ // Omit padding after last element.
+ // FIXME: Is that correct?
+ size_t total_size = offsets.last() + tag_data_bytes.last().size();
+
+ // Leave enough room for the profile header and the tag table count.
+ auto bytes = TRY(ByteBuffer::create_zeroed(total_size));
+
+ for (size_t i = 0; i < tag_data_bytes.size(); ++i)
+ memcpy(bytes.data() + offsets[i], tag_data_bytes[i].data(), tag_data_bytes[i].size());
- TRY(encode_tag_table(bytes, profile));
+ TRY(encode_tag_table(bytes, profile, offsets, tag_data_bytes));
TRY(encode_header(bytes, profile));
return bytes;