mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-05-11 17:37:33 +02:00
Previously we were inconsistent by generating code for enum definitions but not generating code for dictionaries. With future changes to the IDL generator to expose helpers to convert to and from IDL values this produced circular depdendencies. To solve this problem, also generate the dictionary definitions in bindings headers.
181 lines
7.0 KiB
C++
181 lines
7.0 KiB
C++
/*
|
||
* Copyright (c) 2023, Bastiaan van der Plaat <bastiaan.v.d.plaat@gmail.com>
|
||
*
|
||
* SPDX-License-Identifier: BSD-2-Clause
|
||
*/
|
||
|
||
#include <LibWeb/Bindings/DOMQuad.h>
|
||
#include <LibWeb/Bindings/DOMRectReadOnly.h>
|
||
#include <LibWeb/Bindings/Intrinsics.h>
|
||
#include <LibWeb/Geometry/DOMQuad.h>
|
||
#include <LibWeb/HTML/StructuredSerialize.h>
|
||
|
||
namespace Web::Geometry {
|
||
|
||
GC_DEFINE_ALLOCATOR(DOMQuad);
|
||
|
||
GC::Ref<DOMQuad> DOMQuad::construct_impl(JS::Realm& realm, Bindings::DOMPointInit const& p1, Bindings::DOMPointInit const& p2, Bindings::DOMPointInit const& p3, Bindings::DOMPointInit const& p4)
|
||
{
|
||
return realm.create<DOMQuad>(realm, p1, p2, p3, p4);
|
||
}
|
||
|
||
GC::Ref<DOMQuad> DOMQuad::create(JS::Realm& realm)
|
||
{
|
||
return realm.create<DOMQuad>(realm);
|
||
}
|
||
|
||
DOMQuad::DOMQuad(JS::Realm& realm, Bindings::DOMPointInit const& p1, Bindings::DOMPointInit const& p2, Bindings::DOMPointInit const& p3, Bindings::DOMPointInit const& p4)
|
||
: PlatformObject(realm)
|
||
, m_p1(DOMPoint::from_point(realm.vm(), p1))
|
||
, m_p2(DOMPoint::from_point(realm.vm(), p2))
|
||
, m_p3(DOMPoint::from_point(realm.vm(), p3))
|
||
, m_p4(DOMPoint::from_point(realm.vm(), p4))
|
||
{
|
||
}
|
||
|
||
DOMQuad::DOMQuad(JS::Realm& realm)
|
||
: PlatformObject(realm)
|
||
, m_p1(DOMPoint::create(realm))
|
||
, m_p2(DOMPoint::create(realm))
|
||
, m_p3(DOMPoint::create(realm))
|
||
, m_p4(DOMPoint::create(realm))
|
||
{
|
||
}
|
||
|
||
DOMQuad::~DOMQuad() = default;
|
||
|
||
// https://drafts.fxtf.org/geometry/#dom-domquad-fromrect
|
||
GC::Ref<DOMQuad> DOMQuad::from_rect(JS::VM& vm, Bindings::DOMRectInit const& other)
|
||
{
|
||
// The fromRect(other) static method on DOMQuad must create a DOMQuad from the DOMRectInit dictionary other.
|
||
auto make_point = [](double x, double y) {
|
||
Bindings::DOMPointInit point {};
|
||
point.x = x;
|
||
point.y = y;
|
||
return point;
|
||
};
|
||
|
||
return construct_impl(*vm.current_realm(),
|
||
make_point(other.x, other.y),
|
||
make_point(other.x + other.width, other.y),
|
||
make_point(other.x + other.width, other.y + other.height),
|
||
make_point(other.x, other.y + other.height));
|
||
}
|
||
|
||
// https://drafts.fxtf.org/geometry/#dom-domquad-fromquad
|
||
GC::Ref<DOMQuad> DOMQuad::from_quad(JS::VM& vm, Bindings::DOMQuadInit const& other)
|
||
{
|
||
// The fromQuad(other) static method on DOMQuad must create a DOMQuad from the DOMQuadInit dictionary other.
|
||
return construct_impl(*vm.current_realm(),
|
||
other.p1.value_or(Bindings::DOMPointInit {}),
|
||
other.p2.value_or(Bindings::DOMPointInit {}),
|
||
other.p3.value_or(Bindings::DOMPointInit {}),
|
||
other.p4.value_or(Bindings::DOMPointInit {}));
|
||
}
|
||
|
||
// https://drafts.fxtf.org/geometry/#dom-domquad-getbounds
|
||
GC::Ref<DOMRect> DOMQuad::get_bounds() const
|
||
{
|
||
// The NaN-safe minimum of a non-empty list of unrestricted double values is NaN if any member of the list is NaN, or the minimum of the list otherwise.
|
||
auto nan_safe_minimum = [](double a, double b, double c, double d) -> double {
|
||
if (isnan(a) || isnan(b) || isnan(c) || isnan(d))
|
||
return NAN;
|
||
return min(a, min(b, min(c, d)));
|
||
};
|
||
|
||
// Analogously, the NaN-safe maximum of a non-empty list of unrestricted double values is NaN if any member of the list is NaN, or the maximum of the list otherwise.
|
||
auto nan_safe_maximum = [](double a, double b, double c, double d) -> double {
|
||
if (isnan(a) || isnan(b) || isnan(c) || isnan(d))
|
||
return NAN;
|
||
return max(a, max(b, max(c, d)));
|
||
};
|
||
|
||
// 1. Let bounds be a DOMRect object.
|
||
auto bounds = DOMRect::create(realm(), {});
|
||
|
||
// 2. Let left be the NaN-safe minimum of point 1’s x coordinate, point 2’s x coordinate, point 3’s x coordinate and point 4’s x coordinate.
|
||
auto left = nan_safe_minimum(m_p1->x(), m_p2->x(), m_p3->x(), m_p4->x());
|
||
|
||
// 3. Let top be the NaN-safe minimum of point 1’s y coordinate, point 2’s y coordinate, point 3’s y coordinate and point 4’s y coordinate.
|
||
auto top = nan_safe_minimum(m_p1->y(), m_p2->y(), m_p3->y(), m_p4->y());
|
||
|
||
// 4. Let right be the NaN-safe maximum of point 1’s x coordinate, point 2’s x coordinate, point 3’s x coordinate and point 4’s x coordinate.
|
||
auto right = nan_safe_maximum(m_p1->x(), m_p2->x(), m_p3->x(), m_p4->x());
|
||
|
||
// 5. Let bottom be the NaN-safe maximum of point 1’s y coordinate, point 2’s y coordinate, point 3’s y coordinate and point 4’s y coordinate.
|
||
auto bottom = nan_safe_maximum(m_p1->y(), m_p2->y(), m_p3->y(), m_p4->y());
|
||
|
||
// 6. Set x coordinate of bounds to left, y coordinate of bounds to top, width dimension of bounds to right - left and height dimension of bounds to bottom - top.
|
||
bounds->set_x(left);
|
||
bounds->set_y(top);
|
||
bounds->set_width(right - left);
|
||
bounds->set_height(bottom - top);
|
||
|
||
// 7. Return bounds.
|
||
return bounds;
|
||
}
|
||
|
||
// https://drafts.fxtf.org/geometry/#structured-serialization
|
||
WebIDL::ExceptionOr<void> DOMQuad::serialization_steps(HTML::TransferDataEncoder& serialized, bool for_storage, HTML::SerializationMemory& memory)
|
||
{
|
||
auto& vm = this->vm();
|
||
|
||
// 1. Set serialized.[[P1]] to the sub-serialization of value’s point 1.
|
||
serialized.append(TRY(HTML::structured_serialize_internal(vm, m_p1, for_storage, memory)));
|
||
|
||
// 2. Set serialized.[[P2]] to the sub-serialization of value’s point 2.
|
||
serialized.append(TRY(HTML::structured_serialize_internal(vm, m_p2, for_storage, memory)));
|
||
|
||
// 3. Set serialized.[[P3]] to the sub-serialization of value’s point 3.
|
||
serialized.append(TRY(HTML::structured_serialize_internal(vm, m_p3, for_storage, memory)));
|
||
|
||
// 4. Set serialized.[[P4]] to the sub-serialization of value’s point 4.
|
||
serialized.append(TRY(HTML::structured_serialize_internal(vm, m_p4, for_storage, memory)));
|
||
|
||
return {};
|
||
}
|
||
|
||
// https://drafts.fxtf.org/geometry/#structured-serialization
|
||
WebIDL::ExceptionOr<void> DOMQuad::deserialization_steps(HTML::TransferDataDecoder& serialized, HTML::DeserializationMemory& memory)
|
||
{
|
||
auto& vm = this->vm();
|
||
auto& realm = this->realm();
|
||
|
||
auto deserialize_dom_point = [&](GC::Ref<DOMPoint>& storage) -> WebIDL::ExceptionOr<void> {
|
||
auto deserialized = TRY(HTML::structured_deserialize_internal(vm, serialized, realm, memory));
|
||
storage = as<DOMPoint>(deserialized.as_object());
|
||
return {};
|
||
};
|
||
|
||
// 1. Set value’s point 1 to the sub-deserialization of serialized.[[P1]].
|
||
TRY(deserialize_dom_point(m_p1));
|
||
|
||
// 2. Set value’s point 2 to the sub-deserialization of serialized.[[P2]].
|
||
TRY(deserialize_dom_point(m_p2));
|
||
|
||
// 3. Set value’s point 3 to the sub-deserialization of serialized.[[P3]].
|
||
TRY(deserialize_dom_point(m_p3));
|
||
|
||
// 4. Set value’s point 4 to the sub-deserialization of serialized.[[P4]].
|
||
TRY(deserialize_dom_point(m_p4));
|
||
|
||
return {};
|
||
}
|
||
|
||
void DOMQuad::initialize(JS::Realm& realm)
|
||
{
|
||
WEB_SET_PROTOTYPE_FOR_INTERFACE(DOMQuad);
|
||
Base::initialize(realm);
|
||
}
|
||
|
||
void DOMQuad::visit_edges(Cell::Visitor& visitor)
|
||
{
|
||
Base::visit_edges(visitor);
|
||
visitor.visit(m_p1);
|
||
visitor.visit(m_p2);
|
||
visitor.visit(m_p3);
|
||
visitor.visit(m_p4);
|
||
}
|
||
|
||
}
|