Skip to content

Commit

Permalink
LibWeb: Implement "preserves overrides" property of editing commands
Browse files Browse the repository at this point in the history
  • Loading branch information
gmta committed Dec 23, 2024
1 parent 5ecde24 commit b79ab2c
Show file tree
Hide file tree
Showing 9 changed files with 322 additions and 82 deletions.
68 changes: 37 additions & 31 deletions Libraries/LibWeb/CSS/StyleComputer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1767,6 +1767,41 @@ RefPtr<Gfx::FontCascadeList const> StyleComputer::font_matching_algorithm(FlyStr
return {};
}

CSSPixels StyleComputer::default_user_font_size() const
{
// FIXME: This value should be configurable by the user.
return 16;
}

// https://w3c.github.io/csswg-drafts/css-fonts/#absolute-size-mapping
CSSPixelFraction StyleComputer::absolute_size_mapping(Keyword keyword)
{
switch (keyword) {
case Keyword::XxSmall:
return CSSPixels(3) / 5;
case Keyword::XSmall:
return CSSPixels(3) / 4;
case Keyword::Small:
return CSSPixels(8) / 9;
case Keyword::Medium:
return 1;
case Keyword::Large:
return CSSPixels(6) / 5;
case Keyword::XLarge:
return CSSPixels(3) / 2;
case Keyword::XxLarge:
return 2;
case Keyword::XxxLarge:
return 3;
case Keyword::Smaller:
return CSSPixels(4) / 5;
case Keyword::Larger:
return CSSPixels(5) / 4;
default:
return 1;
}
}

RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement::Type> pseudo_element, CSSStyleValue const& font_family, CSSStyleValue const& font_size, CSSStyleValue const& font_style, CSSStyleValue const& font_weight, CSSStyleValue const& font_stretch, int math_depth) const
{
auto* parent_element = element_to_inherit_style_from(element, pseudo_element);
Expand All @@ -1776,8 +1811,7 @@ RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(
auto weight = font_weight.to_font_weight();
bool bold = weight > Gfx::FontWeight::Regular;

// FIXME: Should be based on "user's default font size"
CSSPixels font_size_in_px = 16;
auto font_size_in_px = default_user_font_size();

Gfx::FontPixelMetrics font_pixel_metrics;
if (parent_element && parent_element->computed_properties())
Expand All @@ -1800,34 +1834,6 @@ RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(
Length::FontMetrics font_metrics { parent_font_size(), font_pixel_metrics };

if (font_size.is_keyword()) {
// https://w3c.github.io/csswg-drafts/css-fonts/#absolute-size-mapping
auto get_absolute_size_mapping = [](Keyword keyword) -> CSSPixelFraction {
switch (keyword) {
case Keyword::XxSmall:
return CSSPixels(3) / 5;
case Keyword::XSmall:
return CSSPixels(3) / 4;
case Keyword::Small:
return CSSPixels(8) / 9;
case Keyword::Medium:
return 1;
case Keyword::Large:
return CSSPixels(6) / 5;
case Keyword::XLarge:
return CSSPixels(3) / 2;
case Keyword::XxLarge:
return 2;
case Keyword::XxxLarge:
return 3;
case Keyword::Smaller:
return CSSPixels(4) / 5;
case Keyword::Larger:
return CSSPixels(5) / 4;
default:
return 1;
}
};

auto const keyword = font_size.to_keyword();

if (keyword == Keyword::Math) {
Expand Down Expand Up @@ -1880,7 +1886,7 @@ RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(
font_size_in_px = CSSPixels::nearest_value_for(parent_element->computed_properties()->first_available_computed_font().pixel_metrics().size);
}
}
font_size_in_px *= get_absolute_size_mapping(keyword);
font_size_in_px *= absolute_size_mapping(keyword);
}
} else {
Length::ResolutionContext const length_resolution_context {
Expand Down
2 changes: 2 additions & 0 deletions Libraries/LibWeb/CSS/StyleComputer.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ class StyleComputer {
void load_fonts_from_sheet(CSSStyleSheet&);
void unload_fonts_from_sheet(CSSStyleSheet&);

CSSPixels default_user_font_size() const;
static CSSPixelFraction absolute_size_mapping(Keyword);
RefPtr<Gfx::FontCascadeList const> compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement::Type> pseudo_element, CSSStyleValue const& font_family, CSSStyleValue const& font_size, CSSStyleValue const& font_style, CSSStyleValue const& font_weight, CSSStyleValue const& font_stretch, int math_depth = 0) const;

void set_viewport_rect(Badge<DOM::Document>, CSSPixelRect const& viewport_rect) { m_viewport_rect = viewport_rect; }
Expand Down
3 changes: 3 additions & 0 deletions Libraries/LibWeb/Editing/Commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,7 @@ static Array const commands {
CommandDefinition {
.command = CommandNames::delete_,
.action = command_delete_action,
.preserves_overrides = true,
},
// https://w3c.github.io/editing/docs/execCommand/#the-defaultparagraphseparator-command
CommandDefinition {
Expand All @@ -809,11 +810,13 @@ static Array const commands {
CommandDefinition {
.command = CommandNames::insertLineBreak,
.action = command_insert_linebreak_action,
.preserves_overrides = true,
},
// https://w3c.github.io/editing/docs/execCommand/#the-insertparagraph-command
CommandDefinition {
.command = CommandNames::insertParagraph,
.action = command_insert_paragraph_action,
.preserves_overrides = true,
},
// https://w3c.github.io/editing/docs/execCommand/#the-stylewithcss-command
CommandDefinition {
Expand Down
3 changes: 3 additions & 0 deletions Libraries/LibWeb/Editing/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ struct CommandDefinition {
Function<String(DOM::Document const&)> value {};
Optional<CSS::PropertyID> relevant_css_property {};

// https://w3c.github.io/editing/docs/execCommand/#preserves-overrides
bool preserves_overrides { false };

// https://w3c.github.io/editing/docs/execCommand/#inline-command-activated-values
Vector<String> inline_activated_values {};
};
Expand Down
10 changes: 10 additions & 0 deletions Libraries/LibWeb/Editing/ExecCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,22 @@ bool Document::exec_command(FlyString const& command, [[maybe_unused]] bool show
// at the editing host that was actually affected.
}

// https://w3c.github.io/editing/docs/execCommand/#preserves-overrides
// If a command preserves overrides, then before taking its action, the user agent must record current overrides.
auto overrides = Editing::record_current_overrides(*this);

// 5. Take the action for command, passing value to the instructions as an argument.
auto optional_command = Editing::find_command_definition(command);
VERIFY(optional_command.has_value());
auto const& command_definition = optional_command.release_value();
auto command_result = command_definition.action(*this, value);

// https://w3c.github.io/editing/docs/execCommand/#preserves-overrides
// After taking the action, if the active range is collapsed, it must restore states and values from the recorded
// list.
if (m_selection && m_selection->is_collapsed())
Editing::restore_states_and_values(*this, overrides);

// 6. If the previous step returned false, return false.
if (!command_result)
return false;
Expand Down
Loading

0 comments on commit b79ab2c

Please sign in to comment.