Serenity Operating System
1/*
2 * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include "Angle.h"
8#include <AK/Math.h>
9#include <LibWeb/CSS/StyleValue.h>
10
11namespace Web::CSS {
12
13Angle::Angle(int value, Type type)
14 : m_type(type)
15 , m_value(value)
16{
17}
18
19Angle::Angle(float value, Type type)
20 : m_type(type)
21 , m_value(value)
22{
23}
24
25Angle Angle::make_calculated(NonnullRefPtr<CalculatedStyleValue> calculated_style_value)
26{
27 Angle angle { 0, Type::Calculated };
28 angle.m_calculated_style = move(calculated_style_value);
29 return angle;
30}
31
32Angle Angle::make_degrees(float value)
33{
34 return { value, Type::Deg };
35}
36
37Angle Angle::percentage_of(Percentage const& percentage) const
38{
39 VERIFY(!is_calculated());
40
41 return Angle { percentage.as_fraction() * m_value, m_type };
42}
43
44ErrorOr<String> Angle::to_string() const
45{
46 if (is_calculated())
47 return m_calculated_style->to_string();
48 return String::formatted("{}{}", m_value, unit_name());
49}
50
51float Angle::to_degrees() const
52{
53 switch (m_type) {
54 case Type::Calculated:
55 return m_calculated_style->resolve_angle()->to_degrees();
56 case Type::Deg:
57 return m_value;
58 case Type::Grad:
59 return m_value * (360.0f / 400.0f);
60 case Type::Rad:
61 return m_value * (180.0f / AK::Pi<float>);
62 case Type::Turn:
63 return m_value * 360.0f;
64 }
65 VERIFY_NOT_REACHED();
66}
67
68StringView Angle::unit_name() const
69{
70 switch (m_type) {
71 case Type::Calculated:
72 return "calculated"sv;
73 case Type::Deg:
74 return "deg"sv;
75 case Type::Grad:
76 return "grad"sv;
77 case Type::Rad:
78 return "rad"sv;
79 case Type::Turn:
80 return "turn"sv;
81 }
82 VERIFY_NOT_REACHED();
83}
84
85Optional<Angle::Type> Angle::unit_from_name(StringView name)
86{
87 if (name.equals_ignoring_ascii_case("deg"sv)) {
88 return Type::Deg;
89 }
90 if (name.equals_ignoring_ascii_case("grad"sv)) {
91 return Type::Grad;
92 }
93 if (name.equals_ignoring_ascii_case("rad"sv)) {
94 return Type::Rad;
95 }
96 if (name.equals_ignoring_ascii_case("turn"sv)) {
97 return Type::Turn;
98 }
99 return {};
100}
101
102NonnullRefPtr<CalculatedStyleValue> Angle::calculated_style_value() const
103{
104 VERIFY(!m_calculated_style.is_null());
105 return *m_calculated_style;
106}
107
108}