WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-319178-20260712052550.patch (text/plain), 101.02 KB, created by
alan
on 2026-07-12 05:25:51 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
alan
Created:
2026-07-12 05:25:51 PDT
Size:
101.02 KB
patch
obsolete
>From 6eb89e5ba9e9a5dfb00b3d1ba169affdd4b9ca7c Mon Sep 17 00:00:00 2001 >From: Alan Baradlay <zalan@apple.com> >Date: Sat, 11 Jul 2026 20:20:13 -0700 >Subject: [PATCH] [css-text-decor-4] Implement the text-decoration-inset > property https://bugs.webkit.org/show_bug.cgi?id=319178 > <rdar://problem/182019037> > >Reviewed by NOBODY (OOPS!). > >Add the CSS Text Decoration Level 4 'text-decoration-inset' property >(auto | <length>{1,2}), gated behind the cssTextDecorationInsetEnabled setting. > >The property adjusts the start and end endpoints of the line decorations drawn by >a decorating box (underline, overline, line-through). A positive <length> moves >an endpoint inward, trimming the decoration; a negative <length> moves it outward, >extending it. A single value applies to both endpoints; two values are the start >and the end. 'auto' lets the UA choose an inset so that two adjacent identical >underlined elements do not appear to share a single continuous underline (e.g. >for Chinese, where underlining is a form of punctuation); it is distinct from 0. > >1. It is stored as a new Style::TextDecorationInset value type (a keyword-or-length- >pair) in NonInheritedRareData, parsed grammar-driven, and animated by computed >value. >2. The inset is applied at paint time in TextBoxPainter, which shifts the >decoration's inline origin and shrinks/grows its length (because text-decoration- >inset and box-decoration-break are not inherited, a decoration that propagates >from an ancestor box down to the (root inline) box that paints it) >3. box-decoration-break is then honored via the inline box's closed edges: with 'slice' the start >inset only affects the first fragment's start edge and the end inset the last >fragment's end edge; with 'clone' both edges of every fragment are inset. >4. Endpoints are also gated on the marked-text piece that actually reaches the box's >logical start/end, so a decoration split into several marked texts (selection, >document markers, highlights) stays continuous instead of being trimmed at the >interior boundaries. >5. Because a negative inset extends the decoration past the text >box, decoration ink overflow is expanded by the outward amount, and StyleDifference >treats an inset change as affecting repaint and visual overflow so dynamic/animated >changes invalidate correctly. > >Horizontal and vertical writing modes (including sideways-rl/lr and orthogonal >blocks), in both inline directions, are supported, as is the text-decoration-skip- >ink interaction (its skip gaps are measured against the underline's bounding box, >which already tracks the inset-shifted origin, so they stay aligned to the glyphs). >Across a bidi direction boundary the decoration is painted one segment per run; the >component of the inset that shifts the decoration as a whole is applied to every >segment (so the seam between runs moves with it rather than being pinned), while the >extend/trim overhang is applied only at the segment reaching the decoration's visual >start/end. > >* LayoutTests/TestExpectations: Un-skip the now-passing upstream WPT conformance >tests (text-decoration-inset-001..008, 010..013, 015..024, and >orthogonal-block-001); 009/014 (sub-pixel endpoint rounding) and the unrelated 025 >(multicol) remain ImageOnlyFailure on follow-up bugs. >* LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml-expected.txt: >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-computed-expected.txt: >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-valid-expected.txt: Rebaseline the upstream parsing tests, which still carried the pre-implementation "not supported" baseline. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk-expected.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-expected-mismatch.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break-expected-mismatch.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed-expected.txt: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid-expected.txt: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through-expected.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap-expected.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative-expected-mismatch.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited-expected.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value-expected.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline-expected.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-expected.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-ref.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid-expected.txt: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero-expected.html: Added. >* LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero.html: Added. >* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: Add CSSTextDecorationInsetEnabled. >* Source/WebCore/Headers.cmake: >* Source/WebCore/Sources.txt: >* Source/WebCore/WebCore.xcodeproj/project.pbxproj: Build StyleTextDecorationInset. >* Source/WebCore/css/CSSProperties.json: Add the text-decoration-inset property. >* Source/WebCore/rendering/TextBoxPainter.cpp: >(WebCore::autoTextDecorationInset): >(WebCore::TextBoxPainter::insetAdjustedDecorationLocationAndWidth): Apply the >inset (and box-decoration-break) carried on the decoration styles to the decoration >geometry, honoring box-decoration-break and marked-text sub-ranges. >(WebCore::TextBoxPainter::paintBackgroundDecorations): >(WebCore::TextBoxPainter::paintForegroundDecorations): >(WebCore::TextBoxPainter::insetAdjustedDecorationLocationAndWidth const): >* Source/WebCore/rendering/TextBoxPainter.h: >* Source/WebCore/rendering/TextDecorationPainter.cpp: >(WebCore::collectStylesForRenderer): Also resolve the non-inherited >text-decoration-inset and box-decoration-break from the box that introduces the >decoration, alongside its color/thickness/style. >(WebCore::TextDecorationPainter::Styles::operator==): >(WebCore::TextDecorationPainter::Styles::operator== const): >* Source/WebCore/rendering/TextDecorationPainter.h: Carry the resolved inset and >box-decoration-break on Styles. >* Source/WebCore/style/InlineTextBoxStyle.cpp: >(WebCore::computedInkOverflowForDecorations): Expand ink overflow for a negative >(outward) inset. >* Source/WebCore/style/PropertyAllowlist.cpp: Allow text-decoration-inset in the >(WebCore::Style::isValidHighlightStyleProperty): >(WebCore::Style::isValidCueStyleProperty): >(WebCore::Style::isValidCueSelectorStyleProperty): >highlight and cue property allowlists. >* Source/WebCore/style/StyleBuilderCustom.h: Add forwardInheritedValue overload. >(WebCore::Style::forwardInheritedValue): >* Source/WebCore/style/StyleDifference.cpp: >(WebCore::...::changeAffectsVisualOverflow): >(WebCore::...::rareDataChangeRequiresRepaint): Repaint/recompute overflow when >the inset changes. >* Source/WebCore/style/computed/data/StyleNonInheritedRareData.cpp: >(WebCore::Style::NonInheritedRareData::NonInheritedRareData): >(WebCore::Style::NonInheritedRareData::operator== const): >(WebCore::Style::NonInheritedRareData::dumpDifferences const): >* Source/WebCore/style/computed/data/StyleNonInheritedRareData.h: Store the inset. >* Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.cpp: Added. >(WebCore::Style::TextDecorationInset::resolvedStart const): >(WebCore::Style::TextDecorationInset::resolvedEnd const): >(WebCore::Style::CSSValueConversion<TextDecorationInsetPair>::operator): >* Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.h: Added. >(WTF::MarkableTraits<WebCore::Style::TextDecorationInsetPair>::isEmptyValue): >(WTF::MarkableTraits<WebCore::Style::TextDecorationInsetPair>::emptyValue): >(WebCore::Style::TextDecorationInset::TextDecorationInset): >(WebCore::Style::TextDecorationInset::isAuto const): >* Source/WebCore/style/computed/StyleComputedStyleBase.h: >* LayoutTests/imported/w3c/web-platform-tests/html/rendering/widgets/shadow-dom-expected.txt: >--- > .../Preferences/UnifiedWebPreferences.yaml | 15 +++ > Source/WebCore/Headers.cmake | 1 + > Source/WebCore/Sources.txt | 1 + > .../WebCore/WebCore.xcodeproj/project.pbxproj | 6 ++ > Source/WebCore/css/CSSProperties.json | 18 ++++ > Source/WebCore/rendering/TextBoxPainter.cpp | 96 ++++++++++++++++++- > Source/WebCore/rendering/TextBoxPainter.h | 7 ++ > .../rendering/TextDecorationPainter.cpp | 9 +- > .../WebCore/rendering/TextDecorationPainter.h | 4 + > Source/WebCore/style/InlineTextBoxStyle.cpp | 13 +++ > Source/WebCore/style/PropertyAllowlist.cpp | 3 + > Source/WebCore/style/StyleBuilderCustom.h | 1 + > Source/WebCore/style/StyleDifference.cpp | 5 +- > .../style/computed/StyleComputedStyleBase.h | 1 + > .../data/StyleNonInheritedRareData.cpp | 4 + > .../computed/data/StyleNonInheritedRareData.h | 2 + > .../StyleTextDecorationInset.cpp | 75 +++++++++++++++ > .../StyleTextDecorationInset.h | 84 ++++++++++++++++ > LayoutTests/TestExpectations | 33 ++----- > .../all-prop-initial-xml-expected.txt | 1 + > ...ext-decoration-inset-computed-expected.txt | 20 ++-- > .../text-decoration-inset-valid-expected.txt | 20 ++-- > ...xt-decoration-inset-auto-cjk-expected.html | 11 +++ > .../text-decoration-inset-auto-cjk.html | 12 +++ > ...coration-inset-auto-expected-mismatch.html | 5 + > .../text-decoration-inset-auto.html | 7 ++ > ...ox-decoration-break-expected-mismatch.html | 9 ++ > ...decoration-inset-box-decoration-break.html | 11 +++ > ...ext-decoration-inset-computed-expected.txt | 20 ++++ > .../text-decoration-inset-computed.html | 96 +++++++++++++++++++ > ...text-decoration-inset-invalid-expected.txt | 17 ++++ > .../text-decoration-inset-invalid.html | 35 +++++++ > ...ecoration-inset-line-through-expected.html | 5 + > .../text-decoration-inset-line-through.html | 7 ++ > ...ration-inset-marked-text-gap-expected.html | 12 +++ > ...text-decoration-inset-marked-text-gap.html | 24 +++++ > ...tion-inset-negative-expected-mismatch.html | 5 + > .../text-decoration-inset-negative.html | 7 ++ > ...coration-inset-not-inherited-expected.html | 5 + > .../text-decoration-inset-not-inherited.html | 7 ++ > ...t-decoration-inset-one-value-expected.html | 5 + > .../text-decoration-inset-one-value.html | 7 ++ > ...xt-decoration-inset-overline-expected.html | 5 + > .../text-decoration-inset-overline.html | 7 ++ > ...ration-inset-trims-underline-expected.html | 8 ++ > ...-decoration-inset-trims-underline-ref.html | 8 ++ > ...text-decoration-inset-trims-underline.html | 12 +++ > .../text-decoration-inset-valid-expected.txt | 24 +++++ > .../text-decoration-inset-valid.html | 40 ++++++++ > .../text-decoration-inset-zero-expected.html | 5 + > .../text-decoration-inset-zero.html | 7 ++ > .../rendering/widgets/shadow-dom-expected.txt | 8 +- > 52 files changed, 794 insertions(+), 56 deletions(-) > create mode 100644 Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.cpp > create mode 100644 Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.h > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk-expected.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-expected-mismatch.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break-expected-mismatch.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed-expected.txt > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid-expected.txt > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through-expected.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap-expected.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative-expected-mismatch.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited-expected.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value-expected.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline-expected.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-expected.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-ref.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid-expected.txt > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero-expected.html > create mode 100644 LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero.html > >diff --git a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml >index 7e49e29ae834..3baa22b94a7d 100644 >--- a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml >+++ b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml >@@ -1541,6 +1541,21 @@ CSSSelectorJITCompilerEnabled: > WebCore: > default: true > >+CSSTextDecorationInsetEnabled: >+ type: bool >+ status: preview >+ category: css >+ webcoreOnChange: setNeedsRecalcStyleInAllFrames >+ humanReadableName: "CSS text-decoration-inset property" >+ humanReadableDescription: "Enable the text-decoration-inset property, defined in CSS Text Decoration 4" >+ defaultValue: >+ WebKitLegacy: >+ default: false >+ WebKit: >+ default: false >+ WebCore: >+ default: false >+ > CSSTextDecorationLineErrorValues: > type: bool > status: stable >diff --git a/Source/WebCore/Headers.cmake b/Source/WebCore/Headers.cmake >index a3a66cea6431..9b6925625ea5 100644 >--- a/Source/WebCore/Headers.cmake >+++ b/Source/WebCore/Headers.cmake >@@ -3498,6 +3498,7 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS > style/values/text/StyleTextTransform.h > style/values/text/StyleWordSpacing.h > >+ style/values/text-decoration/StyleTextDecorationInset.h > style/values/text-decoration/StyleTextDecorationLine.h > style/values/text-decoration/StyleTextDecorationThickness.h > style/values/text-decoration/StyleTextEmphasisPosition.h >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index 52a2e0bbb67a..b282150fbd99 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -3491,6 +3491,7 @@ style/values/svg/StyleSVGPaintOrder.cpp > style/values/svg/StyleSVGPathData.cpp > style/values/svg/StyleSVGStrokeDasharray.cpp > style/values/svg/StyleSVGStrokeDashoffset.cpp >+style/values/text-decoration/StyleTextDecorationInset.cpp @header:RenderStyleGetters @cost:5 > style/values/text-decoration/StyleTextDecorationLine.cpp > style/values/text-decoration/StyleTextDecorationThickness.cpp @header:RenderStyleGetters @cost:5 > style/values/text-decoration/StyleTextEmphasisPosition.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index ca4a387f00b7..dbd9c2d8e1fb 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -734,6 +734,7 @@ > 1C4DB02627339FE0007B0AD1 /* ShouldLocalizeAxisNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C4DB02427339E5E007B0AD1 /* ShouldLocalizeAxisNames.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 1C5E1DA826F94B9000E07AF1 /* FontPaletteValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C5E1DA626F949B900E07AF1 /* FontPaletteValues.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 1C6626111C6E7CA600AB527C /* FontFace.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C66260F1C6E7CA600AB527C /* FontFace.h */; }; >+ 1DEC0126000000000000A0DE /* StyleTextDecorationInset.h in Headers */ = {isa = PBXBuildFile; fileRef = 1DEC0126000000000000B0DE /* StyleTextDecorationInset.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 1C73A71521857587004CCEA5 /* StyleTextDecorationThickness.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CB6B4F8217B83930093B9CD /* StyleTextDecorationThickness.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 1C7A6EB526F5D8F50096D8C7 /* FontPalette.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C4674FD26F4843600B61273 /* FontPalette.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 1C81B95A0E97330800266E07 /* PageInspectorController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C81B9560E97330800266E07 /* PageInspectorController.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -9777,6 +9778,7 @@ > 1CAF34800A6C405200ABE06E /* WebScriptObjectPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptObjectPrivate.h; sourceTree = "<group>"; }; > 1CAF56D8253014570017B472 /* DrawGlyphsRecorder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DrawGlyphsRecorder.h; sourceTree = "<group>"; }; > 1CAF56DE2530245A0017B472 /* DrawGlyphsRecorder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DrawGlyphsRecorder.cpp; sourceTree = "<group>"; }; >+ 1DEC0126000000000000B0DE /* StyleTextDecorationInset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StyleTextDecorationInset.h; sourceTree = "<group>"; }; > 1CB6B4F8217B83930093B9CD /* StyleTextDecorationThickness.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StyleTextDecorationThickness.h; sourceTree = "<group>"; }; > 1CC54AFB270F92DA005BF8BE /* ProcessQualified.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProcessQualified.h; sourceTree = "<group>"; }; > 1CCDF5BB1990332400BCEBAD /* SVGToOTFFontConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGToOTFFontConversion.cpp; sourceTree = "<group>"; }; >@@ -19066,6 +19068,7 @@ > BC0929B02E2AA9BA002ACB2C /* StyleWebKitOverflowScrolling.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StyleWebKitOverflowScrolling.cpp; sourceTree = "<group>"; }; > BC0929B12E2AA9BA002ACB2C /* StyleWebKitOverflowScrolling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StyleWebKitOverflowScrolling.h; sourceTree = "<group>"; }; > BC092A042E2D5110002ACB2C /* StyleCursor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StyleCursor.cpp; sourceTree = "<group>"; }; >+ 1DEC0126000000000000C0DE /* StyleTextDecorationInset.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StyleTextDecorationInset.cpp; sourceTree = "<group>"; }; > BC092A0C2E2D75E6002ACB2C /* StyleTextDecorationThickness.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StyleTextDecorationThickness.cpp; sourceTree = "<group>"; }; > BC092A1B2E2DBC36002ACB2C /* StyleViewTransitionName.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StyleViewTransitionName.cpp; sourceTree = "<group>"; }; > BC092A752E300E57002ACB2C /* StyleBlockStepSize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StyleBlockStepSize.h; sourceTree = "<group>"; }; >@@ -37827,6 +37830,8 @@ > BC3078E42D02884200630D75 /* text-decoration */ = { > isa = PBXGroup; > children = ( >+ 1DEC0126000000000000C0DE /* StyleTextDecorationInset.cpp */, >+ 1DEC0126000000000000B0DE /* StyleTextDecorationInset.h */, > 4C1508782E512B4100B720D9 /* StyleTextDecorationLine.cpp */, > 4C1508772E512B4100B720D9 /* StyleTextDecorationLine.h */, > BC092A0C2E2D75E6002ACB2C /* StyleTextDecorationThickness.cpp */, >@@ -49129,6 +49134,7 @@ > BC452A922ED24DE500FD066C /* StyleTextAlignLast.h in Headers */, > BC4631A32EAA911900EA911F /* StyleTextAutospace.h in Headers */, > BC10DA912E80DC39000EE742 /* StyleTextBoxEdge.h in Headers */, >+ 1DEC0126000000000000A0DE /* StyleTextDecorationInset.h in Headers */, > 4C15087A2E512B4100B720D9 /* StyleTextDecorationLine.h in Headers */, > 1C73A71521857587004CCEA5 /* StyleTextDecorationThickness.h in Headers */, > BC10DA8A2E80D200000EE742 /* StyleTextEdge.h in Headers */, >diff --git a/Source/WebCore/css/CSSProperties.json b/Source/WebCore/css/CSSProperties.json >index 2bd391f29ee5..421e35130aaa 100644 >--- a/Source/WebCore/css/CSSProperties.json >+++ b/Source/WebCore/css/CSSProperties.json >@@ -11903,6 +11903,24 @@ > "url": "https://drafts.csswg.org/css-text-decor-4/#text-decoration-thickness-property" > } > }, >+ "text-decoration-inset": { >+ "animation-type": "by computed value", >+ "initial": "0px", >+ "values": [ >+ "auto" >+ ], >+ "codegen-properties": { >+ "settings-flag": "cssTextDecorationInsetEnabled", >+ "computed-style-storage-path": ["m_nonInheritedData", "rareData"], >+ "computed-style-storage-kind": "reference", >+ "computed-style-type": "Style::TextDecorationInset", >+ "parser-grammar": "auto | <length>{1,2}@(type=CSSValuePair default=previous)" >+ }, >+ "specification": { >+ "category": "css-text-decor", >+ "url": "https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property" >+ } >+ }, > "-webkit-text-decorations-in-effect": { > "animation-type": "not animatable (internal)", > "inherited": true, >diff --git a/Source/WebCore/rendering/TextBoxPainter.cpp b/Source/WebCore/rendering/TextBoxPainter.cpp >index 61bc3f93d856..0769acd3ac91 100644 >--- a/Source/WebCore/rendering/TextBoxPainter.cpp >+++ b/Source/WebCore/rendering/TextBoxPainter.cpp >@@ -52,6 +52,7 @@ > #include "RenderView.h" > #include "RenderedDocumentMarker.h" > #include "Settings.h" >+#include "StyleTextDecorationInset.h" > #include "StyleTextDecorationLine.h" > #include "StyleTextDecorationThickness.h" > #include "StyledMarkedText.h" >@@ -898,6 +899,91 @@ void TextBoxPainter::collectDecoratingBoxesForBackgroundPainting(DecoratingBoxLi > } > } > >+static float autoTextDecorationInset(const Style::ComputedStyle& style) >+{ >+ // A small UA-chosen inset (relative to font size) so that two adjacent identical underlined >+ // elements do not appear to share a single continuous underline (important for e.g. Chinese, >+ // where underlining is a form of punctuation). >+ return style.computedFontSize() / 8; >+} >+ >+std::pair<FloatPoint, float> TextBoxPainter::insetAdjustedDecorationLocationAndWidth(const DecoratingBox& decoratingBox, const StyledMarkedText& markedText) const >+{ >+ auto boxOrigin = decoratingBox.location; >+ auto width = decoratingBox.contentWidth; >+ >+ // text-decoration-inset and box-decoration-break are not inherited, but a decoration propagates from >+ // the box that introduces it to the (possibly descendant) box that paints it, so they are resolved >+ // from the originating box and carried on the decoration Styles (see collectStylesForRenderer()), >+ // alongside the decoration color/thickness. >+ auto& insetStyles = decoratingBox.textDecorationStyles; >+ if (!insetStyles.inset) >+ return { boxOrigin, width }; >+ auto& inset = *insetStyles.inset; >+ >+ auto& style = decoratingBox.style.get(); >+ auto autoValue = inset.isAuto() ? autoTextDecorationInset(style) : 0.f; >+ auto startInset = inset.resolvedStart(style, autoValue); >+ auto endInset = inset.resolvedEnd(style, autoValue); >+ if (!startInset && !endInset) >+ return { boxOrigin, width }; >+ >+ auto writingMode = style.writingMode(); >+ auto decoratingInlineBox = decoratingBox.inlineBox; >+ >+ // box-decoration-break: the start inset applies only to the first fragment's start edge and the >+ // end inset only to the last fragment's end edge; for box-decoration-break: clone every fragment is >+ // a complete box, so both endpoints are inset on every line. >+ auto closedEdges = [&]() -> RectEdges<bool> { >+ if (!decoratingInlineBox) >+ return { true }; >+ if (insetStyles.boxDecorationBreak == BoxDecorationBreak::Clone) >+ return { true }; >+ return decoratingInlineBox->closedEdges(); >+ }(); >+ >+ bool isLTR = writingMode.isBidiLTR(); >+ >+ // A decorating box can span several leaf boxes on a line (its bidi runs), each split into marked-text >+ // sub-ranges. Map the logical start/end insets onto the decoration's visual left/right edges; >+ // displacements below are measured rightward (a positive inset trims inward, a negative one extends >+ // outward). box-decoration-break decides which of the decoration's edges live on this line fragment, >+ // and firstLeafBox/lastLeafBox + the marked-text offsets decide which painted piece actually reaches >+ // that visual edge. >+ auto textBox = makeIterator(); >+ bool ownsLineLeftEdge = !decoratingInlineBox || textBox == decoratingInlineBox->firstLeafBox(); >+ bool ownsLineRightEdge = !decoratingInlineBox || textBox == decoratingInlineBox->lastLeafBox(); >+ bool ownsLogicalStart = !markedText.startOffset; >+ bool ownsLogicalEnd = markedText.endOffset == m_paintTextRun.length(); >+ >+ float visualLeftInset = isLTR ? startInset : endInset; >+ float visualRightInset = isLTR ? endInset : startInset; >+ bool leftEdgeOnFragment = isLTR ? closedEdges.start(writingMode) : closedEdges.end(writingMode); >+ bool rightEdgeOnFragment = isLTR ? closedEdges.end(writingMode) : closedEdges.start(writingMode); >+ float leftEdgeMove = leftEdgeOnFragment ? visualLeftInset : 0.f; >+ float rightEdgeMove = rightEdgeOnFragment ? -visualRightInset : 0.f; >+ >+ // When the whole decoration lives on this fragment, the part of the inset that moves both visual >+ // edges the same way is an inline-axis shift of the decoration as a whole. Applying that shift to >+ // every painted piece keeps a symmetric inset a rigid shift of the decoration - including the seam >+ // between bidi runs - instead of pinning that interior seam. The remaining per-edge movement is the >+ // extend/trim overhang, applied only at the piece that actually reaches that visual edge; interior >+ // pieces (e.g. superscripts/subscripts at other baselines) get only the whole-decoration shift, so >+ // they stay put for a pure extend/trim. (skip-ink needs no adjustment: its gaps are measured relative >+ // to the underline's bounding box, which already tracks boxOrigin.) >+ float decorationInlineShift = (leftEdgeOnFragment && rightEdgeOnFragment) ? (leftEdgeMove + rightEdgeMove) / 2.f : 0.f; >+ bool reachesVisualLeft = leftEdgeOnFragment && ownsLineLeftEdge && (isLTR ? ownsLogicalStart : ownsLogicalEnd); >+ bool reachesVisualRight = rightEdgeOnFragment && ownsLineRightEdge && (isLTR ? ownsLogicalEnd : ownsLogicalStart); >+ float leftOverhang = reachesVisualLeft ? leftEdgeMove - decorationInlineShift : 0.f; >+ float rightOverhang = reachesVisualRight ? rightEdgeMove - decorationInlineShift : 0.f; >+ >+ float adjustedLeft = boxOrigin.x() + decorationInlineShift + leftOverhang; >+ float adjustedRight = boxOrigin.x() + width + decorationInlineShift + rightOverhang; >+ boxOrigin.setX(adjustedLeft); >+ width = std::max(0.f, adjustedRight - adjustedLeft); >+ return { boxOrigin, width }; >+} >+ > void TextBoxPainter::paintBackgroundDecorations(TextDecorationPainter& decorationPainter, const StyledMarkedText& markedText, const FloatRect& textBoxPaintRect) > { > if (m_isCombinedText) >@@ -934,10 +1020,11 @@ void TextBoxPainter::paintBackgroundDecorations(TextDecorationPainter& decoratio > return baseOffset - wavyOffset; > }; > >+ auto [insetBoxOrigin, insetWidth] = insetAdjustedDecorationLocationAndWidth(decoratingBox, markedText); > return TextDecorationPainter::BackgroundDecorationGeometry { > textOriginFromPaintRect(textBoxPaintRect), >- decoratingBox.location, >- decoratingBox.contentWidth, >+ insetBoxOrigin, >+ insetWidth, > textDecorationThickness, > underlineOffset(), > overlineOffset(), >@@ -1019,8 +1106,9 @@ void TextBoxPainter::paintForegroundDecorations(TextDecorationPainter& decoratio > > auto textDecorationThickness = resolveTextDecorationThicknessForPaintingBox(decoratingBox.textDecorationStyles.linethrough.thickness, decoratingBox.style.get(), deviceScaleFactor); > auto linethroughCenter = computedLinethroughCenter(decoratingBox.style.get(), textDecorationThickness, computedAutoTextDecorationThickness(decoratingBox.style.get(), deviceScaleFactor)); >- decorationPainter.paintForegroundDecorations({ decoratingBox.location >- , decoratingBox.contentWidth >+ auto [insetBoxOrigin, insetWidth] = insetAdjustedDecorationLocationAndWidth(decoratingBox, markedText); >+ decorationPainter.paintForegroundDecorations({ insetBoxOrigin >+ , insetWidth > , textDecorationThickness > , linethroughCenter > , wavyStrokeParameters(decoratingBox.style->computedFontSize()) }, decoratingBox.textDecorationStyles); >diff --git a/Source/WebCore/rendering/TextBoxPainter.h b/Source/WebCore/rendering/TextBoxPainter.h >index 97b2d2b37a8d..023c7ff8a9d2 100644 >--- a/Source/WebCore/rendering/TextBoxPainter.h >+++ b/Source/WebCore/rendering/TextBoxPainter.h >@@ -103,6 +103,13 @@ protected: > void collectDecoratingBoxesForBackgroundPainting(DecoratingBoxList&, const InlineIterator::TextBoxIterator&, const FloatRect& textBoxRect, const TextDecorationPainter::Styles&); > void collectDecoratingBoxesForForegroundPainting(DecoratingBoxList&, const InlineIterator::TextBoxIterator&, const FloatRect& textBoxRect, const TextDecorationPainter::Styles&); > >+ // Applies 'text-decoration-inset' to a decorating box, returning the decoration's adjusted >+ // logical origin and inline length. Honors box-decoration-break (via the inline box's closed >+ // edges) so the start inset only affects the first fragment and the end inset the last, and shares >+ // a symmetric inset's translation across bidi runs / marked-text pieces while applying the >+ // extend/trim overhang only at the piece that reaches the decoration's visual edge. >+ std::pair<FloatPoint, float> insetAdjustedDecorationLocationAndWidth(const DecoratingBox&, const StyledMarkedText&) const; >+ > // FIXME: We could just talk to the display box directly. > const InlineIterator::BoxModernPath m_textBox; > const CheckedRef<const RenderText> m_renderer; >diff --git a/Source/WebCore/rendering/TextDecorationPainter.cpp b/Source/WebCore/rendering/TextDecorationPainter.cpp >index f47d6fb8fb36..352f4e240f48 100644 >--- a/Source/WebCore/rendering/TextDecorationPainter.cpp >+++ b/Source/WebCore/rendering/TextDecorationPainter.cpp >@@ -34,6 +34,7 @@ > #include "RenderText.h" > #include "StyleAppleColorFilter.h" > #include "StyleComputedStyle+GettersInlines.h" >+#include "StyleTextDecorationInset.h" > #include "StyleTextDecorationLine.h" > #include "TextBoxPainter.h" > #include "TextRun.h" >@@ -178,7 +179,8 @@ bool TextDecorationPainter::Styles::operator==(const Styles& other) const > { > return underline.color == other.underline.color && overline.color == other.overline.color && linethrough.color == other.linethrough.color > && underline.decorationStyle == other.underline.decorationStyle && overline.decorationStyle == other.overline.decorationStyle && linethrough.decorationStyle == other.linethrough.decorationStyle >- && underline.thickness == other.underline.thickness && overline.thickness == other.overline.thickness && linethrough.thickness == other.linethrough.thickness; >+ && underline.thickness == other.underline.thickness && overline.thickness == other.overline.thickness && linethrough.thickness == other.linethrough.thickness >+ && inset == other.inset && boxDecorationBreak == other.boxDecorationBreak; > } > > TextDecorationPainter::TextDecorationPainter(GraphicsContext& context, const FontCascade& font, const Style::TextShadows& shadow, const Style::AppleColorFilter& colorFilter, bool isPrinting, WritingMode writingMode) >@@ -326,6 +328,11 @@ static void collectStylesForRenderer(TextDecorationPainter::Styles& result, cons > if (!decorations.containsAny({ Style::TextDecorationLine::Flag::Underline, Style::TextDecorationLine::Flag::Overline, Style::TextDecorationLine::Flag::LineThrough })) > return; > >+ if (!result.inset) { >+ result.inset = style.textDecorationInset(); >+ result.boxDecorationBreak = style.boxDecorationBreak(); >+ } >+ > auto color = TextDecorationPainter::decorationColor(style, paintBehavior); > auto decorationStyle = style.textDecorationStyle(); > auto thickness = style.textDecorationThickness(); >diff --git a/Source/WebCore/rendering/TextDecorationPainter.h b/Source/WebCore/rendering/TextDecorationPainter.h >index b725dc9a5065..c026f1245d72 100644 >--- a/Source/WebCore/rendering/TextDecorationPainter.h >+++ b/Source/WebCore/rendering/TextDecorationPainter.h >@@ -27,6 +27,7 @@ > #include "GraphicsContext.h" > #include "InlineTextBoxStyle.h" > #include "RenderStyleConstants.h" >+#include "StyleTextDecorationInset.h" > #include "StyleTextDecorationThickness.h" > #include <wtf/OptionSet.h> > >@@ -61,6 +62,9 @@ public: > DecorationStyleAndColor underline; > DecorationStyleAndColor overline; > DecorationStyleAndColor linethrough; >+ >+ std::optional<Style::TextDecorationInset> inset; >+ BoxDecorationBreak boxDecorationBreak { BoxDecorationBreak::Slice }; > }; > struct BackgroundDecorationGeometry { > FloatPoint textOrigin; >diff --git a/Source/WebCore/style/InlineTextBoxStyle.cpp b/Source/WebCore/style/InlineTextBoxStyle.cpp >index c1b0291740e2..9229c856b98a 100644 >--- a/Source/WebCore/style/InlineTextBoxStyle.cpp >+++ b/Source/WebCore/style/InlineTextBoxStyle.cpp >@@ -36,6 +36,7 @@ > #include "RenderElementInlines.h" > #include "RenderInline.h" > #include "RenderObjectInlines.h" >+#include "StyleTextDecorationInset.h" > > namespace WebCore { > >@@ -222,6 +223,18 @@ static InkOverflowForDecorations computedInkOverflowForDecorations(const Style:: > overflowResult.extendTop(-rect.y()); > overflowResult.extendBottom(rect.maxY() - height); > } >+ >+ // text-decoration-inset moves the decoration's endpoints along the inline axis. A negative inset >+ // extends the line outward past the text box, so that overhang must be part of the ink overflow >+ // or it gets clipped / left unrepainted. A positive inset (and 'auto', which only trims inward) >+ // needs no expansion. We expand both inline edges by the largest outward amount, which is a safe >+ // superset regardless of writing mode / direction. >+ auto outwardInset = std::max<float>({ 0.f, -lineStyle.textDecorationInset().resolvedStart(lineStyle, 0.f), -lineStyle.textDecorationInset().resolvedEnd(lineStyle, 0.f) }); >+ if (outwardInset) { >+ overflowResult.left() = std::max(overflowResult.left(), LayoutUnit(ceilf(outwardInset))); >+ overflowResult.right() = std::max(overflowResult.right(), LayoutUnit(ceilf(outwardInset))); >+ } >+ > return overflowResult; > } > >diff --git a/Source/WebCore/style/PropertyAllowlist.cpp b/Source/WebCore/style/PropertyAllowlist.cpp >index 77e95a3fc266..e58cb2b4a5fa 100644 >--- a/Source/WebCore/style/PropertyAllowlist.cpp >+++ b/Source/WebCore/style/PropertyAllowlist.cpp >@@ -58,6 +58,7 @@ bool isValidHighlightStyleProperty(CSSPropertyID id) > case CSSPropertyStrokeWidth: > case CSSPropertyTextDecoration: > case CSSPropertyTextDecorationColor: >+ case CSSPropertyTextDecorationInset: > case CSSPropertyTextDecorationLine: > case CSSPropertyTextDecorationSkip: > case CSSPropertyTextDecorationSkipInk: >@@ -180,6 +181,7 @@ bool isValidCueStyleProperty(CSSPropertyID id) > case CSSPropertyWhiteSpaceCollapse: > case CSSPropertyTextCombineUpright: > case CSSPropertyTextDecorationColor: >+ case CSSPropertyTextDecorationInset: > case CSSPropertyTextDecorationLine: > case CSSPropertyTextDecorationStyle: > case CSSPropertyTextDecorationThickness: >@@ -235,6 +237,7 @@ bool isValidCueSelectorStyleProperty(CSSPropertyID id) > case CSSPropertyWhiteSpaceCollapse: > case CSSPropertyTextCombineUpright: > case CSSPropertyTextDecorationColor: >+ case CSSPropertyTextDecorationInset: > case CSSPropertyTextDecorationLine: > case CSSPropertyTextDecorationStyle: > case CSSPropertyTextDecorationThickness: >diff --git a/Source/WebCore/style/StyleBuilderCustom.h b/Source/WebCore/style/StyleBuilderCustom.h >index 7d9940d4cc7d..53ea036fdabc 100644 >--- a/Source/WebCore/style/StyleBuilderCustom.h >+++ b/Source/WebCore/style/StyleBuilderCustom.h >@@ -176,6 +176,7 @@ inline SingleAnimationTimeline forwardInheritedValue(const SingleAnimationTimeli > inline SingleTransitionProperty forwardInheritedValue(const SingleTransitionProperty& value) { auto copy = value; return copy; } > inline StrokeWidth forwardInheritedValue(const StrokeWidth& value) { auto copy = value; return copy; } > inline TabSize forwardInheritedValue(const TabSize& value) { auto copy = value; return copy; } >+inline TextDecorationInset forwardInheritedValue(const TextDecorationInset& value) { auto copy = value; return copy; } > inline TextDecorationLine forwardInheritedValue(const TextDecorationLine& value) { auto copy = value; return copy; } > inline TextDecorationThickness forwardInheritedValue(const TextDecorationThickness& value) { auto copy = value; return copy; } > inline TextEmphasisStyle forwardInheritedValue(const TextEmphasisStyle& value) { auto copy = value; return copy; } >diff --git a/Source/WebCore/style/StyleDifference.cpp b/Source/WebCore/style/StyleDifference.cpp >index fc7d4fcd1864..87e676b47769 100644 >--- a/Source/WebCore/style/StyleDifference.cpp >+++ b/Source/WebCore/style/StyleDifference.cpp >@@ -100,7 +100,8 @@ public: > > if (&a.nonInheritedData() != &b.nonInheritedData() && a.nonInheritedData().rareData.ptr() != b.nonInheritedData().rareData.ptr()) { > if (a.nonInheritedData().rareData->textDecorationStyle != b.nonInheritedData().rareData->textDecorationStyle >- || a.nonInheritedData().rareData->textDecorationThickness != b.nonInheritedData().rareData->textDecorationThickness) >+ || a.nonInheritedData().rareData->textDecorationThickness != b.nonInheritedData().rareData->textDecorationThickness >+ || a.nonInheritedData().rareData->textDecorationInset != b.nonInheritedData().rareData->textDecorationInset) > return true; > } > >@@ -781,7 +782,7 @@ public: > // Don't return true; keep looking for another change. > } > >- if (a.textDecorationStyle != b.textDecorationStyle || a.textDecorationColor != b.textDecorationColor || a.textDecorationThickness != b.textDecorationThickness) >+ if (a.textDecorationStyle != b.textDecorationStyle || a.textDecorationColor != b.textDecorationColor || a.textDecorationThickness != b.textDecorationThickness || a.textDecorationInset != b.textDecorationInset) > return true; > > return false; >diff --git a/Source/WebCore/style/computed/StyleComputedStyleBase.h b/Source/WebCore/style/computed/StyleComputedStyleBase.h >index 99f205cc0eef..f340a3150be0 100644 >--- a/Source/WebCore/style/computed/StyleComputedStyleBase.h >+++ b/Source/WebCore/style/computed/StyleComputedStyleBase.h >@@ -353,6 +353,7 @@ struct StrokeWidth; > struct TabSize; > struct TextAutospace; > struct TextBoxEdge; >+struct TextDecorationInset; > struct TextDecorationLine; > struct TextDecorationThickness; > struct TextEmphasisPosition; >diff --git a/Source/WebCore/style/computed/data/StyleNonInheritedRareData.cpp b/Source/WebCore/style/computed/data/StyleNonInheritedRareData.cpp >index d96037905a9d..6016bbe63072 100644 >--- a/Source/WebCore/style/computed/data/StyleNonInheritedRareData.cpp >+++ b/Source/WebCore/style/computed/data/StyleNonInheritedRareData.cpp >@@ -79,6 +79,7 @@ NonInheritedRareData::NonInheritedRareData() > , offsetAnchor(ComputedStyle::initialOffsetAnchor()) > , offsetRotate(ComputedStyle::initialOffsetRotate()) > , textDecorationColor(ComputedStyle::initialTextDecorationColor()) >+ , textDecorationInset(ComputedStyle::initialTextDecorationInset()) > , textDecorationThickness(ComputedStyle::initialTextDecorationThickness()) > , scrollTimelines { CSS::Keyword::None { } } > , viewTimelines { CSS::Keyword::None { } } >@@ -187,6 +188,7 @@ inline NonInheritedRareData::NonInheritedRareData(const NonInheritedRareData& o) > , offsetAnchor(o.offsetAnchor) > , offsetRotate(o.offsetRotate) > , textDecorationColor(o.textDecorationColor) >+ , textDecorationInset(o.textDecorationInset) > , textDecorationThickness(o.textDecorationThickness) > , scrollTimelines(o.scrollTimelines) > , viewTimelines(o.viewTimelines) >@@ -301,6 +303,7 @@ bool NonInheritedRareData::operator==(const NonInheritedRareData& o) const > && offsetAnchor == o.offsetAnchor > && offsetRotate == o.offsetRotate > && textDecorationThickness == o.textDecorationThickness >+ && textDecorationInset == o.textDecorationInset > && scrollTimelines == o.scrollTimelines > && viewTimelines == o.viewTimelines > && timelineScope == o.timelineScope >@@ -444,6 +447,7 @@ void NonInheritedRareData::dumpDifferences(TextStream& ts, const NonInheritedRar > LOG_IF_DIFFERENT(offsetRotate); > > LOG_IF_DIFFERENT(textDecorationThickness); >+ LOG_IF_DIFFERENT(textDecorationInset); > > LOG_IF_DIFFERENT(scrollTimelines); > LOG_IF_DIFFERENT(viewTimelines); >diff --git a/Source/WebCore/style/computed/data/StyleNonInheritedRareData.h b/Source/WebCore/style/computed/data/StyleNonInheritedRareData.h >index 47ec3e37fae9..d54923c86b70 100644 >--- a/Source/WebCore/style/computed/data/StyleNonInheritedRareData.h >+++ b/Source/WebCore/style/computed/data/StyleNonInheritedRareData.h >@@ -71,6 +71,7 @@ > #include <WebCore/StyleShapeImageThreshold.h> > #include <WebCore/StyleShapeMargin.h> > #include <WebCore/StyleShapeOutside.h> >+#include <WebCore/StyleTextDecorationInset.h> > #include <WebCore/StyleTextDecorationThickness.h> > #include <WebCore/StyleTimelineTriggers.h> > #include <WebCore/StyleTouchAction.h> >@@ -182,6 +183,7 @@ public: > OffsetRotate offsetRotate; > > Color textDecorationColor; >+ TextDecorationInset textDecorationInset; > TextDecorationThickness textDecorationThickness; > > ScrollTimelines scrollTimelines; >diff --git a/Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.cpp b/Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.cpp >new file mode 100644 >index 000000000000..82475a879b92 >--- /dev/null >+++ b/Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.cpp >@@ -0,0 +1,75 @@ >+/* >+ * Copyright (C) 2026 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "StyleTextDecorationInset.h" >+ >+#include "StyleBuilderChecking.h" >+#include "StyleComputedStyle+GettersInlines.h" >+#include "StylePrimitiveNumericTypes+CSSValueConversion.h" >+#include "StylePrimitiveNumericTypes+Evaluation.h" >+ >+namespace WebCore { >+namespace Style { >+ >+using namespace CSS::Literals; >+ >+float TextDecorationInset::resolvedStart(const Style::ComputedStyle& style, float autoValue) const >+{ >+ if (auto pair = tryValue()) >+ return Style::evaluate<float>(pair->first(), style.usedZoomForLength()); >+ return autoValue; >+} >+ >+float TextDecorationInset::resolvedEnd(const Style::ComputedStyle& style, float autoValue) const >+{ >+ if (auto pair = tryValue()) >+ return Style::evaluate<float>(pair->second(), style.usedZoomForLength()); >+ return autoValue; >+} >+ >+// MARK: - Conversion >+ >+auto CSSValueConversion<TextDecorationInsetPair>::operator()(BuilderState& state, const CSSValue& value) -> TextDecorationInsetPair >+{ >+ using Length = Style::Length<CSS::AllUnzoomed>; >+ >+ if (RefPtr primitiveValue = dynamicDowncast<CSSPrimitiveValue>(value)) { >+ auto length = toStyleFromCSSValue<Length>(state, *primitiveValue); >+ return { length, length }; >+ } >+ >+ auto pair = requiredPairDowncast<CSSPrimitiveValue>(state, value); >+ if (!pair) >+ return { 0_css_px, 0_css_px }; >+ >+ return { >+ toStyleFromCSSValue<Length>(state, pair->first), >+ toStyleFromCSSValue<Length>(state, pair->second), >+ }; >+} >+ >+} // namespace Style >+} // namespace WebCore >diff --git a/Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.h b/Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.h >new file mode 100644 >index 000000000000..2170865a4df2 >--- /dev/null >+++ b/Source/WebCore/style/values/text-decoration/StyleTextDecorationInset.h >@@ -0,0 +1,84 @@ >+/* >+ * Copyright (C) 2026 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include <WebCore/StylePrimitiveNumericTypes.h> >+#include <WebCore/StyleValueTypes.h> >+ >+namespace WebCore { >+namespace Style { >+using TextDecorationInsetPair = MinimallySerializingSpaceSeparatedPair<Length<CSS::AllUnzoomed>>; >+} >+} >+ >+// text-decoration-inset stores 'auto' or a length pair, so ValueOrKeyword needs a Markable >+// representation of the pair; the pair is empty exactly when its first length is empty. >+namespace WTF { >+template<> struct MarkableTraits<WebCore::Style::TextDecorationInsetPair> { >+ using Pair = WebCore::Style::TextDecorationInsetPair; >+ using Length = WebCore::Style::Length<WebCore::CSS::AllUnzoomed>; >+ static bool isEmptyValue(const Pair& value) { return MarkableTraits<Length>::isEmptyValue(value.first()); } >+ static Pair emptyValue() { return { MarkableTraits<Length>::emptyValue(), MarkableTraits<Length>::emptyValue() }; } >+}; >+} >+ >+namespace WebCore { >+namespace Style { >+ >+// <'text-decoration-inset'> = auto | <length>{1,2} >+// The first value applies to the start endpoint, the second to the end endpoint of the line >+// decorations; a single value applies to both. Positive values move an endpoint inward (trimming >+// the decoration), negative values move it outward (extending it). 'auto' lets the UA choose an >+// inset so that adjacent identical underlined elements do not appear to share a single continuous >+// underline. Note that 'auto' is distinct from '0'. >+// https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property >+struct TextDecorationInset : ValueOrKeyword<TextDecorationInsetPair, CSS::Keyword::Auto> { >+ using Base::Base; >+ >+ TextDecorationInset(CSS::ValueLiteral<CSS::LengthUnit::Px> literal) >+ : Base(Value { Length<CSS::AllUnzoomed> { literal }, Length<CSS::AllUnzoomed> { literal } }) >+ { >+ } >+ >+ bool isAuto() const { return isKeyword(); } >+ >+ // Resolves the start/end inset to used CSS pixels. For 'auto', returns the UA-chosen autoValue >+ // supplied by the caller (which depends on the decorating box's font). >+ float resolvedStart(const Style::ComputedStyle&, float autoValue) const; >+ float resolvedEnd(const Style::ComputedStyle&, float autoValue) const; >+}; >+ >+// MARK: - Conversion >+ >+// Conversion of the 'auto' keyword is handled generically (CSSValueConversion<ValueOrKeywordDerived>); >+// only the length-pair value needs the usual pair unpacking. >+template<> struct CSSValueConversion<TextDecorationInsetPair> { >+ auto operator()(BuilderState&, const CSSValue&) -> TextDecorationInsetPair; >+}; >+ >+} // namespace Style >+} // namespace WebCore >+ >+DEFINE_VARIANT_LIKE_CONFORMANCE(WebCore::Style::TextDecorationInset) >diff --git a/LayoutTests/TestExpectations b/LayoutTests/TestExpectations >index 124e7b0cfd34..9dfb7d9e8c5e 100644 >--- a/LayoutTests/TestExpectations >+++ b/LayoutTests/TestExpectations >@@ -4683,31 +4683,14 @@ webkit.org/b/244813 imported/w3c/web-platform-tests/css/css-text-decor/text-deco > webkit.org/b/244813 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-skip-spaces-009.html [ ImageOnlyFailure ] > imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-thickness-length-rounding-001.html [ ImageOnlyFailure ] > imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-thickness-length-rounding-002.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-001.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-002.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-003.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-004.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-005.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-006.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-007.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-008.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-009.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-010.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-011.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-012.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-013.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-014.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-015.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-016.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-017.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-018.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-019.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-020.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-021.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-022.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-023.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-024.html [ ImageOnlyFailure ] >-webkit.org/b/304166 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-025.html [ ImageOnlyFailure ] >+ >+# fractional-position endpoint rounds up to a device pixel >+webkit.org/b/244813 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-009.html [ ImageOnlyFailure ] >+webkit.org/b/244813 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-014.html [ ImageOnlyFailure ] >+ >+# Not a text-decoration-inset bug: a pre-existing ~1px vertical decoration-position difference in a >+# columns:2 multicol context with inline vertical borders. Reproduces with the feature disabled. >+webkit.org/b/304168 imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-025.html [ ImageOnlyFailure ] > imported/w3c/web-platform-tests/css/css-text-decor/text-emphasis-color-property-001.html [ ImageOnlyFailure ] > imported/w3c/web-platform-tests/css/css-text-decor/text-emphasis-color-property-001a.html [ ImageOnlyFailure ] > imported/w3c/web-platform-tests/css/css-text-decor/text-emphasis-color-property-001b.html [ ImageOnlyFailure ] >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml-expected.txt >index 1ba82c0506ca..4d78b0c97916 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml-expected.txt >@@ -351,6 +351,7 @@ PASS text-box-edge > PASS text-box-trim > PASS text-combine-upright > PASS text-decoration-color >+PASS text-decoration-inset > PASS text-decoration-line > PASS text-decoration-skip-ink > PASS text-decoration-style >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-computed-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-computed-expected.txt >index 007652014e8b..49ace8ee9180 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-computed-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-computed-expected.txt >@@ -1,12 +1,12 @@ > >-FAIL Property text-decoration-inset value '0px' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >-FAIL Property text-decoration-inset value '0' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >-FAIL Property text-decoration-inset value '0px 0px' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >-FAIL Property text-decoration-inset value '0.5em' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >-FAIL Property text-decoration-inset value '-1em' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >-FAIL Property text-decoration-inset value '-1ch -1ch' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >-FAIL Property text-decoration-inset value '1px 2px' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >-FAIL Property text-decoration-inset value '1ch -1ch' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >-FAIL Property text-decoration-inset value 'calc(1em / 4) calc(-1ch)' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >-FAIL Property text-decoration-inset value 'auto' assert_true: text-decoration-inset doesn't seem to be supported in the computed style expected true got false >+PASS Property text-decoration-inset value '0px' >+PASS Property text-decoration-inset value '0' >+PASS Property text-decoration-inset value '0px 0px' >+PASS Property text-decoration-inset value '0.5em' >+PASS Property text-decoration-inset value '-1em' >+PASS Property text-decoration-inset value '-1ch -1ch' >+PASS Property text-decoration-inset value '1px 2px' >+PASS Property text-decoration-inset value '1ch -1ch' >+PASS Property text-decoration-inset value 'calc(1em / 4) calc(-1ch)' >+PASS Property text-decoration-inset value 'auto' > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-valid-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-valid-expected.txt >index e392322573bf..115049c2bf6a 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-valid-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/parsing/text-decoration-inset-valid-expected.txt >@@ -1,12 +1,12 @@ > >-FAIL e.style['text-decoration-inset'] = "0px" should set the property value assert_not_equals: property should be set got disallowed value "" >-FAIL e.style['text-decoration-inset'] = "0" should set the property value assert_not_equals: property should be set got disallowed value "" >-FAIL e.style['text-decoration-inset'] = "0px 0px" should set the property value assert_not_equals: property should be set got disallowed value "" >-FAIL e.style['text-decoration-inset'] = "0.5em" should set the property value assert_not_equals: property should be set got disallowed value "" >-FAIL e.style['text-decoration-inset'] = "-1em" should set the property value assert_not_equals: property should be set got disallowed value "" >-FAIL e.style['text-decoration-inset'] = "-1ch -1ch" should set the property value assert_not_equals: property should be set got disallowed value "" >-FAIL e.style['text-decoration-inset'] = "1px 2px" should set the property value assert_not_equals: property should be set got disallowed value "" >-FAIL e.style['text-decoration-inset'] = "1ch -1ch" should set the property value assert_not_equals: property should be set got disallowed value "" >-FAIL e.style['text-decoration-inset'] = "calc(1em / 4) calc(-1ch)" should set the property value assert_not_equals: property should be set got disallowed value "" >-FAIL e.style['text-decoration-inset'] = "auto" should set the property value assert_not_equals: property should be set got disallowed value "" >+PASS e.style['text-decoration-inset'] = "0px" should set the property value >+PASS e.style['text-decoration-inset'] = "0" should set the property value >+PASS e.style['text-decoration-inset'] = "0px 0px" should set the property value >+PASS e.style['text-decoration-inset'] = "0.5em" should set the property value >+PASS e.style['text-decoration-inset'] = "-1em" should set the property value >+PASS e.style['text-decoration-inset'] = "-1ch -1ch" should set the property value >+PASS e.style['text-decoration-inset'] = "1px 2px" should set the property value >+PASS e.style['text-decoration-inset'] = "1ch -1ch" should set the property value >+PASS e.style['text-decoration-inset'] = "calc(1em / 4) calc(-1ch)" should set the property value >+PASS e.style['text-decoration-inset'] = "auto" should set the property value > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk-expected.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk-expected.html >new file mode 100644 >index 000000000000..b15cfb16b631 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk-expected.html >@@ -0,0 +1,11 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset: auto separates adjacent underlined CJK runs (reference)</title> >+<style> >+ body { margin: 20px; background: white; } >+ div { font: 60px/1.5 sans-serif; color: black; } >+ /* WebKit's 'auto' amount is font-size/8 = 0.125em, applied to both endpoints. */ >+ u { text-decoration-line: underline; text-decoration-color: blue; text-underline-position: under; text-decoration-inset: 0.125em; } >+</style> >+<p>The underlines for the two elements should be visibly separated by a gap:</p> >+<div lang="zh"><u>ç³äº</u><u>è¾ä¿ä¿</u></div> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk.html >new file mode 100644 >index 000000000000..b063e0dbdf52 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-cjk.html >@@ -0,0 +1,12 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset: auto separates adjacent underlined CJK runs</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="'text-decoration-inset: auto' insets each decorating box's endpoints by a UA-chosen amount so two adjacent underlined elements do not appear to share a single underline (the spec's CJK example, <u>ç³äº</u><u>è¾ä¿ä¿</u>). WebKit's auto amount is font-size/8, so 'auto' must render identically to '0.125em'."> >+<style> >+ body { margin: 20px; background: white; } >+ div { font: 60px/1.5 sans-serif; color: black; } >+ u { text-decoration-line: underline; text-decoration-color: blue; text-underline-position: under; text-decoration-inset: auto; } >+</style> >+<p>The underlines for the two elements should be visibly separated by a gap:</p> >+<div lang="zh"><u>ç³äº</u><u>è¾ä¿ä¿</u></div> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-expected-mismatch.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-expected-mismatch.html >new file mode 100644 >index 000000000000..6f84e07b55a3 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto-expected-mismatch.html >@@ -0,0 +1,5 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset: auto trims the underline (mismatch reference)</title> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><u>abcdef</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto.html >new file mode 100644 >index 000000000000..bfd95aec5e59 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-auto.html >@@ -0,0 +1,7 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset: auto trims the underline</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="text-decoration-inset: auto insets the endpoints by a UA-chosen amount, so the underline differs from an un-inset one."> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><u style="text-decoration-inset: auto">abcdef</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break-expected-mismatch.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break-expected-mismatch.html >new file mode 100644 >index 000000000000..2579e1960011 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break-expected-mismatch.html >@@ -0,0 +1,9 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset honors box-decoration-break: slice (mismatch reference uses clone)</title> >+<style> >+ body { margin: 20px; font: 40px/1.5 monospace; } >+ div { width: 200px; } >+ span { text-decoration-line: underline; text-decoration-inset: 8px; -webkit-box-decoration-break: clone; } >+</style> >+<div><span>aaaaa bbbbb</span></div> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break.html >new file mode 100644 >index 000000000000..7ff93227f454 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-box-decoration-break.html >@@ -0,0 +1,11 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset honors box-decoration-break: slice</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="With box-decoration-break: slice, the start inset applies only to the first line fragment's start and the end inset only to the last fragment's end; this differs from box-decoration-break: clone, which insets every fragment on both sides."> >+<style> >+ body { margin: 20px; font: 40px/1.5 monospace; } >+ div { width: 200px; } >+ span { text-decoration-line: underline; text-decoration-inset: 8px; -webkit-box-decoration-break: slice; } >+</style> >+<div><span>aaaaa bbbbb</span></div> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed-expected.txt >new file mode 100644 >index 000000000000..4c3f41c99682 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed-expected.txt >@@ -0,0 +1,20 @@ >+ >+PASS text-decoration-inset initial computed value is '0px' >+PASS text-decoration-inset: auto >+PASS text-decoration-inset: 0 computes to '0px' >+PASS text-decoration-inset: 5px >+PASS text-decoration-inset: two equal values serialize as one >+PASS text-decoration-inset: 1px 2px >+PASS text-decoration-inset: negative value (extends the decoration) >+PASS text-decoration-inset: mixed sign start/end >+PASS text-decoration-inset: em resolves against font-size >+PASS text-decoration-inset: calc resolves to an absolute length >+PASS text-decoration-inset: calc with em resolves against font-size >+PASS text-decoration-inset: absolute units resolve to px >+PASS text-decoration-inset: negative em resolves to px >+PASS text-decoration-inset: two values, one a calc >+PASS text-decoration-inset: two equal computed lengths serialize as one >+PASS text-decoration-inset ignores invalid values (auto cannot combine with a length) >+PASS text-decoration-inset is not inherited >+PASS text-decoration-inset: inherit resolves to the parent value >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed.html >new file mode 100644 >index 000000000000..17b0a8df5ca2 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-computed.html >@@ -0,0 +1,96 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: parsing and computed value of text-decoration-inset</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="text-decoration-inset accepts auto or one-or-two <length> values, is not inherited, and computes lengths to absolute values."> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<div id="target" style="font-size: 16px"></div> >+<div id="parent" style="text-decoration-inset: 4px"><div id="child"></div></div> >+<script> >+function computedValueFor(value) { >+ var target = document.getElementById("target"); >+ target.style.textDecorationInset = ""; >+ target.style.textDecorationInset = value; >+ return getComputedStyle(target).textDecorationInset; >+} >+ >+test(function() { >+ assert_equals(computedValueFor(""), "0px"); >+}, "text-decoration-inset initial computed value is '0px'"); >+ >+test(function() { >+ assert_equals(computedValueFor("auto"), "auto"); >+}, "text-decoration-inset: auto"); >+ >+test(function() { >+ assert_equals(computedValueFor("0"), "0px"); >+}, "text-decoration-inset: 0 computes to '0px'"); >+ >+test(function() { >+ assert_equals(computedValueFor("5px"), "5px"); >+}, "text-decoration-inset: 5px"); >+ >+test(function() { >+ assert_equals(computedValueFor("5px 5px"), "5px"); >+}, "text-decoration-inset: two equal values serialize as one"); >+ >+test(function() { >+ assert_equals(computedValueFor("1px 2px"), "1px 2px"); >+}, "text-decoration-inset: 1px 2px"); >+ >+test(function() { >+ assert_equals(computedValueFor("-3px"), "-3px"); >+}, "text-decoration-inset: negative value (extends the decoration)"); >+ >+test(function() { >+ assert_equals(computedValueFor("1px -2px"), "1px -2px"); >+}, "text-decoration-inset: mixed sign start/end"); >+ >+test(function() { >+ assert_equals(computedValueFor("2em"), "32px"); >+}, "text-decoration-inset: em resolves against font-size"); >+ >+test(function() { >+ assert_equals(computedValueFor("calc(10px - 8px)"), "2px"); >+}, "text-decoration-inset: calc resolves to an absolute length"); >+ >+test(function() { >+ assert_equals(computedValueFor("calc(2em - 8px)"), "24px"); >+}, "text-decoration-inset: calc with em resolves against font-size"); >+ >+test(function() { >+ assert_equals(computedValueFor("1in"), "96px"); >+}, "text-decoration-inset: absolute units resolve to px"); >+ >+test(function() { >+ assert_equals(computedValueFor("-1em"), "-16px"); >+}, "text-decoration-inset: negative em resolves to px"); >+ >+test(function() { >+ assert_equals(computedValueFor("10px calc(1em + 4px)"), "10px 20px"); >+}, "text-decoration-inset: two values, one a calc"); >+ >+test(function() { >+ assert_equals(computedValueFor("2em 2em"), "32px"); >+}, "text-decoration-inset: two equal computed lengths serialize as one"); >+ >+test(function() { >+ var target = document.getElementById("target"); >+ target.style.textDecorationInset = "3px"; >+ target.style.textDecorationInset = "auto 5px"; >+ assert_equals(target.style.textDecorationInset, "3px"); >+}, "text-decoration-inset ignores invalid values (auto cannot combine with a length)"); >+ >+test(function() { >+ // text-decoration-inset is not inherited: the child computes the initial value even though its parent sets it. >+ assert_equals(getComputedStyle(document.getElementById("child")).textDecorationInset, "0px"); >+}, "text-decoration-inset is not inherited"); >+ >+test(function() { >+ // The 'inherit' keyword still explicitly pulls the parent's value. >+ var child = document.getElementById("child"); >+ child.style.textDecorationInset = "inherit"; >+ assert_equals(getComputedStyle(child).textDecorationInset, "4px"); >+}, "text-decoration-inset: inherit resolves to the parent value"); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid-expected.txt >new file mode 100644 >index 000000000000..444ef81ced8c >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid-expected.txt >@@ -0,0 +1,17 @@ >+ >+PASS e.style['text-decoration-inset'] = "otto" should not set the property value >+PASS e.style['text-decoration-inset'] = "none" should not set the property value >+PASS e.style['text-decoration-inset'] = "normal" should not set the property value >+PASS e.style['text-decoration-inset'] = "red" should not set the property value >+PASS e.style['text-decoration-inset'] = "10deg" should not set the property value >+PASS e.style['text-decoration-inset'] = "!@#$%" should not set the property value >+PASS e.style['text-decoration-inset'] = "10" should not set the property value >+PASS e.style['text-decoration-inset'] = "10 20" should not set the property value >+PASS e.style['text-decoration-inset'] = "10%" should not set the property value >+PASS e.style['text-decoration-inset'] = "10px 20%" should not set the property value >+PASS e.style['text-decoration-inset'] = "calc(10px + 10%)" should not set the property value >+PASS e.style['text-decoration-inset'] = "auto auto" should not set the property value >+PASS e.style['text-decoration-inset'] = "auto 10px" should not set the property value >+PASS e.style['text-decoration-inset'] = "10px auto" should not set the property value >+PASS e.style['text-decoration-inset'] = "10px 20px 30px" should not set the property value >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid.html >new file mode 100644 >index 000000000000..79be28b4a364 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-invalid.html >@@ -0,0 +1,35 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: parsing text-decoration-inset with invalid values</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="text-decoration-inset supports: auto | <length>{1,2}"> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script src="/css/support/parsing-testcommon.js"></script> >+<div id="target"></div> >+<script> >+// Nonsense / wrong type. >+test_invalid_value("text-decoration-inset", "otto"); >+test_invalid_value("text-decoration-inset", "none"); >+test_invalid_value("text-decoration-inset", "normal"); >+test_invalid_value("text-decoration-inset", "red"); >+test_invalid_value("text-decoration-inset", "10deg"); >+test_invalid_value("text-decoration-inset", "!@#$%"); >+ >+// Unitless non-zero number is not a <length>. >+test_invalid_value("text-decoration-inset", "10"); >+test_invalid_value("text-decoration-inset", "10 20"); >+ >+// Percentages are not accepted (grammar is <length>, not <length-percentage>). >+test_invalid_value("text-decoration-inset", "10%"); >+test_invalid_value("text-decoration-inset", "10px 20%"); >+test_invalid_value("text-decoration-inset", "calc(10px + 10%)"); >+ >+// 'auto' cannot combine with a length, and only one keyword is allowed. >+test_invalid_value("text-decoration-inset", "auto auto"); >+test_invalid_value("text-decoration-inset", "auto 10px"); >+test_invalid_value("text-decoration-inset", "10px auto"); >+ >+// At most two <length> values. >+test_invalid_value("text-decoration-inset", "10px 20px 30px"); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through-expected.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through-expected.html >new file mode 100644 >index 000000000000..65d2b1d89793 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through-expected.html >@@ -0,0 +1,5 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset applies to line-through (reference)</title> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><span>abcdef</span></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through.html >new file mode 100644 >index 000000000000..39ce9b337a04 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-line-through.html >@@ -0,0 +1,7 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset applies to line-through</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="text-decoration-inset adjusts the line-through endpoints; a large inset trims the line-through away."> >+<style>body { margin: 20px; font: 40px/1.5 monospace; } span { text-decoration-line: line-through; }</style> >+<p><span style="text-decoration-inset: 1000px">abcdef</span></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap-expected.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap-expected.html >new file mode 100644 >index 000000000000..a9aa56e4877c >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap-expected.html >@@ -0,0 +1,12 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset is not re-applied at interior marked-text boundaries (reference)</title> >+<link rel="stylesheet" href="/fonts/ahem.css"> >+<style> >+ body { margin: 20px; } >+ div { font: 40px/1.5 Ahem; color: black; } >+ /* One continuous underline over the whole element, trimmed 8px only at the outer ends. */ >+ u { text-decoration-line: underline; text-decoration-color: blue; text-underline-position: under; text-decoration-inset: 8px; } >+ span { color: green; } >+</style> >+<div><u>XX<span>XX</span>XX</u></div> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap.html >new file mode 100644 >index 000000000000..5941a867ac38 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-marked-text-gap.html >@@ -0,0 +1,24 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset is not re-applied at interior marked-text boundaries</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="A single underlined element split into several marked-text pieces (here by a selection over the middle) is one continuous decoration: the inset must trim only the element's true start/end endpoints, not the interior boundaries between marked-text pieces."> >+<link rel="match" href="text-decoration-inset-marked-text-gap-expected.html"> >+<link rel="stylesheet" href="/fonts/ahem.css"> >+<style> >+ body { margin: 20px; } >+ div { font: 40px/1.5 Ahem; color: black; } >+ /* The selection only changes the text color, which keeps the decoration visually continuous >+ but splits it into separate marked-text pieces during painting. */ >+ #target::selection { color: green; background-color: transparent; } >+ u { text-decoration-line: underline; text-decoration-color: blue; text-underline-position: under; text-decoration-inset: 8px; } >+</style> >+<div><u id="target">XXXXXX</u></div> >+<script> >+ const target = document.getElementById("target").firstChild; >+ const range = new Range(); >+ range.setStart(target, 2); >+ range.setEnd(target, 4); >+ getSelection().removeAllRanges(); >+ getSelection().addRange(range); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative-expected-mismatch.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative-expected-mismatch.html >new file mode 100644 >index 000000000000..060f1f854dba >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative-expected-mismatch.html >@@ -0,0 +1,5 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: negative text-decoration-inset extends the underline (mismatch reference)</title> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><u>abcdef</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative.html >new file mode 100644 >index 000000000000..d48bce3478a3 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-negative.html >@@ -0,0 +1,7 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: negative text-decoration-inset extends the underline</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="A negative text-decoration-inset moves the endpoints outward, extending the underline beyond the text, so it differs from an un-inset one."> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><u style="text-decoration-inset: -10px">abcdef</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited-expected.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited-expected.html >new file mode 100644 >index 000000000000..31f7c7b0f41f >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited-expected.html >@@ -0,0 +1,5 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset is not inherited (reference)</title> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<div><u>abcdef</u></div> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited.html >new file mode 100644 >index 000000000000..6e7c99b802da >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-not-inherited.html >@@ -0,0 +1,7 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset is not inherited</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="text-decoration-inset is not inherited: a large inset on the parent does not affect the child's own underline."> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<div style="text-decoration-inset: 1000px"><u>abcdef</u></div> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value-expected.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value-expected.html >new file mode 100644 >index 000000000000..1121945b90f8 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value-expected.html >@@ -0,0 +1,5 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: a single text-decoration-inset value applies to both endpoints (reference)</title> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><u style="text-decoration-inset: 12px 12px">wwwwwwww</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value.html >new file mode 100644 >index 000000000000..dad664a35386 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-one-value.html >@@ -0,0 +1,7 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: a single text-decoration-inset value applies to both endpoints</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="A single <length> applies to both the start and end endpoints, i.e. '12px' == '12px 12px'."> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><u style="text-decoration-inset: 12px">wwwwwwww</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline-expected.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline-expected.html >new file mode 100644 >index 000000000000..dbd0bb05c56f >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline-expected.html >@@ -0,0 +1,5 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset applies to overline (reference)</title> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><span>abcdef</span></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline.html >new file mode 100644 >index 000000000000..7a0291035f60 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-overline.html >@@ -0,0 +1,7 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset applies to overline</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="text-decoration-inset adjusts the overline endpoints; a large inset trims the overline away."> >+<style>body { margin: 20px; font: 40px/1.5 monospace; } span { text-decoration-line: overline; }</style> >+<p><span style="text-decoration-inset: 1000px">abcdef</span></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-expected.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-expected.html >new file mode 100644 >index 000000000000..36534c8d599d >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-expected.html >@@ -0,0 +1,8 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset trims the underline inward (reference)</title> >+<style> >+ body { margin: 20px; font: 40px/1.5 monospace; } >+ u { text-decoration-line: none; } >+</style> >+<p><u>abc</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-ref.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-ref.html >new file mode 100644 >index 000000000000..36534c8d599d >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline-ref.html >@@ -0,0 +1,8 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset trims the underline inward (reference)</title> >+<style> >+ body { margin: 20px; font: 40px/1.5 monospace; } >+ u { text-decoration-line: none; } >+</style> >+<p><u>abc</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline.html >new file mode 100644 >index 000000000000..67969486dc2e >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-trims-underline.html >@@ -0,0 +1,12 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset trims the underline inward</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<link rel="match" href="text-decoration-inset-trims-underline-ref.html"> >+<meta name="assert" content="A large positive text-decoration-inset trims the underline from both endpoints until nothing is drawn."> >+<style> >+ body { margin: 20px; font: 40px/1.5 monospace; } >+ /* The start and end insets together exceed the underline length, so no underline is drawn. */ >+ u { text-decoration-inset: 1000px; } >+</style> >+<p><u>abc</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid-expected.txt >new file mode 100644 >index 000000000000..9f3f691349dc >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid-expected.txt >@@ -0,0 +1,24 @@ >+ >+PASS e.style['text-decoration-inset'] = "auto" should set the property value >+PASS e.style['text-decoration-inset'] = "0px" should set the property value >+PASS e.style['text-decoration-inset'] = "10px" should set the property value >+PASS e.style['text-decoration-inset'] = "-10px" should set the property value >+PASS e.style['text-decoration-inset'] = "0.5em" should set the property value >+PASS e.style['text-decoration-inset'] = "2em" should set the property value >+PASS e.style['text-decoration-inset'] = "-3em" should set the property value >+PASS e.style['text-decoration-inset'] = "100px" should set the property value >+PASS e.style['text-decoration-inset'] = "1in" should set the property value >+PASS e.style['text-decoration-inset'] = "2cm" should set the property value >+PASS e.style['text-decoration-inset'] = "10pt" should set the property value >+PASS e.style['text-decoration-inset'] = "2rem" should set the property value >+PASS e.style['text-decoration-inset'] = "calc(10px + 2px)" should set the property value >+PASS e.style['text-decoration-inset'] = "calc(2em - 5px)" should set the property value >+PASS e.style['text-decoration-inset'] = "10px 20px" should set the property value >+PASS e.style['text-decoration-inset'] = "20px 10px" should set the property value >+PASS e.style['text-decoration-inset'] = "-5px 8px" should set the property value >+PASS e.style['text-decoration-inset'] = "10px -20px" should set the property value >+PASS e.style['text-decoration-inset'] = "0px 0px" should set the property value >+PASS e.style['text-decoration-inset'] = "10px 0px" should set the property value >+PASS e.style['text-decoration-inset'] = "1em 10px" should set the property value >+PASS e.style['text-decoration-inset'] = "calc(1px + 1px) 5px" should set the property value >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid.html >new file mode 100644 >index 000000000000..0224f600ffc8 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-valid.html >@@ -0,0 +1,40 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: parsing text-decoration-inset with valid values</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="text-decoration-inset supports: auto | <length>{1,2}"> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script src="/css/support/parsing-testcommon.js"></script> >+<div id="target"></div> >+<script> >+// Keyword. >+test_valid_value("text-decoration-inset", "auto"); >+ >+// Single <length>, various units and signs. >+test_valid_value("text-decoration-inset", "0px"); >+test_valid_value("text-decoration-inset", "10px"); >+test_valid_value("text-decoration-inset", "-10px"); >+test_valid_value("text-decoration-inset", "0.5em"); >+test_valid_value("text-decoration-inset", "2em"); >+test_valid_value("text-decoration-inset", "-3em"); >+test_valid_value("text-decoration-inset", "100px"); >+test_valid_value("text-decoration-inset", "1in"); >+test_valid_value("text-decoration-inset", "2cm"); >+test_valid_value("text-decoration-inset", "10pt"); >+test_valid_value("text-decoration-inset", "2rem"); >+ >+// calc(). >+test_valid_value("text-decoration-inset", "calc(10px + 2px)", "calc(12px)"); >+test_valid_value("text-decoration-inset", "calc(2em - 5px)"); >+ >+// Two <length> values (start end). >+test_valid_value("text-decoration-inset", "10px 20px"); >+test_valid_value("text-decoration-inset", "20px 10px"); >+test_valid_value("text-decoration-inset", "-5px 8px"); >+test_valid_value("text-decoration-inset", "10px -20px"); >+test_valid_value("text-decoration-inset", "0px 0px", "0px"); >+test_valid_value("text-decoration-inset", "10px 0px"); >+test_valid_value("text-decoration-inset", "1em 10px"); >+test_valid_value("text-decoration-inset", "calc(1px + 1px) 5px", "calc(2px) 5px"); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero-expected.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero-expected.html >new file mode 100644 >index 000000000000..6995147dde43 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero-expected.html >@@ -0,0 +1,5 @@ >+<!DOCTYPE html> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset: 0 does not change the decoration (reference)</title> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><u>abcdef</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero.html b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero.html >new file mode 100644 >index 000000000000..3b5e125a0704 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/css/css-text-decor/text-decoration-inset-zero.html >@@ -0,0 +1,7 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ CSSTextDecorationInsetEnabled=true ] --> >+<meta charset="utf-8"> >+<title>CSS Text Decoration: text-decoration-inset: 0 does not change the decoration</title> >+<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#text-decoration-inset-property"> >+<meta name="assert" content="text-decoration-inset: 0 (the initial value) leaves the underline unchanged."> >+<style>body { margin: 20px; font: 40px/1.5 monospace; }</style> >+<p><u style="text-decoration-inset: 0">abcdef</u></p> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/html/rendering/widgets/shadow-dom-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/html/rendering/widgets/shadow-dom-expected.txt >index 44b490fbd3c6..2ce64b1235b1 100644 >--- a/LayoutTests/imported/w3c/web-platform-tests/html/rendering/widgets/shadow-dom-expected.txt >+++ b/LayoutTests/imported/w3c/web-platform-tests/html/rendering/widgets/shadow-dom-expected.txt >@@ -1,9 +1,9 @@ > > >-FAIL <video controls=""></video> has a shadow tree with no slots assert_equals: child should be outside the flat tree expected 0 but got 445 >-FAIL <video></video> has a shadow tree with no slots assert_equals: child should be outside the flat tree expected 0 but got 445 >-FAIL <audio></audio> has a shadow tree with no slots assert_equals: child should be outside the flat tree expected 0 but got 445 >-FAIL <audio controls=""></audio> has a shadow tree with no slots assert_equals: child should be outside the flat tree expected 0 but got 446 >+FAIL <video controls=""></video> has a shadow tree with no slots assert_equals: child should be outside the flat tree expected 0 but got 446 >+FAIL <video></video> has a shadow tree with no slots assert_equals: child should be outside the flat tree expected 0 but got 446 >+FAIL <audio></audio> has a shadow tree with no slots assert_equals: child should be outside the flat tree expected 0 but got 446 >+FAIL <audio controls=""></audio> has a shadow tree with no slots assert_equals: child should be outside the flat tree expected 0 but got 447 > PASS <select></select> has a shadow tree with slot > PASS <select multiple=""></select> has a shadow tree with slot > PASS <select size="4"></select> has a shadow tree with slot
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 319178
:
480520
|
480523
|
480524
|
480532
|
480542
|
480554
|
480566
|
480567
|
480579
|
480585
|
480590