mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 17:31:58 -05:00
LibGfx+LibWeb: Produce font cascade list in CSS font matching algorithm
According to the CSS font matching algorithm specification, it is supposed to be executed for each glyph instead of each text run, as is currently done. This change partially implements this by having the font matching algorithm produce a list of fonts against which each glyph will be tested to find its suitable font. Now, it becomes possible to have per-glyph fallback fonts: if the needed glyph is not present in a font, we can check the subsequent fonts in the list.
This commit is contained in:
parent
f50bf00814
commit
2cb0039a13
23 changed files with 250 additions and 109 deletions
|
@ -13,6 +13,7 @@ set(SOURCES
|
|||
Filters/FastBoxBlurFilter.cpp
|
||||
Filters/LumaFilter.cpp
|
||||
Filters/StackBlurFilter.cpp
|
||||
FontCascadeList.cpp
|
||||
Font/BitmapFont.cpp
|
||||
Font/Emoji.cpp
|
||||
Font/Font.cpp
|
||||
|
|
54
Userland/Libraries/LibGfx/FontCascadeList.cpp
Normal file
54
Userland/Libraries/LibGfx/FontCascadeList.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibGfx/FontCascadeList.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
void FontCascadeList::add(NonnullRefPtr<Font> font)
|
||||
{
|
||||
m_fonts.append({ move(font), {} });
|
||||
}
|
||||
|
||||
void FontCascadeList::add(NonnullRefPtr<Font> font, Vector<UnicodeRange> unicode_ranges)
|
||||
{
|
||||
m_fonts.append({ move(font), move(unicode_ranges) });
|
||||
}
|
||||
|
||||
void FontCascadeList::extend(FontCascadeList const& other)
|
||||
{
|
||||
for (auto const& font : other.m_fonts) {
|
||||
m_fonts.append({ font.font->clone(), font.unicode_ranges });
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::Font const& FontCascadeList::font_for_code_point(u32 code_point) const
|
||||
{
|
||||
for (auto const& entry : m_fonts) {
|
||||
if (!entry.unicode_ranges.has_value())
|
||||
return entry.font;
|
||||
if (!entry.font->contains_glyph(code_point))
|
||||
continue;
|
||||
for (auto const& range : *entry.unicode_ranges) {
|
||||
if (range.contains(code_point))
|
||||
return entry.font;
|
||||
}
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
bool FontCascadeList::equals(FontCascadeList const& other) const
|
||||
{
|
||||
if (m_fonts.size() != other.m_fonts.size())
|
||||
return false;
|
||||
for (size_t i = 0; i < m_fonts.size(); ++i) {
|
||||
if (m_fonts[i].font != other.m_fonts[i].font)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
43
Userland/Libraries/LibGfx/FontCascadeList.h
Normal file
43
Userland/Libraries/LibGfx/FontCascadeList.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/Font/UnicodeRange.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
class FontCascadeList : public RefCounted<FontCascadeList> {
|
||||
public:
|
||||
static NonnullRefPtr<FontCascadeList> create()
|
||||
{
|
||||
return adopt_ref(*new FontCascadeList());
|
||||
}
|
||||
|
||||
size_t size() const { return m_fonts.size(); }
|
||||
bool is_empty() const { return m_fonts.is_empty(); }
|
||||
Font const& first() const { return *m_fonts.first().font; }
|
||||
|
||||
void add(NonnullRefPtr<Font> font);
|
||||
void add(NonnullRefPtr<Font> font, Vector<UnicodeRange> unicode_ranges);
|
||||
|
||||
void extend(FontCascadeList const& other);
|
||||
|
||||
Gfx::Font const& font_for_code_point(u32 code_point) const;
|
||||
|
||||
bool equals(FontCascadeList const& other) const;
|
||||
|
||||
struct Entry {
|
||||
NonnullRefPtr<Font> font;
|
||||
Optional<Vector<UnicodeRange>> unicode_ranges;
|
||||
};
|
||||
|
||||
private:
|
||||
Vector<Entry> m_fonts;
|
||||
};
|
||||
|
||||
}
|
|
@ -138,8 +138,8 @@ Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Nod
|
|||
VERIFY(root_element->layout_node());
|
||||
return Length::ResolutionContext {
|
||||
.viewport_rect = node.navigable()->viewport_rect(),
|
||||
.font_metrics = { node.computed_values().font_size(), node.font().pixel_metrics(), node.line_height() },
|
||||
.root_font_metrics = { root_element->layout_node()->computed_values().font_size(), root_element->layout_node()->font().pixel_metrics(), root_element->layout_node()->line_height() },
|
||||
.font_metrics = { node.computed_values().font_size(), node.first_available_font().pixel_metrics(), node.line_height() },
|
||||
.root_font_metrics = { root_element->layout_node()->computed_values().font_size(), root_element->layout_node()->first_available_font().pixel_metrics(), root_element->layout_node()->line_height() },
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -169,12 +169,12 @@ CSSPixels Length::to_px(Layout::Node const& layout_node) const
|
|||
|
||||
FontMetrics font_metrics {
|
||||
layout_node.computed_values().font_size(),
|
||||
layout_node.font().pixel_metrics(),
|
||||
layout_node.first_available_font().pixel_metrics(),
|
||||
layout_node.line_height()
|
||||
};
|
||||
FontMetrics root_font_metrics {
|
||||
root_element->layout_node()->computed_values().font_size(),
|
||||
root_element->layout_node()->font().pixel_metrics(),
|
||||
root_element->layout_node()->first_available_font().pixel_metrics(),
|
||||
root_element->layout_node()->line_height()
|
||||
};
|
||||
|
||||
|
|
|
@ -91,15 +91,18 @@ StyleComputer::~StyleComputer() = default;
|
|||
|
||||
class StyleComputer::FontLoader : public ResourceClient {
|
||||
public:
|
||||
explicit FontLoader(StyleComputer& style_computer, FlyString family_name, Vector<AK::URL> urls)
|
||||
explicit FontLoader(StyleComputer& style_computer, FlyString family_name, Vector<Gfx::UnicodeRange> unicode_ranges, Vector<AK::URL> urls)
|
||||
: m_style_computer(style_computer)
|
||||
, m_family_name(move(family_name))
|
||||
, m_unicode_ranges(move(unicode_ranges))
|
||||
, m_urls(move(urls))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~FontLoader() override { }
|
||||
|
||||
Vector<Gfx::UnicodeRange> const& unicode_ranges() const { return m_unicode_ranges; }
|
||||
|
||||
virtual void resource_did_load() override
|
||||
{
|
||||
auto result = try_load_font();
|
||||
|
@ -183,6 +186,7 @@ private:
|
|||
|
||||
StyleComputer& m_style_computer;
|
||||
FlyString m_family_name;
|
||||
Vector<Gfx::UnicodeRange> m_unicode_ranges;
|
||||
RefPtr<Gfx::VectorFont> m_vector_font;
|
||||
Vector<AK::URL> m_urls;
|
||||
|
||||
|
@ -191,14 +195,21 @@ private:
|
|||
|
||||
struct StyleComputer::MatchingFontCandidate {
|
||||
FontFaceKey key;
|
||||
Variant<FontLoader*, Gfx::Typeface const*> loader_or_typeface;
|
||||
Variant<FontLoaderList*, Gfx::Typeface const*> loader_or_typeface;
|
||||
|
||||
[[nodiscard]] RefPtr<Gfx::Font const> font_with_point_size(float point_size) const
|
||||
[[nodiscard]] RefPtr<Gfx::FontCascadeList const> font_with_point_size(float point_size) const
|
||||
{
|
||||
if (auto* loader = loader_or_typeface.get_pointer<FontLoader*>(); loader) {
|
||||
return (*loader)->font_with_point_size(point_size);
|
||||
RefPtr<Gfx::FontCascadeList> font_list = Gfx::FontCascadeList::create();
|
||||
if (auto* loader_list = loader_or_typeface.get_pointer<FontLoaderList*>(); loader_list) {
|
||||
for (auto const& loader : **loader_list) {
|
||||
if (auto font = loader->font_with_point_size(point_size); font)
|
||||
font_list->add(*font, loader->unicode_ranges());
|
||||
}
|
||||
return font_list;
|
||||
}
|
||||
return loader_or_typeface.get<Gfx::Typeface const*>()->get_font(point_size);
|
||||
|
||||
font_list->add(*loader_or_typeface.get<Gfx::Typeface const*>()->get_font(point_size));
|
||||
return font_list;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1529,7 +1540,7 @@ Length::FontMetrics StyleComputer::calculate_root_element_font_metrics(StyleProp
|
|||
{
|
||||
auto root_value = style.property(CSS::PropertyID::FontSize);
|
||||
|
||||
auto font_pixel_metrics = style.computed_font().pixel_metrics();
|
||||
auto font_pixel_metrics = style.first_available_computed_font().pixel_metrics();
|
||||
Length::FontMetrics font_metrics { m_default_font_metrics.font_size, font_pixel_metrics, CSSPixels::nearest_value_for(font_pixel_metrics.line_spacing()) };
|
||||
font_metrics.font_size = root_value->as_length().length().to_px(viewport_rect(), font_metrics, font_metrics);
|
||||
font_metrics.line_height = style.line_height(viewport_rect(), font_metrics, font_metrics);
|
||||
|
@ -1537,7 +1548,7 @@ Length::FontMetrics StyleComputer::calculate_root_element_font_metrics(StyleProp
|
|||
return font_metrics;
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Font const> StyleComputer::find_matching_font_weight_ascending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive)
|
||||
RefPtr<Gfx::FontCascadeList const> StyleComputer::find_matching_font_weight_ascending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive)
|
||||
{
|
||||
using Fn = AK::Function<bool(MatchingFontCandidate const&)>;
|
||||
auto pred = inclusive ? Fn([&](auto const& matching_font_candidate) { return matching_font_candidate.key.weight >= target_weight; })
|
||||
|
@ -1550,7 +1561,7 @@ RefPtr<Gfx::Font const> StyleComputer::find_matching_font_weight_ascending(Vecto
|
|||
return {};
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Font const> StyleComputer::find_matching_font_weight_descending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive)
|
||||
RefPtr<Gfx::FontCascadeList const> StyleComputer::find_matching_font_weight_descending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive)
|
||||
{
|
||||
using Fn = AK::Function<bool(MatchingFontCandidate const&)>;
|
||||
auto pred = inclusive ? Fn([&](auto const& matching_font_candidate) { return matching_font_candidate.key.weight <= target_weight; })
|
||||
|
@ -1565,14 +1576,14 @@ RefPtr<Gfx::Font const> StyleComputer::find_matching_font_weight_descending(Vect
|
|||
|
||||
// Partial implementation of the font-matching algorithm: https://www.w3.org/TR/css-fonts-4/#font-matching-algorithm
|
||||
// FIXME: This should be replaced by the full CSS font selection algorithm.
|
||||
RefPtr<Gfx::Font const> StyleComputer::font_matching_algorithm(FontFaceKey const& key, float font_size_in_pt) const
|
||||
RefPtr<Gfx::FontCascadeList const> StyleComputer::font_matching_algorithm(FontFaceKey const& key, float font_size_in_pt) const
|
||||
{
|
||||
// If a font family match occurs, the user agent assembles the set of font faces in that family and then
|
||||
// narrows the set to a single face using other font properties in the order given below.
|
||||
Vector<MatchingFontCandidate> matching_family_fonts;
|
||||
for (auto const& font_key_and_loader : m_loaded_fonts) {
|
||||
if (font_key_and_loader.key.family_name.equals_ignoring_ascii_case(key.family_name))
|
||||
matching_family_fonts.empend(font_key_and_loader.key, font_key_and_loader.value.ptr());
|
||||
matching_family_fonts.empend(font_key_and_loader.key, const_cast<FontLoaderList*>(&font_key_and_loader.value));
|
||||
}
|
||||
Gfx::FontDatabase::the().for_each_typeface_with_family_name(key.family_name.to_string(), [&](Gfx::Typeface const& typeface) {
|
||||
matching_family_fonts.empend(
|
||||
|
@ -1634,7 +1645,7 @@ RefPtr<Gfx::Font const> StyleComputer::font_matching_algorithm(FontFaceKey const
|
|||
return {};
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth) const
|
||||
RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth) const
|
||||
{
|
||||
auto* parent_element = element_to_inherit_style_from(element, pseudo_element);
|
||||
|
||||
|
@ -1649,7 +1660,7 @@ RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Elemen
|
|||
auto parent_line_height = parent_or_root_element_line_height(element, pseudo_element);
|
||||
Gfx::FontPixelMetrics font_pixel_metrics;
|
||||
if (parent_element && parent_element->computed_css_values())
|
||||
font_pixel_metrics = parent_element->computed_css_values()->computed_font().pixel_metrics();
|
||||
font_pixel_metrics = parent_element->computed_css_values()->first_available_computed_font().pixel_metrics();
|
||||
else
|
||||
font_pixel_metrics = Platform::FontPlugin::the().default_font().pixel_metrics();
|
||||
auto parent_font_size = [&]() -> CSSPixels {
|
||||
|
@ -1746,7 +1757,7 @@ RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Elemen
|
|||
// and smaller may compute the font size to the previous entry in the table.
|
||||
if (identifier == CSS::ValueID::Smaller || identifier == CSS::ValueID::Larger) {
|
||||
if (parent_element && parent_element->computed_css_values()) {
|
||||
font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_css_values()->computed_font().pixel_metrics().size);
|
||||
font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_css_values()->first_available_computed_font().pixel_metrics().size);
|
||||
}
|
||||
}
|
||||
font_size_in_px *= get_absolute_size_mapping(identifier);
|
||||
|
@ -1787,7 +1798,7 @@ RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Elemen
|
|||
|
||||
float const font_size_in_pt = font_size_in_px * 0.75f;
|
||||
|
||||
auto find_font = [&](FlyString const& family) -> RefPtr<Gfx::Font const> {
|
||||
auto find_font = [&](FlyString const& family) -> RefPtr<Gfx::FontCascadeList const> {
|
||||
font_selector = { family, font_size_in_pt, weight, width, slope };
|
||||
|
||||
FontFaceKey key {
|
||||
|
@ -1796,25 +1807,29 @@ RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Elemen
|
|||
.slope = slope,
|
||||
};
|
||||
|
||||
auto result = Gfx::FontCascadeList::create();
|
||||
if (auto it = m_loaded_fonts.find(key); it != m_loaded_fonts.end()) {
|
||||
auto& loader = *it->value;
|
||||
if (auto found_font = loader.font_with_point_size(font_size_in_pt))
|
||||
return found_font;
|
||||
auto const& loaders = it->value;
|
||||
for (auto const& loader : loaders) {
|
||||
if (auto found_font = loader->font_with_point_size(font_size_in_pt))
|
||||
result->add(*found_font, loader->unicode_ranges());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (auto found_font = m_font_cache.get(font_selector))
|
||||
if (auto found_font = font_matching_algorithm(key, font_size_in_pt); found_font && !found_font->is_empty()) {
|
||||
return found_font;
|
||||
}
|
||||
|
||||
if (auto found_font = font_matching_algorithm(key, font_size_in_pt))
|
||||
return found_font;
|
||||
|
||||
if (auto found_font = Gfx::FontDatabase::the().get(family, font_size_in_pt, weight, width, slope, Gfx::Font::AllowInexactSizeMatch::Yes))
|
||||
return found_font;
|
||||
if (auto found_font = Gfx::FontDatabase::the().get(family, font_size_in_pt, weight, width, slope, Gfx::Font::AllowInexactSizeMatch::Yes)) {
|
||||
result->add(*found_font);
|
||||
return result;
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
auto find_generic_font = [&](ValueID font_id) -> RefPtr<Gfx::Font const> {
|
||||
auto find_generic_font = [&](ValueID font_id) -> RefPtr<Gfx::FontCascadeList const> {
|
||||
Platform::GenericFont generic_font {};
|
||||
switch (font_id) {
|
||||
case ValueID::Monospace:
|
||||
|
@ -1849,40 +1864,38 @@ RefPtr<Gfx::Font const> StyleComputer::compute_font_for_style_values(DOM::Elemen
|
|||
return find_font(Platform::FontPlugin::the().generic_font_name(generic_font));
|
||||
};
|
||||
|
||||
RefPtr<Gfx::Font const> found_font;
|
||||
|
||||
auto font_list = Gfx::FontCascadeList::create();
|
||||
if (font_family.is_value_list()) {
|
||||
auto const& family_list = static_cast<StyleValueList const&>(font_family).values();
|
||||
for (auto const& family : family_list) {
|
||||
RefPtr<Gfx::FontCascadeList const> other_font_list;
|
||||
if (family->is_identifier()) {
|
||||
found_font = find_generic_font(family->to_identifier());
|
||||
other_font_list = find_generic_font(family->to_identifier());
|
||||
} else if (family->is_string()) {
|
||||
found_font = find_font(family->as_string().string_value());
|
||||
other_font_list = find_font(family->as_string().string_value());
|
||||
} else if (family->is_custom_ident()) {
|
||||
found_font = find_font(family->as_custom_ident().custom_ident());
|
||||
other_font_list = find_font(family->as_custom_ident().custom_ident());
|
||||
}
|
||||
if (found_font)
|
||||
break;
|
||||
if (other_font_list)
|
||||
font_list->extend(*other_font_list);
|
||||
}
|
||||
} else if (font_family.is_identifier()) {
|
||||
found_font = find_generic_font(font_family.to_identifier());
|
||||
if (auto other_font_list = find_generic_font(font_family.to_identifier()))
|
||||
font_list->extend(*other_font_list);
|
||||
} else if (font_family.is_string()) {
|
||||
found_font = find_font(font_family.as_string().string_value());
|
||||
if (auto other_font_list = find_font(font_family.as_string().string_value()))
|
||||
font_list->extend(*other_font_list);
|
||||
} else if (font_family.is_custom_ident()) {
|
||||
found_font = find_font(font_family.as_custom_ident().custom_ident());
|
||||
if (auto other_font_list = find_font(font_family.as_custom_ident().custom_ident()))
|
||||
font_list->extend(*other_font_list);
|
||||
}
|
||||
|
||||
if (!found_font) {
|
||||
found_font = StyleProperties::font_fallback(monospace, bold);
|
||||
if (found_font) {
|
||||
if (auto scaled_fallback_font = found_font->with_size(font_size_in_pt))
|
||||
found_font = scaled_fallback_font;
|
||||
}
|
||||
auto found_font = StyleProperties::font_fallback(monospace, bold);
|
||||
if (auto scaled_fallback_font = found_font->with_size(font_size_in_pt)) {
|
||||
font_list->add(*scaled_fallback_font);
|
||||
}
|
||||
|
||||
m_font_cache.set(font_selector, *found_font);
|
||||
|
||||
return found_font;
|
||||
return font_list;
|
||||
}
|
||||
|
||||
void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element) const
|
||||
|
@ -1902,12 +1915,16 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
|
|||
auto font_weight = style.property(CSS::PropertyID::FontWeight);
|
||||
auto font_stretch = style.property(CSS::PropertyID::FontStretch);
|
||||
|
||||
auto found_font = compute_font_for_style_values(element, pseudo_element, font_family, font_size, font_style, font_weight, font_stretch, style.math_depth());
|
||||
auto font_list = compute_font_for_style_values(element, pseudo_element, font_family, font_size, font_style, font_weight, font_stretch, style.math_depth());
|
||||
VERIFY(font_list);
|
||||
VERIFY(!font_list->is_empty());
|
||||
|
||||
RefPtr<Gfx::Font const> const found_font = font_list->first();
|
||||
|
||||
style.set_property(CSS::PropertyID::FontSize, LengthStyleValue::create(CSS::Length::make_px(CSSPixels::nearest_value_for(found_font->pixel_size()))), nullptr);
|
||||
style.set_property(CSS::PropertyID::FontWeight, NumberStyleValue::create(font_weight->to_font_weight()));
|
||||
|
||||
style.set_computed_font(found_font.release_nonnull());
|
||||
style.set_computed_font_list(*font_list);
|
||||
|
||||
if (element && is<HTML::HTMLHtmlElement>(*element)) {
|
||||
const_cast<StyleComputer&>(*this).m_root_element_font_metrics = calculate_root_element_font_metrics(style);
|
||||
|
@ -1928,7 +1945,7 @@ CSSPixels StyleComputer::parent_or_root_element_line_height(DOM::Element const*
|
|||
auto const* computed_values = parent_element->computed_css_values();
|
||||
if (!computed_values)
|
||||
return m_root_element_font_metrics.line_height;
|
||||
auto parent_font_pixel_metrics = computed_values->computed_font().pixel_metrics();
|
||||
auto parent_font_pixel_metrics = computed_values->first_available_computed_font().pixel_metrics();
|
||||
auto parent_font_size = computed_values->property(CSS::PropertyID::FontSize)->as_length().length();
|
||||
// FIXME: Can the parent font size be non-absolute here?
|
||||
auto parent_font_size_value = parent_font_size.is_absolute() ? parent_font_size.absolute_length_to_px() : m_root_element_font_metrics.font_size;
|
||||
|
@ -1941,7 +1958,7 @@ void StyleComputer::absolutize_values(StyleProperties& style, DOM::Element const
|
|||
{
|
||||
auto parent_or_root_line_height = parent_or_root_element_line_height(element, pseudo_element);
|
||||
|
||||
auto font_pixel_metrics = style.computed_font().pixel_metrics();
|
||||
auto font_pixel_metrics = style.first_available_computed_font().pixel_metrics();
|
||||
|
||||
Length::FontMetrics font_metrics { m_root_element_font_metrics.font_size, font_pixel_metrics, parent_or_root_line_height };
|
||||
|
||||
|
@ -2367,8 +2384,6 @@ void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet)
|
|||
.weight = font_face.weight().value_or(0),
|
||||
.slope = font_face.slope().value_or(0),
|
||||
};
|
||||
if (m_loaded_fonts.contains(key))
|
||||
continue;
|
||||
|
||||
Vector<AK::URL> urls;
|
||||
for (auto& source : font_face.sources()) {
|
||||
|
@ -2381,8 +2396,15 @@ void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet)
|
|||
if (urls.is_empty())
|
||||
continue;
|
||||
|
||||
auto loader = make<FontLoader>(const_cast<StyleComputer&>(*this), font_face.font_family(), move(urls));
|
||||
const_cast<StyleComputer&>(*this).m_loaded_fonts.set(key, move(loader));
|
||||
auto loader = make<FontLoader>(const_cast<StyleComputer&>(*this), font_face.font_family(), font_face.unicode_ranges(), move(urls));
|
||||
auto maybe_font_loaders_list = const_cast<StyleComputer&>(*this).m_loaded_fonts.get(key);
|
||||
if (maybe_font_loaders_list.has_value()) {
|
||||
maybe_font_loaders_list->append(move(loader));
|
||||
} else {
|
||||
FontLoaderList loaders;
|
||||
loaders.append(move(loader));
|
||||
const_cast<StyleComputer&>(*this).m_loaded_fonts.set(key, move(loaders));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
|
||||
void load_fonts_from_sheet(CSSStyleSheet const&);
|
||||
|
||||
RefPtr<Gfx::Font const> compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth = 0) const;
|
||||
RefPtr<Gfx::FontCascadeList const> compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement> pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth = 0) const;
|
||||
|
||||
struct AnimationKey {
|
||||
CSS::CSSStyleDeclaration const* source_declaration;
|
||||
|
@ -123,9 +123,9 @@ private:
|
|||
|
||||
ErrorOr<RefPtr<StyleProperties>> compute_style_impl(DOM::Element&, Optional<CSS::Selector::PseudoElement>, ComputeStyleMode) const;
|
||||
ErrorOr<void> compute_cascaded_values(StyleProperties&, DOM::Element&, Optional<CSS::Selector::PseudoElement>, bool& did_match_any_pseudo_element_rules, ComputeStyleMode) const;
|
||||
static RefPtr<Gfx::Font const> find_matching_font_weight_ascending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
||||
static RefPtr<Gfx::Font const> find_matching_font_weight_descending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
||||
RefPtr<Gfx::Font const> font_matching_algorithm(FontFaceKey const& key, float font_size_in_pt) const;
|
||||
static RefPtr<Gfx::FontCascadeList const> find_matching_font_weight_ascending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
||||
static RefPtr<Gfx::FontCascadeList const> find_matching_font_weight_descending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
||||
RefPtr<Gfx::FontCascadeList const> font_matching_algorithm(FontFaceKey const& key, float font_size_in_pt) const;
|
||||
void compute_font(StyleProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement>) const;
|
||||
void compute_math_depth(StyleProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement>) const;
|
||||
void compute_defaulted_values(StyleProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement>) const;
|
||||
|
@ -186,7 +186,8 @@ private:
|
|||
|
||||
mutable FontCache m_font_cache;
|
||||
|
||||
HashMap<FontFaceKey, NonnullOwnPtr<FontLoader>> m_loaded_fonts;
|
||||
using FontLoaderList = Vector<NonnullOwnPtr<FontLoader>>;
|
||||
HashMap<FontFaceKey, FontLoaderList> m_loaded_fonts;
|
||||
|
||||
Length::FontMetrics m_default_font_metrics;
|
||||
Length::FontMetrics m_root_element_font_metrics;
|
||||
|
|
|
@ -191,7 +191,7 @@ CSSPixels StyleProperties::line_height(Layout::Node const& layout_node) const
|
|||
auto line_height = property(CSS::PropertyID::LineHeight);
|
||||
|
||||
if (line_height->is_identifier() && line_height->to_identifier() == ValueID::Normal)
|
||||
return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing());
|
||||
return CSSPixels::nearest_value_for(layout_node.first_available_font().pixel_metrics().line_spacing());
|
||||
|
||||
if (line_height->is_length()) {
|
||||
auto line_height_length = line_height->as_length().length();
|
||||
|
@ -213,7 +213,7 @@ CSSPixels StyleProperties::line_height(Layout::Node const& layout_node) const
|
|||
auto resolved = line_height->as_calculated().resolve_number();
|
||||
if (!resolved.has_value()) {
|
||||
dbgln("FIXME: Failed to resolve calc() line-height (number): {}", line_height->as_calculated().to_string());
|
||||
return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing());
|
||||
return CSSPixels::nearest_value_for(layout_node.first_available_font().pixel_metrics().line_spacing());
|
||||
}
|
||||
return Length(resolved.value(), Length::Type::Em).to_px(layout_node);
|
||||
}
|
||||
|
@ -221,12 +221,12 @@ CSSPixels StyleProperties::line_height(Layout::Node const& layout_node) const
|
|||
auto resolved = line_height->as_calculated().resolve_length(layout_node);
|
||||
if (!resolved.has_value()) {
|
||||
dbgln("FIXME: Failed to resolve calc() line-height: {}", line_height->as_calculated().to_string());
|
||||
return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing());
|
||||
return CSSPixels::nearest_value_for(layout_node.first_available_font().pixel_metrics().line_spacing());
|
||||
}
|
||||
return resolved->to_px(layout_node);
|
||||
}
|
||||
|
||||
return CSSPixels::nearest_value_for(layout_node.font().pixel_metrics().line_spacing());
|
||||
return CSSPixels::nearest_value_for(layout_node.first_available_font().pixel_metrics().line_spacing());
|
||||
}
|
||||
|
||||
Optional<int> StyleProperties::z_index() const
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <AK/HashMap.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/FontCascadeList.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibWeb/CSS/ComputedValues.h>
|
||||
#include <LibWeb/CSS/LengthBox.h>
|
||||
|
@ -22,8 +23,6 @@ public:
|
|||
|
||||
static NonnullRefPtr<StyleProperties> create() { return adopt_ref(*new StyleProperties); }
|
||||
|
||||
NonnullRefPtr<StyleProperties> clone() const;
|
||||
|
||||
template<typename Callback>
|
||||
inline void for_each_property(Callback callback) const
|
||||
{
|
||||
|
@ -128,15 +127,17 @@ public:
|
|||
float stroke_opacity() const;
|
||||
Optional<CSS::FillRule> fill_rule() const;
|
||||
|
||||
Gfx::Font const& computed_font() const
|
||||
Gfx::Font const& first_available_computed_font() const { return m_font_list->first(); }
|
||||
|
||||
Gfx::FontCascadeList const& computed_font_list() const
|
||||
{
|
||||
VERIFY(m_font);
|
||||
return *m_font;
|
||||
VERIFY(m_font_list);
|
||||
return *m_font_list;
|
||||
}
|
||||
|
||||
void set_computed_font(NonnullRefPtr<Gfx::Font const> font)
|
||||
void set_computed_font_list(NonnullRefPtr<Gfx::FontCascadeList> font_list) const
|
||||
{
|
||||
m_font = move(font);
|
||||
m_font_list = move(font_list);
|
||||
}
|
||||
|
||||
CSSPixels line_height(CSSPixelRect const& viewport_rect, Length::FontMetrics const& font_metrics, Length::FontMetrics const& root_font_metrics) const;
|
||||
|
@ -162,7 +163,7 @@ private:
|
|||
Vector<CSS::ShadowData> shadow(CSS::PropertyID, Layout::Node const&) const;
|
||||
|
||||
int m_math_depth { InitialValues::math_depth() };
|
||||
mutable RefPtr<Gfx::Font const> m_font;
|
||||
mutable RefPtr<Gfx::FontCascadeList> m_font_list;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -492,7 +492,7 @@ static Element::RequiredInvalidationAfterStyleChange compute_required_invalidati
|
|||
{
|
||||
Element::RequiredInvalidationAfterStyleChange invalidation;
|
||||
|
||||
if (&old_style.computed_font() != &new_style.computed_font())
|
||||
if (!old_style.computed_font_list().equals(new_style.computed_font_list()))
|
||||
invalidation.relayout = true;
|
||||
|
||||
for (auto i = to_underlying(CSS::first_property_id); i <= to_underlying(CSS::last_property_id); ++i) {
|
||||
|
|
|
@ -58,7 +58,8 @@ public:
|
|||
auto& font_stretch = *font_style_value.longhand(CSS::PropertyID::FontStretch);
|
||||
auto& font_size = *font_style_value.longhand(CSS::PropertyID::FontSize);
|
||||
auto& font_family = *font_style_value.longhand(CSS::PropertyID::FontFamily);
|
||||
my_drawing_state().current_font = canvas_element.document().style_computer().compute_font_for_style_values(&canvas_element, {}, font_family, font_size, font_style, font_weight, font_stretch);
|
||||
auto font_list = canvas_element.document().style_computer().compute_font_for_style_values(&canvas_element, {}, font_family, font_size, font_style, font_weight, font_stretch);
|
||||
my_drawing_state().current_font = font_list->first();
|
||||
}
|
||||
|
||||
Bindings::CanvasTextAlign text_align() const { return my_drawing_state().text_align; }
|
||||
|
|
|
@ -1093,17 +1093,17 @@ void BlockFormattingContext::layout_list_item_marker(ListItemBox const& list_ite
|
|||
image_height = list_style_image->natural_height().value_or(0);
|
||||
}
|
||||
|
||||
CSSPixels default_marker_width = max(4, marker.font().pixel_size_rounded_up() - 4);
|
||||
CSSPixels default_marker_width = max(4, marker.first_available_font().pixel_size_rounded_up() - 4);
|
||||
|
||||
auto marker_text = marker.text().value_or("");
|
||||
if (marker_text.is_empty()) {
|
||||
marker_state.set_content_width(image_width + default_marker_width);
|
||||
} else {
|
||||
auto text_width = marker.font().width(marker_text);
|
||||
auto text_width = marker.first_available_font().width(marker_text);
|
||||
marker_state.set_content_width(image_width + CSSPixels::nearest_value_for(text_width));
|
||||
}
|
||||
|
||||
marker_state.set_content_height(max(image_height, marker.font().pixel_size_rounded_up() + 1));
|
||||
marker_state.set_content_height(max(image_height, marker.first_available_font().pixel_size_rounded_up() + 1));
|
||||
|
||||
auto final_marker_width = marker_state.content_width() + default_marker_width;
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ void ButtonBox::prepare_for_replaced_layout()
|
|||
// value attribute. This is not the case with <button />, which contains
|
||||
// its contents normally.
|
||||
if (is<HTML::HTMLInputElement>(dom_node())) {
|
||||
set_natural_width(CSSPixels::nearest_value_for(font().width(static_cast<HTML::HTMLInputElement&>(dom_node()).value())));
|
||||
set_natural_height(font().pixel_size_rounded_up());
|
||||
set_natural_width(CSSPixels::nearest_value_for(first_available_font().width(static_cast<HTML::HTMLInputElement&>(dom_node()).value())));
|
||||
set_natural_height(first_available_font().pixel_size_rounded_up());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1720,7 +1720,7 @@ CSSPixels FormattingContext::box_baseline(Box const& box) const
|
|||
return box.computed_values().font_size();
|
||||
case CSS::VerticalAlign::TextBottom:
|
||||
// TextTop: Align the bottom of the box with the bottom of the parent's content area (see 10.6.1).
|
||||
return box_state.content_height() - CSSPixels::nearest_value_for(box.containing_block()->font().pixel_metrics().descent * 2);
|
||||
return box_state.content_height() - CSSPixels::nearest_value_for(box.containing_block()->first_available_font().pixel_metrics().descent * 2);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -190,14 +190,14 @@ Optional<InlineLevelIterator::Item> InlineLevelIterator::next_without_lookahead(
|
|||
Vector<Gfx::DrawGlyphOrEmoji> glyph_run;
|
||||
float glyph_run_width = 0;
|
||||
Gfx::for_each_glyph_position(
|
||||
{ 0, 0 }, chunk.view, text_node.font(), [&](Gfx::DrawGlyphOrEmoji const& glyph_or_emoji) {
|
||||
{ 0, 0 }, chunk.view, text_node.first_available_font(), [&](Gfx::DrawGlyphOrEmoji const& glyph_or_emoji) {
|
||||
glyph_run.append(glyph_or_emoji);
|
||||
return IterationDecision::Continue;
|
||||
},
|
||||
Gfx::IncludeLeftBearing::No, glyph_run_width);
|
||||
|
||||
if (!m_text_node_context->is_last_chunk)
|
||||
glyph_run_width += text_node.font().glyph_spacing();
|
||||
glyph_run_width += text_node.first_available_font().glyph_spacing();
|
||||
|
||||
CSSPixels chunk_width = CSSPixels::nearest_value_for(glyph_run_width);
|
||||
|
||||
|
|
|
@ -70,7 +70,8 @@ void LineBox::trim_trailing_whitespace()
|
|||
if (!is_ascii_space(last_character))
|
||||
break;
|
||||
|
||||
int last_character_width = last_fragment->layout_node().font().glyph_width(last_character);
|
||||
// FIXME: Use fragment's glyph run to determine the width of the last character.
|
||||
int last_character_width = last_fragment->layout_node().first_available_font().glyph_width(last_character);
|
||||
last_fragment->m_length -= 1;
|
||||
last_fragment->set_width(last_fragment->width() - last_character_width);
|
||||
m_width -= last_character_width;
|
||||
|
|
|
@ -47,7 +47,7 @@ int LineBoxFragment::text_index_at(CSSPixels x) const
|
|||
if (!is<TextNode>(layout_node()))
|
||||
return 0;
|
||||
auto& layout_text = verify_cast<TextNode>(layout_node());
|
||||
auto& font = layout_text.font();
|
||||
auto& font = layout_text.first_available_font();
|
||||
Utf8View view(text());
|
||||
|
||||
CSSPixels relative_x = x - absolute_x();
|
||||
|
|
|
@ -192,7 +192,7 @@ void LineBuilder::update_last_line()
|
|||
}
|
||||
|
||||
auto strut_baseline = [&] {
|
||||
auto& font = m_context.containing_block().font();
|
||||
auto& font = m_context.containing_block().first_available_font();
|
||||
auto const line_height = m_context.containing_block().line_height();
|
||||
auto const font_metrics = font.pixel_metrics();
|
||||
auto const typographic_height = CSSPixels::nearest_value_for(font_metrics.ascent + font_metrics.descent);
|
||||
|
@ -204,7 +204,7 @@ void LineBuilder::update_last_line()
|
|||
auto line_box_baseline = [&] {
|
||||
CSSPixels line_box_baseline = strut_baseline;
|
||||
for (auto& fragment : line_box.fragments()) {
|
||||
auto const& font = fragment.layout_node().font();
|
||||
auto const& font = fragment.layout_node().first_available_font();
|
||||
auto const line_height = fragment.layout_node().line_height();
|
||||
auto const font_metrics = font.pixel_metrics();
|
||||
auto const typographic_height = CSSPixels::nearest_value_for(font_metrics.ascent + font_metrics.descent);
|
||||
|
@ -301,7 +301,7 @@ void LineBuilder::update_last_line()
|
|||
top_of_inline_box = (fragment.offset().y() - fragment_box_state.margin_box_top());
|
||||
bottom_of_inline_box = (fragment.offset().y() + fragment_box_state.content_height() + fragment_box_state.margin_box_bottom());
|
||||
} else {
|
||||
auto font_metrics = fragment.layout_node().font().pixel_metrics();
|
||||
auto font_metrics = fragment.layout_node().first_available_font().pixel_metrics();
|
||||
auto typographic_height = CSSPixels::nearest_value_for(font_metrics.ascent + font_metrics.descent);
|
||||
auto leading = fragment.layout_node().line_height() - typographic_height;
|
||||
auto half_leading = leading / 2;
|
||||
|
|
|
@ -349,7 +349,7 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
|
|||
// NOTE: We have to be careful that font-related properties get set in the right order.
|
||||
// m_font is used by Length::to_px() when resolving sizes against this layout node.
|
||||
// That's why it has to be set before everything else.
|
||||
m_font = computed_style.computed_font();
|
||||
m_font_list = computed_style.computed_font_list();
|
||||
computed_values.set_font_size(computed_style.property(CSS::PropertyID::FontSize)->as_length().length().to_px(*this));
|
||||
computed_values.set_font_weight(round_to<int>(computed_style.property(CSS::PropertyID::FontWeight)->as_number().number()));
|
||||
m_line_height = computed_style.line_height(*this);
|
||||
|
@ -930,7 +930,7 @@ JS::NonnullGCPtr<NodeWithStyle> NodeWithStyle::create_anonymous_wrapper() const
|
|||
{
|
||||
auto wrapper = heap().allocate_without_realm<BlockContainer>(const_cast<DOM::Document&>(document()), nullptr, m_computed_values.clone_inherited_values());
|
||||
static_cast<CSS::MutableComputedValues&>(wrapper->m_computed_values).set_display(CSS::Display(CSS::DisplayOutside::Block, CSS::DisplayInside::Flow));
|
||||
wrapper->m_font = m_font;
|
||||
wrapper->m_font_list = m_font_list;
|
||||
wrapper->m_line_height = m_line_height;
|
||||
return *wrapper;
|
||||
}
|
||||
|
|
|
@ -143,7 +143,8 @@ public:
|
|||
|
||||
bool can_contain_boxes_with_position_absolute() const;
|
||||
|
||||
Gfx::Font const& font() const;
|
||||
Gfx::FontCascadeList const& font_list() const;
|
||||
Gfx::Font const& first_available_font() const;
|
||||
Gfx::Font const& scaled_font(PaintContext&) const;
|
||||
Gfx::Font const& scaled_font(float scale_factor) const;
|
||||
|
||||
|
@ -217,10 +218,11 @@ public:
|
|||
|
||||
void apply_style(const CSS::StyleProperties&);
|
||||
|
||||
Gfx::Font const& font() const { return *m_font; }
|
||||
Gfx::Font const& first_available_font() const;
|
||||
Gfx::FontCascadeList const& font_list() const { return *m_font_list; }
|
||||
CSSPixels line_height() const { return m_line_height; }
|
||||
void set_line_height(CSSPixels line_height) { m_line_height = line_height; }
|
||||
void set_font(Gfx::Font const& font) { m_font = font; }
|
||||
void set_font_list(Gfx::FontCascadeList const& font_list) { m_font_list = font_list; }
|
||||
Vector<CSS::BackgroundLayerData> const& background_layers() const { return computed_values().background_layers(); }
|
||||
const CSS::AbstractImageStyleValue* list_style_image() const { return m_list_style_image; }
|
||||
|
||||
|
@ -238,7 +240,7 @@ private:
|
|||
void reset_table_box_computed_values_used_by_wrapper_to_init_values();
|
||||
|
||||
CSS::ComputedValues m_computed_values;
|
||||
RefPtr<Gfx::Font const> m_font;
|
||||
RefPtr<Gfx::FontCascadeList const> m_font_list;
|
||||
CSSPixels m_line_height { 0 };
|
||||
RefPtr<CSS::AbstractImageStyleValue const> m_list_style_image;
|
||||
};
|
||||
|
@ -275,13 +277,20 @@ inline bool Node::has_style_or_parent_with_style() const
|
|||
return m_has_style || (parent() != nullptr && parent()->has_style_or_parent_with_style());
|
||||
}
|
||||
|
||||
inline Gfx::Font const& Node::font() const
|
||||
inline Gfx::Font const& Node::first_available_font() const
|
||||
{
|
||||
VERIFY(has_style_or_parent_with_style());
|
||||
|
||||
if (m_has_style)
|
||||
return static_cast<NodeWithStyle const*>(this)->font();
|
||||
return parent()->font();
|
||||
return static_cast<NodeWithStyle const*>(this)->first_available_font();
|
||||
return parent()->first_available_font();
|
||||
}
|
||||
|
||||
inline Gfx::FontCascadeList const& Node::font_list() const
|
||||
{
|
||||
VERIFY(has_style_or_parent_with_style());
|
||||
if (m_has_style)
|
||||
return static_cast<NodeWithStyle const*>(this)->font_list();
|
||||
return parent()->font_list();
|
||||
}
|
||||
|
||||
inline Gfx::Font const& Node::scaled_font(PaintContext& context) const
|
||||
|
@ -291,7 +300,7 @@ inline Gfx::Font const& Node::scaled_font(PaintContext& context) const
|
|||
|
||||
inline Gfx::Font const& Node::scaled_font(float scale_factor) const
|
||||
{
|
||||
return document().style_computer().font_cache().scaled_font(font(), scale_factor);
|
||||
return document().style_computer().font_cache().scaled_font(first_available_font(), scale_factor);
|
||||
}
|
||||
|
||||
inline const CSS::ImmutableComputedValues& Node::computed_values() const
|
||||
|
@ -322,4 +331,12 @@ inline NodeWithStyle* Node::parent()
|
|||
return static_cast<NodeWithStyle*>(TreeNode<Node>::parent());
|
||||
}
|
||||
|
||||
inline Gfx::Font const& NodeWithStyle::first_available_font() const
|
||||
{
|
||||
// https://drafts.csswg.org/css-fonts/#first-available-font
|
||||
// FIXME: Should be be the first font for which the character U+0020 (space) instead of
|
||||
// any first font in the list
|
||||
return m_font_list->first();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available
|
|||
} else if (is<SVGTextBox>(descendant)) {
|
||||
auto& text_element = static_cast<SVG::SVGTextPositioningElement&>(dom_node);
|
||||
|
||||
auto& font = graphics_box.font();
|
||||
auto& font = graphics_box.first_available_font();
|
||||
auto text_contents = text_element.text_contents();
|
||||
Utf8View text_utf8 { text_contents };
|
||||
auto text_width = font.width(text_utf8);
|
||||
|
|
|
@ -427,7 +427,7 @@ ErrorOr<void> TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::
|
|||
|
||||
auto content_box_computed_values = parent.computed_values().clone_inherited_values();
|
||||
auto content_box_wrapper = parent.heap().template allocate_without_realm<BlockContainer>(parent.document(), nullptr, move(content_box_computed_values));
|
||||
content_box_wrapper->set_font(parent.font());
|
||||
content_box_wrapper->set_font_list(parent.font_list());
|
||||
content_box_wrapper->set_line_height(parent.line_height());
|
||||
content_box_wrapper->set_children_are_inline(parent.children_are_inline());
|
||||
|
||||
|
@ -630,7 +630,7 @@ static void wrap_in_anonymous(Vector<JS::Handle<Node>>& sequence, Node* nearest_
|
|||
}
|
||||
wrapper->set_children_are_inline(parent.children_are_inline());
|
||||
wrapper->set_line_height(parent.line_height());
|
||||
wrapper->set_font(parent.font());
|
||||
wrapper->set_font_list(parent.font_list());
|
||||
if (nearest_sibling)
|
||||
parent.insert_before(*wrapper, *nearest_sibling);
|
||||
else
|
||||
|
@ -717,7 +717,7 @@ Vector<JS::Handle<Box>> TreeBuilder::generate_missing_parents(NodeWithStyle& roo
|
|||
|
||||
parent.remove_child(*table_box);
|
||||
wrapper->append_child(*table_box);
|
||||
wrapper->set_font(parent.font());
|
||||
wrapper->set_font_list(parent.font_list());
|
||||
wrapper->set_line_height(parent.line_height());
|
||||
|
||||
if (nearest_sibling)
|
||||
|
@ -753,7 +753,7 @@ static void fixup_row(Box& row_box, TableGrid const& table_grid, size_t row_inde
|
|||
// Ensure that the cell (with zero content height) will have the same height as the row by setting vertical-align to middle.
|
||||
cell_computed_values.set_vertical_align(CSS::VerticalAlign::Middle);
|
||||
auto cell_box = row_box.heap().template allocate_without_realm<BlockContainer>(row_box.document(), nullptr, cell_computed_values);
|
||||
cell_box->set_font(row_box.font());
|
||||
cell_box->set_font_list(row_box.font_list());
|
||||
cell_box->set_line_height(row_box.line_height());
|
||||
row_box.append_child(cell_box);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ void ButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
|
|||
painter.draw_text(
|
||||
text_rect.to_type<int>(),
|
||||
static_cast<HTML::HTMLInputElement const&>(dom_node).value(),
|
||||
document().style_computer().font_cache().scaled_font(layout_box().font(), context.device_pixels_per_css_pixel()),
|
||||
document().style_computer().font_cache().scaled_font(layout_box().first_available_font(), context.device_pixels_per_css_pixel()),
|
||||
Gfx::TextAlignment::Center,
|
||||
computed_values().color());
|
||||
painter.restore();
|
||||
|
|
|
@ -531,7 +531,7 @@ static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const
|
|||
auto fragment_rect = fragment.absolute_rect();
|
||||
|
||||
CSSPixelRect cursor_rect {
|
||||
fragment_rect.x() + CSSPixels::nearest_value_for(text_node.font().width(fragment.text().substring_view(0, text_node.browsing_context().cursor_position()->offset() - fragment.start()))),
|
||||
fragment_rect.x() + CSSPixels::nearest_value_for(text_node.first_available_font().width(fragment.text().substring_view(0, text_node.browsing_context().cursor_position()->offset() - fragment.start()))),
|
||||
fragment_rect.top(),
|
||||
1,
|
||||
fragment_rect.height()
|
||||
|
@ -545,7 +545,7 @@ static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const
|
|||
static void paint_text_decoration(PaintContext& context, Layout::Node const& text_node, Layout::LineBoxFragment const& fragment)
|
||||
{
|
||||
auto& painter = context.recording_painter();
|
||||
auto& font = fragment.layout_node().font();
|
||||
auto& font = fragment.layout_node().first_available_font();
|
||||
auto fragment_box = fragment.absolute_rect();
|
||||
CSSPixels glyph_height = CSSPixels::nearest_value_for(font.pixel_size());
|
||||
auto baseline = fragment_box.height() / 2 - (glyph_height + 4) / 2 + glyph_height;
|
||||
|
@ -650,7 +650,7 @@ static void paint_text_fragment(PaintContext& context, Layout::TextNode const& t
|
|||
}
|
||||
painter.draw_text_run(baseline_start.to_type<int>(), scaled_glyph_run, text_node.computed_values().color(), fragment_absolute_device_rect.to_type<int>());
|
||||
|
||||
auto selection_rect = context.enclosing_device_rect(fragment.selection_rect(text_node.font())).to_type<int>();
|
||||
auto selection_rect = context.enclosing_device_rect(fragment.selection_rect(text_node.first_available_font())).to_type<int>();
|
||||
if (!selection_rect.is_empty()) {
|
||||
painter.fill_rect(selection_rect, CSS::SystemColor::highlight());
|
||||
RecordingPainterStateSaver saver(painter);
|
||||
|
@ -720,7 +720,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
|||
layer.spread_distance.to_px(layout_box()),
|
||||
ShadowPlacement::Outer);
|
||||
}
|
||||
context.recording_painter().set_font(fragment.layout_node().font());
|
||||
context.recording_painter().set_font(fragment.layout_node().first_available_font());
|
||||
paint_text_shadow(context, fragment, resolved_shadow_data);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue