mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 09:45:06 +02:00
LibWeb: Implement dominant-baseline for SVG text
This property determines the default baseline used to align content within the given box.
This commit is contained in:
committed by
Jelle Raaijmakers
parent
90a211bf47
commit
f05bc7c0cd
Notes:
github-actions[bot]
2026-02-26 08:24:27 +00:00
Author: https://github.com/tcl3 Commit: https://github.com/LadybirdBrowser/ladybird/commit/f05bc7c0cd3 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8173 Reviewed-by: https://github.com/gmta ✅
@@ -971,6 +971,12 @@ TextAnchor ComputedProperties::text_anchor() const
|
|||||||
return keyword_to_text_anchor(value.to_keyword()).release_value();
|
return keyword_to_text_anchor(value.to_keyword()).release_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<BaselineMetric> ComputedProperties::dominant_baseline() const
|
||||||
|
{
|
||||||
|
auto const& value = property(PropertyID::DominantBaseline);
|
||||||
|
return keyword_to_baseline_metric(value.to_keyword());
|
||||||
|
}
|
||||||
|
|
||||||
TextAlign ComputedProperties::text_align() const
|
TextAlign ComputedProperties::text_align() const
|
||||||
{
|
{
|
||||||
auto const& value = property(PropertyID::TextAlign);
|
auto const& value = property(PropertyID::TextAlign);
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ public:
|
|||||||
ColorInterpolation color_interpolation() const;
|
ColorInterpolation color_interpolation() const;
|
||||||
PreferredColorScheme color_scheme(PreferredColorScheme, Optional<Vector<String> const&> document_supported_schemes) const;
|
PreferredColorScheme color_scheme(PreferredColorScheme, Optional<Vector<String> const&> document_supported_schemes) const;
|
||||||
TextAnchor text_anchor() const;
|
TextAnchor text_anchor() const;
|
||||||
|
Optional<BaselineMetric> dominant_baseline() const;
|
||||||
TextAlign text_align() const;
|
TextAlign text_align() const;
|
||||||
TextJustify text_justify() const;
|
TextJustify text_justify() const;
|
||||||
TextOverflow text_overflow() const;
|
TextOverflow text_overflow() const;
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ public:
|
|||||||
static TransformBox transform_box() { return TransformBox::ViewBox; }
|
static TransformBox transform_box() { return TransformBox::ViewBox; }
|
||||||
static TransformStyle transform_style() { return TransformStyle::Flat; }
|
static TransformStyle transform_style() { return TransformStyle::Flat; }
|
||||||
static Direction direction() { return Direction::Ltr; }
|
static Direction direction() { return Direction::Ltr; }
|
||||||
|
static Optional<BaselineMetric> dominant_baseline() { return {}; }
|
||||||
static UnicodeBidi unicode_bidi() { return UnicodeBidi::Normal; }
|
static UnicodeBidi unicode_bidi() { return UnicodeBidi::Normal; }
|
||||||
static WritingMode writing_mode() { return WritingMode::HorizontalTb; }
|
static WritingMode writing_mode() { return WritingMode::HorizontalTb; }
|
||||||
static UserSelect user_select() { return UserSelect::Auto; }
|
static UserSelect user_select() { return UserSelect::Auto; }
|
||||||
@@ -594,6 +595,7 @@ public:
|
|||||||
ObjectFit object_fit() const { return m_noninherited.object_fit; }
|
ObjectFit object_fit() const { return m_noninherited.object_fit; }
|
||||||
Position object_position() const { return m_noninherited.object_position; }
|
Position object_position() const { return m_noninherited.object_position; }
|
||||||
Direction direction() const { return m_inherited.direction; }
|
Direction direction() const { return m_inherited.direction; }
|
||||||
|
Optional<BaselineMetric> dominant_baseline() const { return m_inherited.dominant_baseline; }
|
||||||
UnicodeBidi unicode_bidi() const { return m_noninherited.unicode_bidi; }
|
UnicodeBidi unicode_bidi() const { return m_noninherited.unicode_bidi; }
|
||||||
WritingMode writing_mode() const { return m_inherited.writing_mode; }
|
WritingMode writing_mode() const { return m_inherited.writing_mode; }
|
||||||
UserSelect user_select() const { return m_noninherited.user_select; }
|
UserSelect user_select() const { return m_noninherited.user_select; }
|
||||||
@@ -749,6 +751,7 @@ protected:
|
|||||||
ListStyleType list_style_type { InitialValues::list_style_type() };
|
ListStyleType list_style_type { InitialValues::list_style_type() };
|
||||||
QuotesData quotes { InitialValues::quotes() };
|
QuotesData quotes { InitialValues::quotes() };
|
||||||
Direction direction { InitialValues::direction() };
|
Direction direction { InitialValues::direction() };
|
||||||
|
Optional<BaselineMetric> dominant_baseline { InitialValues::dominant_baseline() };
|
||||||
WritingMode writing_mode { InitialValues::writing_mode() };
|
WritingMode writing_mode { InitialValues::writing_mode() };
|
||||||
FillRule fill_rule { InitialValues::fill_rule() };
|
FillRule fill_rule { InitialValues::fill_rule() };
|
||||||
StrokeLinecap stroke_linecap { InitialValues::stroke_linecap() };
|
StrokeLinecap stroke_linecap { InitialValues::stroke_linecap() };
|
||||||
@@ -1078,6 +1081,7 @@ public:
|
|||||||
void set_object_fit(ObjectFit value) { m_noninherited.object_fit = value; }
|
void set_object_fit(ObjectFit value) { m_noninherited.object_fit = value; }
|
||||||
void set_object_position(Position value) { m_noninherited.object_position = move(value); }
|
void set_object_position(Position value) { m_noninherited.object_position = move(value); }
|
||||||
void set_direction(Direction value) { m_inherited.direction = value; }
|
void set_direction(Direction value) { m_inherited.direction = value; }
|
||||||
|
void set_dominant_baseline(Optional<BaselineMetric> value) { m_inherited.dominant_baseline = value; }
|
||||||
void set_unicode_bidi(UnicodeBidi value) { m_noninherited.unicode_bidi = value; }
|
void set_unicode_bidi(UnicodeBidi value) { m_noninherited.unicode_bidi = value; }
|
||||||
void set_writing_mode(WritingMode value) { m_inherited.writing_mode = value; }
|
void set_writing_mode(WritingMode value) { m_inherited.writing_mode = value; }
|
||||||
void set_user_select(UserSelect value) { m_noninherited.user_select = value; }
|
void set_user_select(UserSelect value) { m_noninherited.user_select = value; }
|
||||||
|
|||||||
@@ -127,6 +127,16 @@
|
|||||||
"padding-box",
|
"padding-box",
|
||||||
"text"
|
"text"
|
||||||
],
|
],
|
||||||
|
"baseline-metric": [
|
||||||
|
"text-bottom",
|
||||||
|
"alphabetic",
|
||||||
|
"ideographic",
|
||||||
|
"middle",
|
||||||
|
"central",
|
||||||
|
"mathematical",
|
||||||
|
"hanging",
|
||||||
|
"text-top"
|
||||||
|
],
|
||||||
"border-collapse": [
|
"border-collapse": [
|
||||||
"separate",
|
"separate",
|
||||||
"collapse"
|
"collapse"
|
||||||
|
|||||||
@@ -130,6 +130,7 @@
|
|||||||
"captiontext",
|
"captiontext",
|
||||||
"cell",
|
"cell",
|
||||||
"center",
|
"center",
|
||||||
|
"central",
|
||||||
"checkbox",
|
"checkbox",
|
||||||
"circle",
|
"circle",
|
||||||
"clip",
|
"clip",
|
||||||
@@ -269,6 +270,7 @@
|
|||||||
"inactivecaption",
|
"inactivecaption",
|
||||||
"inactivecaptiontext",
|
"inactivecaptiontext",
|
||||||
"increasing",
|
"increasing",
|
||||||
|
"ideographic",
|
||||||
"incremental",
|
"incremental",
|
||||||
"infinite",
|
"infinite",
|
||||||
"infinity",
|
"infinity",
|
||||||
@@ -348,6 +350,7 @@
|
|||||||
"match-source",
|
"match-source",
|
||||||
"math",
|
"math",
|
||||||
"math-auto",
|
"math-auto",
|
||||||
|
"mathematical",
|
||||||
"max-content",
|
"max-content",
|
||||||
"medium",
|
"medium",
|
||||||
"menu",
|
"menu",
|
||||||
|
|||||||
@@ -1820,6 +1820,18 @@
|
|||||||
"display-legacy"
|
"display-legacy"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"dominant-baseline": {
|
||||||
|
"animation-type": "discrete",
|
||||||
|
"inherited": true,
|
||||||
|
"initial": "auto",
|
||||||
|
"requires-computation": "never",
|
||||||
|
"valid-types": [
|
||||||
|
"baseline-metric"
|
||||||
|
],
|
||||||
|
"valid-identifiers": [
|
||||||
|
"auto"
|
||||||
|
]
|
||||||
|
},
|
||||||
"empty-cells": {
|
"empty-cells": {
|
||||||
"animation-type": "discrete",
|
"animation-type": "discrete",
|
||||||
"inherited": true,
|
"inherited": true,
|
||||||
|
|||||||
62
Libraries/LibWeb/Layout/DominantBaseline.h
Normal file
62
Libraries/LibWeb/Layout/DominantBaseline.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2026, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibGfx/Font/Font.h>
|
||||||
|
#include <LibWeb/CSS/ComputedValues.h>
|
||||||
|
|
||||||
|
namespace Web::Layout {
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-inline/#dominant-baseline-property
|
||||||
|
static float dominant_baseline_offset(CSS::BaselineMetric metric, Gfx::FontPixelMetrics const& font_metrics)
|
||||||
|
{
|
||||||
|
switch (metric) {
|
||||||
|
case CSS::BaselineMetric::Central:
|
||||||
|
return (font_metrics.ascent - font_metrics.descent) / 2;
|
||||||
|
case CSS::BaselineMetric::Middle:
|
||||||
|
return font_metrics.x_height / 2;
|
||||||
|
case CSS::BaselineMetric::Hanging:
|
||||||
|
// FIXME: Read the hanging baseline from the font's BASE table.
|
||||||
|
return font_metrics.ascent * 0.8f;
|
||||||
|
case CSS::BaselineMetric::Ideographic:
|
||||||
|
// FIXME: Read the ideographic baseline from the font's BASE table.
|
||||||
|
return -font_metrics.descent;
|
||||||
|
case CSS::BaselineMetric::Mathematical:
|
||||||
|
// FIXME: Read the math baseline from the font's BASE table.
|
||||||
|
return font_metrics.ascent * 0.5f;
|
||||||
|
case CSS::BaselineMetric::TextTop:
|
||||||
|
case CSS::BaselineMetric::TextBottom:
|
||||||
|
// FIXME: Support text-top and text-bottom.
|
||||||
|
case CSS::BaselineMetric::Alphabetic:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
static CSS::BaselineMetric resolve_dominant_baseline_metric(CSS::ComputedValues const& computed_values)
|
||||||
|
{
|
||||||
|
auto dominant_baseline = computed_values.dominant_baseline();
|
||||||
|
if (dominant_baseline.has_value())
|
||||||
|
return *dominant_baseline;
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-inline/#valdef-dominant-baseline-auto
|
||||||
|
// Equivalent to alphabetic in horizontal writing modes and in vertical writing modes when text-orientation is
|
||||||
|
// sideways. Equivalent to central in vertical writing modes when text-orientation is mixed or upright.
|
||||||
|
// FIXME: Take text-orientation into account once it is implemented.
|
||||||
|
switch (computed_values.writing_mode()) {
|
||||||
|
case CSS::WritingMode::HorizontalTb:
|
||||||
|
case CSS::WritingMode::SidewaysRl:
|
||||||
|
case CSS::WritingMode::SidewaysLr:
|
||||||
|
return CSS::BaselineMetric::Alphabetic;
|
||||||
|
case CSS::WritingMode::VerticalRl:
|
||||||
|
case CSS::WritingMode::VerticalLr:
|
||||||
|
return CSS::BaselineMetric::Central;
|
||||||
|
}
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -893,6 +893,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
|
|||||||
computed_values.set_stop_opacity(computed_style.stop_opacity());
|
computed_values.set_stop_opacity(computed_style.stop_opacity());
|
||||||
|
|
||||||
computed_values.set_text_anchor(computed_style.text_anchor());
|
computed_values.set_text_anchor(computed_style.text_anchor());
|
||||||
|
computed_values.set_dominant_baseline(computed_style.dominant_baseline());
|
||||||
|
|
||||||
// FIXME: Support calc()
|
// FIXME: Support calc()
|
||||||
if (auto const& column_count = computed_style.property(CSS::PropertyID::ColumnCount); column_count.is_integer())
|
if (auto const& column_count = computed_style.property(CSS::PropertyID::ColumnCount); column_count.is_integer())
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <LibGfx/TextLayout.h>
|
#include <LibGfx/TextLayout.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/Layout/BlockFormattingContext.h>
|
#include <LibWeb/Layout/BlockFormattingContext.h>
|
||||||
|
#include <LibWeb/Layout/DominantBaseline.h>
|
||||||
#include <LibWeb/Layout/SVGClipBox.h>
|
#include <LibWeb/Layout/SVGClipBox.h>
|
||||||
#include <LibWeb/Layout/SVGFormattingContext.h>
|
#include <LibWeb/Layout/SVGFormattingContext.h>
|
||||||
#include <LibWeb/Layout/SVGGeometryBox.h>
|
#include <LibWeb/Layout/SVGGeometryBox.h>
|
||||||
@@ -381,6 +382,9 @@ Gfx::Path SVGFormattingContext::compute_path_for_text(SVGTextBox const& text_box
|
|||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto baseline_metric = resolve_dominant_baseline_metric(text_box.computed_values());
|
||||||
|
text_offset.translate_by(0, dominant_baseline_offset(baseline_metric, font.pixel_metrics()));
|
||||||
|
|
||||||
Gfx::Path path;
|
Gfx::Path path;
|
||||||
path.move_to(text_offset);
|
path.move_to(text_offset);
|
||||||
path.text(text_contents, font);
|
path.text(text_contents, font);
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ static ReadonlySpan<NamedPropertyID> attribute_style_properties()
|
|||||||
NamedPropertyID(CSS::PropertyID::Cy, { SVG::TagNames::circle, SVG::TagNames::ellipse }),
|
NamedPropertyID(CSS::PropertyID::Cy, { SVG::TagNames::circle, SVG::TagNames::ellipse }),
|
||||||
NamedPropertyID(CSS::PropertyID::Direction),
|
NamedPropertyID(CSS::PropertyID::Direction),
|
||||||
NamedPropertyID(CSS::PropertyID::Display),
|
NamedPropertyID(CSS::PropertyID::Display),
|
||||||
|
NamedPropertyID(CSS::PropertyID::DominantBaseline),
|
||||||
NamedPropertyID(CSS::PropertyID::FillOpacity),
|
NamedPropertyID(CSS::PropertyID::FillOpacity),
|
||||||
NamedPropertyID(CSS::PropertyID::FillRule),
|
NamedPropertyID(CSS::PropertyID::FillRule),
|
||||||
NamedPropertyID(CSS::PropertyID::Filter),
|
NamedPropertyID(CSS::PropertyID::Filter),
|
||||||
|
|||||||
64
Tests/LibWeb/Layout/expected/svg-text-dominant-baseline.txt
Normal file
64
Tests/LibWeb/Layout/expected/svg-text-dominant-baseline.txt
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] [BFC] children: not-inline
|
||||||
|
BlockContainer <html> at [0,0] [0+0+0 800 0+0+0] [0+0+0 416 0+0+0] [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at [8,8] [8+0+0 784 0+0+8] [8+0+0 400 0+0+8] children: inline
|
||||||
|
frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 400x400] baseline: 400
|
||||||
|
SVGSVGBox <svg> at [8,8] [0+0+0 400 0+0+0] [0+0+0 400 0+0+0] [SVG] children: inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGGeometryBox <line> at [7.75,57.75] [0+0+0 400.5 0+0+0] [0+0+0 0.5 0+0+0] children: not-inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGGeometryBox <line> at [7.75,107.75] [0+0+0 400.5 0+0+0] [0+0+0 0.5 0+0+0] children: not-inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGGeometryBox <line> at [7.75,157.75] [0+0+0 400.5 0+0+0] [0+0+0 0.5 0+0+0] children: not-inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGGeometryBox <line> at [7.75,207.75] [0+0+0 400.5 0+0+0] [0+0+0 0.5 0+0+0] children: not-inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGGeometryBox <line> at [7.75,257.75] [0+0+0 400.5 0+0+0] [0+0+0 0.5 0+0+0] children: not-inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGGeometryBox <line> at [7.75,307.75] [0+0+0 400.5 0+0+0] [0+0+0 0.5 0+0+0] children: not-inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGGeometryBox <line> at [7.75,357.75] [0+0+0 400.5 0+0+0] [0+0+0 0.5 0+0+0] children: not-inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGTextBox <text> at [18.171875,44.90625] [0+0+0 44.4375 0+0+0] [0+0+0 14 0+0+0] children: inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGTextBox <text> at [18.171875,92.96875] [0+0+0 100.59375 0+0+0] [0+0+0 15.703125 0+0+0] children: inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGTextBox <text> at [19.015625,150.90625] [0+0+0 68.890625 0+0+0] [0+0+0 14.03125 0+0+0] children: inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGTextBox <text> at [19.3125,198.328125] [0+0+0 54.46875 0+0+0] [0+0+0 15.46875 0+0+0] children: inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGTextBox <text> at [18.859375,255.75] [0+0+0 70.625 0+0+0] [0+0+0 17.515625 0+0+0] children: inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGTextBox <text> at [19.265625,288.953125] [0+0+0 110.5 0+0+0] [0+0+0 17.515625 0+0+0] children: inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
SVGTextBox <text> at [19.3125,350.953125] [0+0+0 126.59375 0+0+0] [0+0+0 15.46875 0+0+0] children: inline
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
TextNode <#text> (not painted)
|
||||||
|
|
||||||
|
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x416]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [8,8 784x400]
|
||||||
|
SVGSVGPaintable (SVGSVGBox<svg>) [8,8 400x400] overflow: [8,8 400.25x400]
|
||||||
|
SVGPathPaintable (SVGGeometryBox<line>) [7.75,57.75 400.5x0.5]
|
||||||
|
SVGPathPaintable (SVGGeometryBox<line>) [7.75,107.75 400.5x0.5]
|
||||||
|
SVGPathPaintable (SVGGeometryBox<line>) [7.75,157.75 400.5x0.5]
|
||||||
|
SVGPathPaintable (SVGGeometryBox<line>) [7.75,207.75 400.5x0.5]
|
||||||
|
SVGPathPaintable (SVGGeometryBox<line>) [7.75,257.75 400.5x0.5]
|
||||||
|
SVGPathPaintable (SVGGeometryBox<line>) [7.75,307.75 400.5x0.5]
|
||||||
|
SVGPathPaintable (SVGGeometryBox<line>) [7.75,357.75 400.5x0.5]
|
||||||
|
SVGPathPaintable (SVGTextBox<text>) [18.171875,44.90625 44.4375x14]
|
||||||
|
SVGPathPaintable (SVGTextBox<text>) [18.171875,92.96875 100.59375x15.703125]
|
||||||
|
SVGPathPaintable (SVGTextBox<text>) [19.015625,150.90625 68.890625x14.03125]
|
||||||
|
SVGPathPaintable (SVGTextBox<text>) [19.3125,198.328125 54.46875x15.46875]
|
||||||
|
SVGPathPaintable (SVGTextBox<text>) [18.859375,255.75 70.625x17.515625]
|
||||||
|
SVGPathPaintable (SVGTextBox<text>) [19.265625,288.953125 110.5x17.515625]
|
||||||
|
SVGPathPaintable (SVGTextBox<text>) [19.3125,350.953125 126.59375x15.46875]
|
||||||
|
|
||||||
|
SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto)
|
||||||
|
SC for BlockContainer<HTML> [0,0 800x416] [children: 0] (z-index: auto)
|
||||||
17
Tests/LibWeb/Layout/input/svg-text-dominant-baseline.html
Normal file
17
Tests/LibWeb/Layout/input/svg-text-dominant-baseline.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<svg viewBox="0 0 400 400" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<line x1="0" y1="50" x2="400" y2="50" stroke="gray" stroke-width="0.5"/>
|
||||||
|
<line x1="0" y1="100" x2="400" y2="100" stroke="gray" stroke-width="0.5"/>
|
||||||
|
<line x1="0" y1="150" x2="400" y2="150" stroke="gray" stroke-width="0.5"/>
|
||||||
|
<line x1="0" y1="200" x2="400" y2="200" stroke="gray" stroke-width="0.5"/>
|
||||||
|
<line x1="0" y1="250" x2="400" y2="250" stroke="gray" stroke-width="0.5"/>
|
||||||
|
<line x1="0" y1="300" x2="400" y2="300" stroke="gray" stroke-width="0.5"/>
|
||||||
|
<line x1="0" y1="350" x2="400" y2="350" stroke="gray" stroke-width="0.5"/>
|
||||||
|
<text x="10" y="50" font-size="20" font-family="SerenitySans" dominant-baseline="auto">auto</text>
|
||||||
|
<text x="10" y="100" font-size="20" font-family="SerenitySans" dominant-baseline="alphabetic">alphabetic</text>
|
||||||
|
<text x="10" y="150" font-size="20" font-family="SerenitySans" dominant-baseline="central">central</text>
|
||||||
|
<text x="10" y="200" font-size="20" font-family="SerenitySans" dominant-baseline="middle">middle</text>
|
||||||
|
<text x="10" y="250" font-size="20" font-family="SerenitySans" dominant-baseline="hanging">hanging</text>
|
||||||
|
<text x="10" y="300" font-size="20" font-family="SerenitySans" dominant-baseline="ideographic">ideographic</text>
|
||||||
|
<text x="10" y="350" font-size="20" font-family="SerenitySans" dominant-baseline="mathematical">mathematical</text>
|
||||||
|
</svg>
|
||||||
@@ -12,6 +12,7 @@ All properties associated with getComputedStyle(document.body):
|
|||||||
"color-scheme",
|
"color-scheme",
|
||||||
"cursor",
|
"cursor",
|
||||||
"direction",
|
"direction",
|
||||||
|
"dominant-baseline",
|
||||||
"empty-cells",
|
"empty-cells",
|
||||||
"fill",
|
"fill",
|
||||||
"fill-opacity",
|
"fill-opacity",
|
||||||
|
|||||||
@@ -443,6 +443,8 @@ All supported properties and their default values exposed from CSSStylePropertie
|
|||||||
'cy': '0px'
|
'cy': '0px'
|
||||||
'direction': 'ltr'
|
'direction': 'ltr'
|
||||||
'display': 'block'
|
'display': 'block'
|
||||||
|
'dominantBaseline': 'auto'
|
||||||
|
'dominant-baseline': 'auto'
|
||||||
'emptyCells': 'show'
|
'emptyCells': 'show'
|
||||||
'empty-cells': 'show'
|
'empty-cells': 'show'
|
||||||
'fill': 'rgb(0, 0, 0)'
|
'fill': 'rgb(0, 0, 0)'
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ color-interpolation: srgb
|
|||||||
color-scheme: normal
|
color-scheme: normal
|
||||||
cursor: auto
|
cursor: auto
|
||||||
direction: ltr
|
direction: ltr
|
||||||
|
dominant-baseline: auto
|
||||||
empty-cells: show
|
empty-cells: show
|
||||||
fill: rgb(0, 0, 0)
|
fill: rgb(0, 0, 0)
|
||||||
fill-opacity: 1
|
fill-opacity: 1
|
||||||
@@ -102,7 +103,7 @@ background-position-x: 0%
|
|||||||
background-position-y: 0%
|
background-position-y: 0%
|
||||||
background-repeat: repeat
|
background-repeat: repeat
|
||||||
background-size: auto
|
background-size: auto
|
||||||
block-size: 1560px
|
block-size: 1575px
|
||||||
border-block-end-color: rgb(0, 0, 0)
|
border-block-end-color: rgb(0, 0, 0)
|
||||||
border-block-end-style: none
|
border-block-end-style: none
|
||||||
border-block-end-width: 0px
|
border-block-end-width: 0px
|
||||||
@@ -188,7 +189,7 @@ grid-row-start: auto
|
|||||||
grid-template-areas: none
|
grid-template-areas: none
|
||||||
grid-template-columns: none
|
grid-template-columns: none
|
||||||
grid-template-rows: none
|
grid-template-rows: none
|
||||||
height: 2850px
|
height: 2865px
|
||||||
inline-size: 784px
|
inline-size: 784px
|
||||||
inset-block-end: auto
|
inset-block-end: auto
|
||||||
inset-block-start: auto
|
inset-block-start: auto
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
Harness status: OK
|
Harness status: OK
|
||||||
|
|
||||||
Found 285 tests
|
Found 286 tests
|
||||||
|
|
||||||
281 Pass
|
282 Pass
|
||||||
4 Fail
|
4 Fail
|
||||||
Pass accent-color
|
Pass accent-color
|
||||||
Pass border-collapse
|
Pass border-collapse
|
||||||
@@ -15,6 +15,7 @@ Pass color-interpolation
|
|||||||
Pass color-scheme
|
Pass color-scheme
|
||||||
Pass cursor
|
Pass cursor
|
||||||
Pass direction
|
Pass direction
|
||||||
|
Pass dominant-baseline
|
||||||
Pass empty-cells
|
Pass empty-cells
|
||||||
Pass fill
|
Pass fill
|
||||||
Pass fill-opacity
|
Pass fill-opacity
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 9 tests
|
||||||
|
|
||||||
|
9 Pass
|
||||||
|
Pass Property dominant-baseline value 'auto'
|
||||||
|
Pass Property dominant-baseline value 'text-bottom'
|
||||||
|
Pass Property dominant-baseline value 'alphabetic'
|
||||||
|
Pass Property dominant-baseline value 'ideographic'
|
||||||
|
Pass Property dominant-baseline value 'middle'
|
||||||
|
Pass Property dominant-baseline value 'central'
|
||||||
|
Pass Property dominant-baseline value 'mathematical'
|
||||||
|
Pass Property dominant-baseline value 'hanging'
|
||||||
|
Pass Property dominant-baseline value 'text-top'
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 4 tests
|
||||||
|
|
||||||
|
4 Pass
|
||||||
|
Pass e.style['dominant-baseline'] = "normal" should not set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "none" should not set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "alphabetic, ideographic" should not set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "middle central" should not set the property value
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 9 tests
|
||||||
|
|
||||||
|
9 Pass
|
||||||
|
Pass e.style['dominant-baseline'] = "auto" should set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "text-bottom" should set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "alphabetic" should set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "ideographic" should set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "middle" should set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "central" should set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "mathematical" should set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "hanging" should set the property value
|
||||||
|
Pass e.style['dominant-baseline'] = "text-top" should set the property value
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
Harness status: OK
|
Harness status: OK
|
||||||
|
|
||||||
Found 48 tests
|
Found 49 tests
|
||||||
|
|
||||||
48 Pass
|
49 Pass
|
||||||
Pass clip-path presentation attribute supported on an irrelevant element
|
Pass clip-path presentation attribute supported on an irrelevant element
|
||||||
Pass clip-rule presentation attribute supported on an irrelevant element
|
Pass clip-rule presentation attribute supported on an irrelevant element
|
||||||
Pass color presentation attribute supported on an irrelevant element
|
Pass color presentation attribute supported on an irrelevant element
|
||||||
@@ -10,6 +10,7 @@ Pass color-interpolation presentation attribute supported on an irrelevant eleme
|
|||||||
Pass cursor presentation attribute supported on an irrelevant element
|
Pass cursor presentation attribute supported on an irrelevant element
|
||||||
Pass direction presentation attribute supported on an irrelevant element
|
Pass direction presentation attribute supported on an irrelevant element
|
||||||
Pass display presentation attribute supported on an irrelevant element
|
Pass display presentation attribute supported on an irrelevant element
|
||||||
|
Pass dominant-baseline presentation attribute supported on an irrelevant element
|
||||||
Pass fill presentation attribute supported on an irrelevant element
|
Pass fill presentation attribute supported on an irrelevant element
|
||||||
Pass fill-opacity presentation attribute supported on an irrelevant element
|
Pass fill-opacity presentation attribute supported on an irrelevant element
|
||||||
Pass fill-rule presentation attribute supported on an irrelevant element
|
Pass fill-rule presentation attribute supported on an irrelevant element
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
Harness status: OK
|
Harness status: OK
|
||||||
|
|
||||||
Found 58 tests
|
Found 59 tests
|
||||||
|
|
||||||
57 Pass
|
58 Pass
|
||||||
1 Fail
|
1 Fail
|
||||||
Pass clip-path presentation attribute supported on a relevant element
|
Pass clip-path presentation attribute supported on a relevant element
|
||||||
Pass clip-rule presentation attribute supported on a relevant element
|
Pass clip-rule presentation attribute supported on a relevant element
|
||||||
@@ -13,6 +13,7 @@ Pass cx presentation attribute supported on a relevant element
|
|||||||
Pass cy presentation attribute supported on a relevant element
|
Pass cy presentation attribute supported on a relevant element
|
||||||
Pass direction presentation attribute supported on a relevant element
|
Pass direction presentation attribute supported on a relevant element
|
||||||
Pass display presentation attribute supported on a relevant element
|
Pass display presentation attribute supported on a relevant element
|
||||||
|
Pass dominant-baseline presentation attribute supported on a relevant element
|
||||||
Pass fill presentation attribute supported on a relevant element
|
Pass fill presentation attribute supported on a relevant element
|
||||||
Pass fill-opacity presentation attribute supported on a relevant element
|
Pass fill-opacity presentation attribute supported on a relevant element
|
||||||
Pass fill-rule presentation attribute supported on a relevant element
|
Pass fill-rule presentation attribute supported on a relevant element
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
Harness status: OK
|
Harness status: OK
|
||||||
|
|
||||||
Found 48 tests
|
Found 49 tests
|
||||||
|
|
||||||
48 Pass
|
49 Pass
|
||||||
Pass clip-path presentation attribute supported on an unknown SVG element
|
Pass clip-path presentation attribute supported on an unknown SVG element
|
||||||
Pass clip-rule presentation attribute supported on an unknown SVG element
|
Pass clip-rule presentation attribute supported on an unknown SVG element
|
||||||
Pass color presentation attribute supported on an unknown SVG element
|
Pass color presentation attribute supported on an unknown SVG element
|
||||||
@@ -10,6 +10,7 @@ Pass color-interpolation presentation attribute supported on an unknown SVG elem
|
|||||||
Pass cursor presentation attribute supported on an unknown SVG element
|
Pass cursor presentation attribute supported on an unknown SVG element
|
||||||
Pass direction presentation attribute supported on an unknown SVG element
|
Pass direction presentation attribute supported on an unknown SVG element
|
||||||
Pass display presentation attribute supported on an unknown SVG element
|
Pass display presentation attribute supported on an unknown SVG element
|
||||||
|
Pass dominant-baseline presentation attribute supported on an unknown SVG element
|
||||||
Pass fill presentation attribute supported on an unknown SVG element
|
Pass fill presentation attribute supported on an unknown SVG element
|
||||||
Pass fill-opacity presentation attribute supported on an unknown SVG element
|
Pass fill-opacity presentation attribute supported on an unknown SVG element
|
||||||
Pass fill-rule presentation attribute supported on an unknown SVG element
|
Pass fill-rule presentation attribute supported on an unknown SVG element
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Inline Layout: getComputedStyle().dominantBaseline</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-inline-3/#dominant-baseline-property">
|
||||||
|
<meta name="assert" content="dominant-baseline computed value is as specified.">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../../css/support/computed-testcommon.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="target"></div>
|
||||||
|
<script>
|
||||||
|
test_computed_value("dominant-baseline", "auto");
|
||||||
|
test_computed_value("dominant-baseline", "text-bottom");
|
||||||
|
test_computed_value("dominant-baseline", "alphabetic");
|
||||||
|
test_computed_value("dominant-baseline", "ideographic");
|
||||||
|
test_computed_value("dominant-baseline", "middle");
|
||||||
|
test_computed_value("dominant-baseline", "central");
|
||||||
|
test_computed_value("dominant-baseline", "mathematical");
|
||||||
|
test_computed_value("dominant-baseline", "hanging");
|
||||||
|
test_computed_value("dominant-baseline", "text-top");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Inline Layout: parsing dominant-baseline with invalid values</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-inline-3/#dominant-baseline-property">
|
||||||
|
<meta name="assert" content="dominant-baseline supports only the grammar 'auto | text-bottom | alphabetic | ideographic | middle | central | mathematical | hanging | text-top'.">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
test_invalid_value("dominant-baseline", "normal");
|
||||||
|
test_invalid_value("dominant-baseline", "none");
|
||||||
|
test_invalid_value("dominant-baseline", "alphabetic, ideographic");
|
||||||
|
test_invalid_value("dominant-baseline", "middle central");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Inline Layout: parsing dominant-baseline with valid values</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-inline-3/#dominant-baseline-property">
|
||||||
|
<meta name="assert" content="dominant-baseline supports the full grammar 'auto | text-bottom | alphabetic | ideographic | middle | central | mathematical | hanging | text-top'.">
|
||||||
|
<script src="../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
test_valid_value("dominant-baseline", "auto");
|
||||||
|
test_valid_value("dominant-baseline", "text-bottom");
|
||||||
|
test_valid_value("dominant-baseline", "alphabetic");
|
||||||
|
test_valid_value("dominant-baseline", "ideographic");
|
||||||
|
test_valid_value("dominant-baseline", "middle");
|
||||||
|
test_valid_value("dominant-baseline", "central");
|
||||||
|
test_valid_value("dominant-baseline", "mathematical");
|
||||||
|
test_valid_value("dominant-baseline", "hanging");
|
||||||
|
test_valid_value("dominant-baseline", "text-top");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user