/src/serenity/Userland/Libraries/LibWeb/HTML/ImageRequest.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2023, Andreas Kling <kling@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <AK/HashTable.h> |
8 | | #include <LibGfx/Bitmap.h> |
9 | | #include <LibWeb/Fetch/Fetching/Fetching.h> |
10 | | #include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h> |
11 | | #include <LibWeb/Fetch/Infrastructure/FetchController.h> |
12 | | #include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h> |
13 | | #include <LibWeb/HTML/AnimatedBitmapDecodedImageData.h> |
14 | | #include <LibWeb/HTML/DecodedImageData.h> |
15 | | #include <LibWeb/HTML/ImageRequest.h> |
16 | | #include <LibWeb/HTML/ListOfAvailableImages.h> |
17 | | #include <LibWeb/HTML/SharedResourceRequest.h> |
18 | | #include <LibWeb/Page/Page.h> |
19 | | #include <LibWeb/Platform/ImageCodecPlugin.h> |
20 | | #include <LibWeb/SVG/SVGDecodedImageData.h> |
21 | | |
22 | | namespace Web::HTML { |
23 | | |
24 | | JS_DEFINE_ALLOCATOR(ImageRequest); |
25 | | |
26 | | JS::NonnullGCPtr<ImageRequest> ImageRequest::create(JS::Realm& realm, JS::NonnullGCPtr<Page> page) |
27 | 0 | { |
28 | 0 | return realm.heap().allocate<ImageRequest>(realm, page); |
29 | 0 | } |
30 | | |
31 | | ImageRequest::ImageRequest(JS::NonnullGCPtr<Page> page) |
32 | 0 | : m_page(page) |
33 | 0 | { |
34 | 0 | } |
35 | | |
36 | | ImageRequest::~ImageRequest() |
37 | 0 | { |
38 | 0 | } |
39 | | |
40 | | void ImageRequest::visit_edges(JS::Cell::Visitor& visitor) |
41 | 0 | { |
42 | 0 | Base::visit_edges(visitor); |
43 | 0 | visitor.visit(m_shared_resource_request); |
44 | 0 | visitor.visit(m_page); |
45 | 0 | visitor.visit(m_image_data); |
46 | 0 | } |
47 | | |
48 | | // https://html.spec.whatwg.org/multipage/images.html#img-available |
49 | | bool ImageRequest::is_available() const |
50 | 0 | { |
51 | | // When an image request's state is either partially available or completely available, the image request is said to be available. |
52 | 0 | return m_state == State::PartiallyAvailable || m_state == State::CompletelyAvailable; |
53 | 0 | } |
54 | | |
55 | | bool ImageRequest::is_fetching() const |
56 | 0 | { |
57 | 0 | return m_shared_resource_request && m_shared_resource_request->is_fetching(); |
58 | 0 | } |
59 | | |
60 | | ImageRequest::State ImageRequest::state() const |
61 | 0 | { |
62 | 0 | return m_state; |
63 | 0 | } |
64 | | |
65 | | void ImageRequest::set_state(State state) |
66 | 0 | { |
67 | 0 | m_state = state; |
68 | 0 | } |
69 | | |
70 | | URL::URL const& ImageRequest::current_url() const |
71 | 0 | { |
72 | 0 | return m_current_url; |
73 | 0 | } |
74 | | |
75 | | void ImageRequest::set_current_url(JS::Realm& realm, URL::URL url) |
76 | 0 | { |
77 | 0 | m_current_url = move(url); |
78 | 0 | if (m_current_url.is_valid()) |
79 | 0 | m_shared_resource_request = SharedResourceRequest::get_or_create(realm, m_page, m_current_url); |
80 | 0 | } |
81 | | |
82 | | // https://html.spec.whatwg.org/multipage/images.html#abort-the-image-request |
83 | | void abort_the_image_request(JS::Realm&, ImageRequest* image_request) |
84 | 0 | { |
85 | | // 1. If image request is null, then return. |
86 | 0 | if (!image_request) |
87 | 0 | return; |
88 | | |
89 | | // 2. Forget image request's image data, if any. |
90 | 0 | image_request->set_image_data(nullptr); |
91 | | |
92 | | // 3. Abort any instance of the fetching algorithm for image request, |
93 | | // discarding any pending tasks generated by that algorithm. |
94 | | // AD-HOC: We simply don't do this, since our SharedResourceRequest may be used by someone else. |
95 | 0 | } |
96 | | |
97 | | JS::GCPtr<DecodedImageData> ImageRequest::image_data() const |
98 | 0 | { |
99 | 0 | return m_image_data; |
100 | 0 | } |
101 | | |
102 | | void ImageRequest::set_image_data(JS::GCPtr<DecodedImageData> data) |
103 | 0 | { |
104 | 0 | m_image_data = data; |
105 | 0 | } |
106 | | |
107 | | // https://html.spec.whatwg.org/multipage/images.html#prepare-an-image-for-presentation |
108 | | void ImageRequest::prepare_for_presentation(HTMLImageElement&) |
109 | 0 | { |
110 | | // FIXME: 1. Let exifTagMap be the EXIF tags obtained from req's image data, as defined by the relevant codec. [EXIF] |
111 | | // FIXME: 2. Let physicalWidth and physicalHeight be the width and height obtained from req's image data, as defined by the relevant codec. |
112 | | // FIXME: 3. Let dimX be the value of exifTagMap's tag 0xA002 (PixelXDimension). |
113 | | // FIXME: 4. Let dimY be the value of exifTagMap's tag 0xA003 (PixelYDimension). |
114 | | // FIXME: 5. Let resX be the value of exifTagMap's tag 0x011A (XResolution). |
115 | | // FIXME: 6. Let resY be the value of exifTagMap's tag 0x011B (YResolution). |
116 | | // FIXME: 7. Let resUnit be the value of exifTagMap's tag 0x0128 (ResolutionUnit). |
117 | | // FIXME: 8. If either dimX or dimY is not a positive integer, then return. |
118 | | // FIXME: 9. If either resX or resY is not a positive floating-point number, then return. |
119 | | // FIXME: 10. If resUnit is not equal to 2 (Inch), then return. |
120 | | // FIXME: 11. Let widthFromDensity be the value of physicalWidth, multiplied by 72 and divided by resX. |
121 | | // FIXME: 12. Let heightFromDensity be the value of physicalHeight, multiplied by 72 and divided by resY. |
122 | | // FIXME: 13. If widthFromDensity is not equal to dimX or heightFromDensity is not equal to dimY, then return. |
123 | | // FIXME: 14. If req's image data is CORS-cross-origin, then set img's intrinsic dimensions to dimX and dimY, scale img's pixel data accordingly, and return. |
124 | | // FIXME: 15. Set req's preferred density-corrected dimensions to a struct with its width set to dimX and its height set to dimY. |
125 | | // FIXME: 16. Update req's img element's presentation appropriately. |
126 | 0 | } |
127 | | |
128 | | void ImageRequest::fetch_image(JS::Realm& realm, JS::NonnullGCPtr<Fetch::Infrastructure::Request> request) |
129 | 0 | { |
130 | 0 | VERIFY(m_shared_resource_request); |
131 | 0 | m_shared_resource_request->fetch_resource(realm, request); |
132 | 0 | } |
133 | | |
134 | | void ImageRequest::add_callbacks(Function<void()> on_finish, Function<void()> on_fail) |
135 | 0 | { |
136 | 0 | VERIFY(m_shared_resource_request); |
137 | 0 | m_shared_resource_request->add_callbacks(move(on_finish), move(on_fail)); |
138 | 0 | } |
139 | | |
140 | | } |