Skip to content

Commit ebd802f

Browse files
tcl3gmta
authored andcommitted
LibWeb+LibGfx: Move CSS sRGB color serialization function to LibGfx
1 parent 633fc45 commit ebd802f

File tree

8 files changed

+74
-73
lines changed

8 files changed

+74
-73
lines changed

Libraries/LibGfx/Color.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,73 @@
2525

2626
namespace Gfx {
2727

28+
namespace {
29+
30+
char nth_digit(u32 value, u8 digit)
31+
{
32+
// This helper is used to format integers.
33+
// nth_digit(745, 1) -> '5'
34+
// nth_digit(745, 2) -> '4'
35+
// nth_digit(745, 3) -> '7'
36+
37+
VERIFY(value < 1000);
38+
VERIFY(digit <= 3);
39+
VERIFY(digit > 0);
40+
41+
while (digit > 1) {
42+
value /= 10;
43+
digit--;
44+
}
45+
46+
return '0' + value % 10;
47+
}
48+
49+
Array<char, 4> format_to_8bit_compatible(u8 value)
50+
{
51+
// This function formats to the shortest string that roundtrips at 8 bits.
52+
// As an example:
53+
// 127 / 255 = 0.498 ± 0.001
54+
// 128 / 255 = 0.502 ± 0.001
55+
// But round(.5 * 255) == 128, so this function returns (note that it's only the fractional part):
56+
// 127 -> "498"
57+
// 128 -> "5"
58+
59+
u32 const three_digits = (value * 1000u + 127) / 255;
60+
u32 const rounded_to_two_digits = (three_digits + 5) / 10 * 10;
61+
62+
if ((rounded_to_two_digits * 255 / 100 + 5) / 10 != value)
63+
return { nth_digit(three_digits, 3), nth_digit(three_digits, 2), nth_digit(three_digits, 1), '\0' };
64+
65+
u32 const rounded_to_one_digit = (three_digits + 50) / 100 * 100;
66+
if ((rounded_to_one_digit * 255 / 100 + 5) / 10 != value)
67+
return { nth_digit(rounded_to_two_digits, 3), nth_digit(rounded_to_two_digits, 2), '\0', '\0' };
68+
69+
return { nth_digit(rounded_to_one_digit, 3), '\0', '\0', '\0' };
70+
}
71+
72+
}
73+
74+
// https://www.w3.org/TR/css-color-4/#serializing-sRGB-values
75+
void Color::serialize_a_srgb_value(StringBuilder& builder) const
76+
{
77+
// The serialized form is derived from the computed value and thus, uses either the rgb() or rgba() form
78+
// (depending on whether the alpha is exactly 1, or not), with lowercase letters for the function name.
79+
// NOTE: Since we use Gfx::Color, having an "alpha of 1" means its value is 255.
80+
if (alpha() == 0)
81+
builder.appendff("rgba({}, {}, {}, 0)", red(), green(), blue());
82+
else if (alpha() == 255)
83+
builder.appendff("rgb({}, {}, {})", red(), green(), blue());
84+
else
85+
builder.appendff("rgba({}, {}, {}, 0.{})", red(), green(), blue(), format_to_8bit_compatible(alpha()).data());
86+
}
87+
88+
String Color::serialize_a_srgb_value() const
89+
{
90+
StringBuilder builder;
91+
serialize_a_srgb_value(builder);
92+
return builder.to_string_without_validation();
93+
}
94+
2895
String Color::to_string(HTMLCompatibleSerialization html_compatible_serialization) const
2996
{
3097
// If the following conditions are all true:

Libraries/LibGfx/Color.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,9 @@ class Color {
502502
String to_string_without_alpha() const;
503503
Utf16String to_utf16_string_without_alpha() const;
504504

505+
void serialize_a_srgb_value(StringBuilder&) const;
506+
String serialize_a_srgb_value() const;
507+
505508
ByteString to_byte_string() const;
506509
ByteString to_byte_string_without_alpha() const;
507510
static Optional<Color> from_string(StringView);

Libraries/LibWeb/CSS/Serialize.cpp

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -127,66 +127,6 @@ void serialize_unicode_ranges(StringBuilder& builder, Vector<Gfx::UnicodeRange>
127127
});
128128
}
129129

130-
namespace {
131-
132-
char nth_digit(u32 value, u8 digit)
133-
{
134-
// This helper is used to format integers.
135-
// nth_digit(745, 1) -> '5'
136-
// nth_digit(745, 2) -> '4'
137-
// nth_digit(745, 3) -> '7'
138-
139-
VERIFY(value < 1000);
140-
VERIFY(digit <= 3);
141-
VERIFY(digit > 0);
142-
143-
while (digit > 1) {
144-
value /= 10;
145-
digit--;
146-
}
147-
148-
return '0' + value % 10;
149-
}
150-
151-
Array<char, 4> format_to_8bit_compatible(u8 value)
152-
{
153-
// This function formats to the shortest string that roundtrips at 8 bits.
154-
// As an example:
155-
// 127 / 255 = 0.498 ± 0.001
156-
// 128 / 255 = 0.502 ± 0.001
157-
// But round(.5 * 255) == 128, so this function returns (note that it's only the fractional part):
158-
// 127 -> "498"
159-
// 128 -> "5"
160-
161-
u32 const three_digits = (value * 1000u + 127) / 255;
162-
u32 const rounded_to_two_digits = (three_digits + 5) / 10 * 10;
163-
164-
if ((rounded_to_two_digits * 255 / 100 + 5) / 10 != value)
165-
return { nth_digit(three_digits, 3), nth_digit(three_digits, 2), nth_digit(three_digits, 1), '\0' };
166-
167-
u32 const rounded_to_one_digit = (three_digits + 50) / 100 * 100;
168-
if ((rounded_to_one_digit * 255 / 100 + 5) / 10 != value)
169-
return { nth_digit(rounded_to_two_digits, 3), nth_digit(rounded_to_two_digits, 2), '\0', '\0' };
170-
171-
return { nth_digit(rounded_to_one_digit, 3), '\0', '\0', '\0' };
172-
}
173-
174-
}
175-
176-
// https://www.w3.org/TR/css-color-4/#serializing-sRGB-values
177-
void serialize_a_srgb_value(StringBuilder& builder, Color color)
178-
{
179-
// The serialized form is derived from the computed value and thus, uses either the rgb() or rgba() form
180-
// (depending on whether the alpha is exactly 1, or not), with lowercase letters for the function name.
181-
// NOTE: Since we use Gfx::Color, having an "alpha of 1" means its value is 255.
182-
if (color.alpha() == 0)
183-
builder.appendff("rgba({}, {}, {}, 0)", color.red(), color.green(), color.blue());
184-
else if (color.alpha() == 255)
185-
builder.appendff("rgb({}, {}, {})", color.red(), color.green(), color.blue());
186-
else
187-
builder.appendff("rgba({}, {}, {}, 0.{})", color.red(), color.green(), color.blue(), format_to_8bit_compatible(color.alpha()).data());
188-
}
189-
190130
// https://drafts.csswg.org/cssom/#serialize-a-css-value
191131
void serialize_a_number(StringBuilder& builder, double value)
192132
{
@@ -218,13 +158,6 @@ String serialize_a_url(StringView url)
218158
return builder.to_string_without_validation();
219159
}
220160

221-
String serialize_a_srgb_value(Color color)
222-
{
223-
StringBuilder builder;
224-
serialize_a_srgb_value(builder, color);
225-
return builder.to_string_without_validation();
226-
}
227-
228161
String serialize_a_number(double value)
229162
{
230163
StringBuilder builder;

Libraries/LibWeb/CSS/Serialize.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@ WEB_API void serialize_an_identifier(StringBuilder&, StringView ident);
2323
void serialize_a_string(StringBuilder&, StringView string);
2424
WEB_API void serialize_a_url(StringBuilder&, StringView url);
2525
void serialize_unicode_ranges(StringBuilder&, Vector<Gfx::UnicodeRange> const& unicode_ranges);
26-
void serialize_a_srgb_value(StringBuilder&, Color color);
2726
void serialize_a_number(StringBuilder&, double value);
2827

2928
String serialize_an_identifier(StringView ident);
3029
String serialize_a_string(StringView string);
3130
String serialize_a_url(StringView url);
32-
String serialize_a_srgb_value(Color color);
3331
String serialize_a_number(double value);
3432

3533
// https://www.w3.org/TR/cssom/#serialize-a-comma-separated-list

Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ String FilterValueListStyleValue::to_string(SerializationMode mode) const
5757
[&](FilterOperation::DropShadow const& drop_shadow) {
5858
builder.append("drop-shadow("sv);
5959
if (drop_shadow.color.has_value()) {
60-
serialize_a_srgb_value(builder, *drop_shadow.color);
60+
drop_shadow.color->serialize_a_srgb_value(builder);
6161
builder.append(' ');
6262
}
6363
builder.appendff("{} {}", drop_shadow.offset_x, drop_shadow.offset_y);

Libraries/LibWeb/CSS/StyleValues/HSLColorStyleValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ bool HSLColorStyleValue::equals(StyleValue const& other) const
4040
String HSLColorStyleValue::to_string(SerializationMode mode) const
4141
{
4242
if (auto color = to_color({}); color.has_value())
43-
return serialize_a_srgb_value(color.value());
43+
return color->serialize_a_srgb_value();
4444

4545
StringBuilder builder;
4646

Libraries/LibWeb/CSS/StyleValues/HWBColorStyleValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ bool HWBColorStyleValue::equals(StyleValue const& other) const
5353
String HWBColorStyleValue::to_string(SerializationMode mode) const
5454
{
5555
if (auto color = to_color({}); color.has_value())
56-
return serialize_a_srgb_value(color.value());
56+
return color->serialize_a_srgb_value();
5757

5858
StringBuilder builder;
5959
builder.append("hwb("sv);

Libraries/LibWeb/CSS/StyleValues/RGBColorStyleValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ String RGBColorStyleValue::to_string(SerializationMode mode) const
9090
return m_properties.name.value().to_string().to_ascii_lowercase();
9191

9292
if (auto color = to_color({}); color.has_value())
93-
return serialize_a_srgb_value(color.value());
93+
return color->serialize_a_srgb_value();
9494

9595
StringBuilder builder;
9696
builder.append("rgb("sv);

0 commit comments

Comments
 (0)