mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
LibWeb: Cache parsed font descriptors on FontFace objects
This commit is contained in:
committed by
Andreas Kling
parent
9526dfbef3
commit
333df3b399
Notes:
github-actions[bot]
2026-04-04 22:14:40 +00:00
Author: https://github.com/tcl3 Commit: https://github.com/LadybirdBrowser/ladybird/commit/333df3b399c Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8739
@@ -22,8 +22,14 @@
|
||||
#include <LibWeb/CSS/FontFace.h>
|
||||
#include <LibWeb/CSS/FontFaceSet.h>
|
||||
#include <LibWeb/CSS/Parser/Parser.h>
|
||||
#include <LibWeb/CSS/StyleComputer.h>
|
||||
#include <LibWeb/CSS/StyleValues/ComputationContext.h>
|
||||
#include <LibWeb/CSS/StyleValues/CustomIdentStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FontStyleStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/StringStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
|
||||
#include <LibWeb/CSS/StyleValues/UnicodeRangeStyleValue.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
@@ -46,6 +52,32 @@ static bool is_unsupported_source(ParsedFontFace::Source const& source)
|
||||
return source.local_or_url.get<URL>().url().ends_with_bytes(".eot"sv);
|
||||
}
|
||||
|
||||
static FontWeightRange compute_weight_range(StyleValue const& value)
|
||||
{
|
||||
if (value.to_keyword() == Keyword::Auto || value.to_keyword() == Keyword::Normal)
|
||||
return { 400, 400 };
|
||||
|
||||
auto& weight_values = value.as_value_list().values();
|
||||
if (weight_values.size() == 1) {
|
||||
auto one_weight = static_cast<int>(StyleComputer::compute_font_weight(weight_values[0], {})->as_number().number());
|
||||
return { one_weight, one_weight };
|
||||
}
|
||||
if (weight_values.size() == 2) {
|
||||
auto first = static_cast<int>(StyleComputer::compute_font_weight(weight_values[0], {})->as_number().number());
|
||||
auto second = static_cast<int>(StyleComputer::compute_font_weight(weight_values[1], {})->as_number().number());
|
||||
return { min(first, second), max(first, second) };
|
||||
}
|
||||
return { 400, 400 };
|
||||
}
|
||||
|
||||
static int compute_slope(StyleValue const& value)
|
||||
{
|
||||
if (value.to_keyword() == Keyword::Auto || value.to_keyword() == Keyword::Normal)
|
||||
return 0;
|
||||
|
||||
return StyleComputer::compute_font_style(value)->as_font_style().to_font_slope();
|
||||
}
|
||||
|
||||
static NonnullRefPtr<Core::Promise<NonnullRefPtr<Gfx::Typeface const>>> load_vector_font(JS::Realm& realm, ByteBuffer const& data)
|
||||
{
|
||||
auto promise = Core::Promise<NonnullRefPtr<Gfx::Typeface const>>::construct();
|
||||
@@ -95,29 +127,25 @@ GC::Ref<FontFace> FontFace::construct_impl(JS::Realm& realm, String family, Font
|
||||
// Otherwise, set font face’s corresponding attributes to the serialization of the parsed values.
|
||||
|
||||
Parser::ParsingParams parsing_params { realm };
|
||||
auto try_parse_descriptor = [&parsing_params, &font_face, &realm](DescriptorID descriptor_id, String const& string) -> String {
|
||||
auto try_set_descriptor = [&](DescriptorID descriptor_id, String const& string, auto setter_impl) {
|
||||
auto result = parse_css_descriptor(parsing_params, AtRuleID::FontFace, DescriptorNameAndID::from_id(descriptor_id), string);
|
||||
if (!result) {
|
||||
font_face->reject_status_promise(WebIDL::SyntaxError::create(realm, Utf16String::formatted("FontFace constructor: Invalid {}", to_string(descriptor_id))));
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (result->is_custom_ident())
|
||||
return result->as_custom_ident().custom_ident().to_string();
|
||||
|
||||
return result->to_string(SerializationMode::Normal);
|
||||
(font_face.ptr()->*setter_impl)(result.release_nonnull());
|
||||
};
|
||||
font_face->m_family = try_parse_descriptor(DescriptorID::FontFamily, family);
|
||||
font_face->m_style = try_parse_descriptor(DescriptorID::FontStyle, descriptors.style);
|
||||
font_face->m_weight = try_parse_descriptor(DescriptorID::FontWeight, descriptors.weight);
|
||||
font_face->m_stretch = try_parse_descriptor(DescriptorID::FontWidth, descriptors.stretch);
|
||||
font_face->m_unicode_range = try_parse_descriptor(DescriptorID::UnicodeRange, descriptors.unicode_range);
|
||||
font_face->m_feature_settings = try_parse_descriptor(DescriptorID::FontFeatureSettings, descriptors.feature_settings);
|
||||
font_face->m_variation_settings = try_parse_descriptor(DescriptorID::FontVariationSettings, descriptors.variation_settings);
|
||||
font_face->m_display = try_parse_descriptor(DescriptorID::FontDisplay, descriptors.display);
|
||||
font_face->m_ascent_override = try_parse_descriptor(DescriptorID::AscentOverride, descriptors.ascent_override);
|
||||
font_face->m_descent_override = try_parse_descriptor(DescriptorID::DescentOverride, descriptors.descent_override);
|
||||
font_face->m_line_gap_override = try_parse_descriptor(DescriptorID::LineGapOverride, descriptors.line_gap_override);
|
||||
try_set_descriptor(DescriptorID::FontFamily, family, &FontFace::set_family_impl);
|
||||
try_set_descriptor(DescriptorID::FontStyle, descriptors.style, &FontFace::set_style_impl);
|
||||
try_set_descriptor(DescriptorID::FontWeight, descriptors.weight, &FontFace::set_weight_impl);
|
||||
try_set_descriptor(DescriptorID::FontWidth, descriptors.stretch, &FontFace::set_stretch_impl);
|
||||
try_set_descriptor(DescriptorID::UnicodeRange, descriptors.unicode_range, &FontFace::set_unicode_range_impl);
|
||||
try_set_descriptor(DescriptorID::FontFeatureSettings, descriptors.feature_settings, &FontFace::set_feature_settings_impl);
|
||||
try_set_descriptor(DescriptorID::FontVariationSettings, descriptors.variation_settings, &FontFace::set_variation_settings_impl);
|
||||
try_set_descriptor(DescriptorID::FontDisplay, descriptors.display, &FontFace::set_display_impl);
|
||||
try_set_descriptor(DescriptorID::AscentOverride, descriptors.ascent_override, &FontFace::set_ascent_override_impl);
|
||||
try_set_descriptor(DescriptorID::DescentOverride, descriptors.descent_override, &FontFace::set_descent_override_impl);
|
||||
try_set_descriptor(DescriptorID::LineGapOverride, descriptors.line_gap_override, &FontFace::set_line_gap_override_impl);
|
||||
RefPtr<StyleValue const> parsed_source;
|
||||
if (auto* source_string = source.get_pointer<String>()) {
|
||||
parsed_source = parse_css_descriptor(parsing_params, AtRuleID::FontFace, DescriptorNameAndID::from_id(DescriptorID::Src), *source_string);
|
||||
@@ -252,9 +280,13 @@ void FontFace::reparse_connected_css_font_face_rule_descriptors()
|
||||
{
|
||||
auto const& descriptors = m_css_font_face_rule->descriptors();
|
||||
|
||||
ComputationContext computation_context {
|
||||
.length_resolution_context = Length::ResolutionContext::for_document(*descriptors->parent_rule()->parent_style_sheet()->owning_document())
|
||||
};
|
||||
|
||||
set_family_impl(*descriptors->descriptor(DescriptorNameAndID::from_id(DescriptorID::FontFamily)));
|
||||
set_style_impl(*descriptors->descriptor_or_initial_value(DescriptorNameAndID::from_id(DescriptorID::FontStyle)));
|
||||
set_weight_impl(*descriptors->descriptor_or_initial_value(DescriptorNameAndID::from_id(DescriptorID::FontWeight)));
|
||||
set_style_impl(*descriptors->descriptor_or_initial_value(DescriptorNameAndID::from_id(DescriptorID::FontStyle))->absolutized(computation_context));
|
||||
set_weight_impl(*descriptors->descriptor_or_initial_value(DescriptorNameAndID::from_id(DescriptorID::FontWeight))->absolutized(computation_context));
|
||||
set_stretch_impl(*descriptors->descriptor_or_initial_value(DescriptorNameAndID::from_id(DescriptorID::FontWidth)));
|
||||
set_unicode_range_impl(*descriptors->descriptor_or_initial_value(DescriptorNameAndID::from_id(DescriptorID::UnicodeRange)));
|
||||
set_feature_settings_impl(*descriptors->descriptor_or_initial_value(DescriptorNameAndID::from_id(DescriptorID::FontFeatureSettings)));
|
||||
@@ -275,9 +307,8 @@ ParsedFontFace FontFace::parsed_font_face() const
|
||||
// Create a dummy CSSFontFaceRule so that we load relative to the document's base URL
|
||||
CSSFontFaceRule::create(realm(), CSSFontFaceDescriptors::create(realm(), {})),
|
||||
m_family,
|
||||
// FIXME: Actually parse this as we're supposed to.
|
||||
m_weight.to_number<int>().map([](auto weight) { return FontWeightRange { weight, weight }; }),
|
||||
0, // FIXME: slope
|
||||
m_cached_weight_range,
|
||||
m_cached_slope,
|
||||
Gfx::FontWidth::Normal, // FIXME: width
|
||||
m_urls,
|
||||
m_unicode_ranges,
|
||||
@@ -381,6 +412,7 @@ WebIDL::ExceptionOr<void> FontFace::set_style(String const& string)
|
||||
void FontFace::set_style_impl(NonnullRefPtr<StyleValue const> const& value)
|
||||
{
|
||||
m_style = value->to_string(SerializationMode::Normal);
|
||||
m_cached_slope = compute_slope(*value);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-font-loading/#dom-fontface-weight
|
||||
@@ -405,6 +437,7 @@ WebIDL::ExceptionOr<void> FontFace::set_weight(String const& string)
|
||||
void FontFace::set_weight_impl(NonnullRefPtr<StyleValue const> const& value)
|
||||
{
|
||||
m_weight = value->to_string(SerializationMode::Normal);
|
||||
m_cached_weight_range = compute_weight_range(*value);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-font-loading/#dom-fontface-stretch
|
||||
@@ -454,6 +487,11 @@ WebIDL::ExceptionOr<void> FontFace::set_unicode_range(String const& string)
|
||||
void FontFace::set_unicode_range_impl(NonnullRefPtr<StyleValue const> const& value)
|
||||
{
|
||||
m_unicode_range = value->to_string(SerializationMode::Normal);
|
||||
auto const& ranges = value->as_value_list().values();
|
||||
m_unicode_ranges.clear_with_capacity();
|
||||
m_unicode_ranges.ensure_capacity(ranges.size());
|
||||
for (auto const& range : ranges)
|
||||
m_unicode_ranges.unchecked_append(range->as_unicode_range().unicode_range());
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-font-loading/#dom-fontface-featuresettings
|
||||
|
||||
Reference in New Issue
Block a user