/* * Copyright (c) 2026-present, the Ladybird developers. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include namespace Web::Painting { static ErrorOr shareable_bitmap_from_image_frame(Gfx::DecodedImageFrame const& frame) { auto bitmap = frame.bitmap().to_shareable_bitmap(); if (!bitmap.is_valid()) return Error::from_string_literal("Display-list resource transaction failed to create image-frame bitmap"); return bitmap; } static ErrorOr create_image_frame_from_ipc(Gfx::ShareableBitmap bitmap, Gfx::ColorSpace color_space) { if (!bitmap.is_valid() || !bitmap.bitmap()) return Error::from_string_literal("Display-list resource transaction contained invalid image-frame bitmap"); return Gfx::DecodedImageFrame { *bitmap.bitmap(), move(color_space) }; } } namespace IPC { template<> ErrorOr encode(Encoder& encoder, Web::Painting::DisplayListFontResource const& resource) { auto& font = *resource.font; TRY(encoder.encode(resource.id)); TRY(encoder.encode(font.typeface())); TRY(encoder.encode(font.point_size())); TRY(encoder.encode(font.variation_settings())); TRY(encoder.encode(font.features())); return {}; } template<> ErrorOr decode(Decoder& decoder) { auto id = TRY(decoder.decode()); auto typeface = TRY(decoder.decode>()); auto point_size = TRY(decoder.decode()); auto variations = TRY(decoder.decode()); auto features = TRY(decoder.decode()); return Web::Painting::DisplayListFontResource { .id = id, .font = typeface->font(point_size, move(variations), move(features)), }; } template<> ErrorOr encode(Encoder& encoder, Web::Painting::DisplayListImageFrameResource const& resource) { TRY(encoder.encode(resource.id)); TRY(encoder.encode(TRY(Web::Painting::shareable_bitmap_from_image_frame(resource.frame)))); TRY(encoder.encode(resource.frame.color_space())); return {}; } template<> ErrorOr decode(Decoder& decoder) { auto id = TRY(decoder.decode()); auto bitmap = TRY(decoder.decode()); auto color_space = TRY(decoder.decode()); return Web::Painting::DisplayListImageFrameResource { .id = id, .frame = TRY(Web::Painting::create_image_frame_from_ipc(move(bitmap), move(color_space))), }; } template<> ErrorOr encode(Encoder& encoder, Web::Painting::DisplayListVideoFrameResource const& resource) { Optional> frame; if (resource.frame) frame = NonnullRefPtr { *resource.frame }; TRY(encoder.encode(resource.id)); TRY(encoder.encode(frame)); return {}; } template<> ErrorOr decode(Decoder& decoder) { auto id = TRY(decoder.decode()); auto frame = TRY(decoder.decode>>()); RefPtr decoded_frame; if (frame.has_value()) decoded_frame = frame.release_value(); return Web::Painting::DisplayListVideoFrameResource { .id = id, .frame = move(decoded_frame), }; } template<> ErrorOr encode(Encoder& encoder, Web::Painting::DisplayListResourceTransaction const& transaction) { TRY(encoder.encode(transaction.fonts)); TRY(encoder.encode(transaction.image_frames)); TRY(encoder.encode(transaction.video_frames)); TRY(encoder.encode_size(transaction.display_lists.size())); for (auto const& display_list : transaction.display_lists) { TRY(encoder.encode(*display_list.display_list)); TRY(encoder.encode(display_list.visual_context_tree)); } TRY(encoder.encode(transaction.font_ids_to_remove)); TRY(encoder.encode(transaction.image_frame_ids_to_remove)); TRY(encoder.encode(transaction.video_frame_ids_to_remove)); TRY(encoder.encode(transaction.display_list_ids_to_remove)); return {}; } template<> ErrorOr decode(Decoder& decoder) { auto fonts = TRY(decoder.decode>()); auto image_frames = TRY(decoder.decode>()); auto video_frames = TRY(decoder.decode>()); auto display_list_count = TRY(decoder.decode_size()); Vector display_lists; TRY(display_lists.try_ensure_capacity(display_list_count)); for (size_t i = 0; i < display_list_count; ++i) { auto display_list = TRY(decoder.decode>()); auto visual_context_tree = TRY(decoder.decode()); display_lists.unchecked_append({ move(display_list), move(visual_context_tree) }); } return Web::Painting::DisplayListResourceTransaction { .fonts = move(fonts), .image_frames = move(image_frames), .video_frames = move(video_frames), .display_lists = move(display_lists), .font_ids_to_remove = TRY(decoder.decode>()), .image_frame_ids_to_remove = TRY(decoder.decode>()), .video_frame_ids_to_remove = TRY(decoder.decode>()), .display_list_ids_to_remove = TRY(decoder.decode>()), }; } }