Skip to content

layout: Resolve word-spacing percentages against computed font-size#44031

Merged
mrobinson merged 10 commits into
servo:mainfrom
sabbCodes:issue-43997
Apr 10, 2026
Merged

layout: Resolve word-spacing percentages against computed font-size#44031
mrobinson merged 10 commits into
servo:mainfrom
sabbCodes:issue-43997

Conversation

@sabbCodes
Copy link
Copy Markdown
Contributor

@sabbCodes sabbCodes commented Apr 8, 2026

Changes word-spacing to resolve percentages against the computed font-size, instead of the size of a space.

Testing: tests/wpt/tests/css/css-text/word-spacing/word-spacing-percent-001.html is now passing

Fixes: #43997

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Apr 8, 2026
@mrobinson
Copy link
Copy Markdown
Member

@sabbCodes The testing field refers to automated testing and is not meant as place to show screenshots of behavior changes. Are you able to write an automated test that shows this fix?

@mrobinson mrobinson added the T-linux-wpt Do a try run of the WPT label Apr 8, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Apr 8, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 8, 2026

🔨 Triggering try run (#24142085495) for Linux (WPT)

@mrobinson
Copy link
Copy Markdown
Member

We should also link to the specification discussion for this issue and give some background about why we are making these changes in the PR description.

@Loirooriol
Copy link
Copy Markdown
Contributor

Should be covered by /css/css-text/word-spacing/word-spacing-percent-001.html

Comment on lines +411 to +413
inherited_text_style
.word_spacing
.to_used_value(Au::from_f64_px(space_width))
.to_used_value(parent_style.clone_font().font_size.computed_size().into())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't depend on segment. You can resolve above in the word_spacing variable before the loop.

@sabbCodes
Copy link
Copy Markdown
Contributor Author

@sabbCodes The testing field refers to automated testing and is not meant as place to show screenshots of behavior changes. Are you able to write an automated test that shows this fix?

Yes, I found one here ./mach test-wpt tests/wpt/tests/css/css-text/word-spacing/word-spacing-percent-001.html but it's marked expected: FAIL

This was the result;

web-platform-test
~~~~~~~~~~~~~~~~~
Ran 1 checks (1 tests)
Expected results: 0
Unexpected results: 1
  test: 1 (1 pass)

I wasn't sure what to do, so I followed only the testcase described in #43997

@Loirooriol
Copy link
Copy Markdown
Contributor

Yes, it's expected to fail because currently it fails. After your fix, the expectation should be to pass.

See https://book.servo.org/contributing/testing.html#updating-web-platform-test-expectations

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 8, 2026

Test results for linux-wpt from try job (#24142085495):

Flaky unexpected result (37)
  • TIMEOUT /FileAPI/url/url-in-tags-revoke.window.html (#19978)
    • PASS [expected TIMEOUT] subtest: Fetching a blob URL immediately before revoking it works in <script> tags.
  • OK /IndexedDB/idbdatabase_deleteObjectStore.any.html (#43823)
    • PASS [expected FAIL] subtest: Deleted object store's name should be removed from database's list. Attempting to use a deleted IDBObjectStore should throw an InvalidStateError
  • OK /_mozilla/css/offset_properties_inline.html (#40543)
    • FAIL [expected PASS] subtest: offsetTop

      assert_equals: offsetTop of #inline-1 should be 0. expected 0 but got -1
      

    • FAIL [expected PASS] subtest: offsetLeft

      assert_equals: offsetLeft of #inline-2 should be 40. expected 40 but got 25
      

  • OK /_mozilla/mozilla/getBoundingClientRect.html (#39668)
    • FAIL [expected PASS] subtest: getBoundingClientRect 1

      assert_equals: expected 62 but got 60.35
      

  • CRASH [expected OK] /_webgl/conformance2/glsl3/const-array-init.html
  • CRASH [expected OK] /_webgl/conformance2/wasm/readpixels-2gb-in-4gb-wasm-memory.html
  • CRASH [expected OK] /content-security-policy/meta/sandbox-iframe.html (#43478)
  • FAIL [expected PASS] /css/css-backgrounds/background-size-041.html
  • FAIL [expected PASS] /css/css-ui/webkit-appearance-menulist-001.html
  • CRASH [expected OK] /fetch/api/credentials/cookies.any.worker.html
  • CRASH [expected OK] /fetch/api/request/request-init-stream.any.worker.html
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-site destination
  • TIMEOUT /fetch/metadata/generated/css-images.sub.tentative.html (#29047)
    • TIMEOUT [expected PASS] subtest: background-image sec-fetch-site - Not sent to non-trustworthy cross-site destination

      Test timed out
      

  • OK /fetch/metadata/window-open.https.sub.html (#40339)
    • FAIL [expected PASS] subtest: Same-site window, forced, reloaded

      The operation is insecure.
      

  • ERROR [expected OK] /focus/focus-event-after-switching-iframes.sub.html (#40368)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/005.html (#27062)
    • PASS [expected FAIL] subtest: Link with onclick navigation and href navigation
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.html (#29056)
    • PASS [expected FAIL] subtest: Cross-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin-fragment.html (#20768)
    • PASS [expected FAIL] subtest: Tests that a fragment navigation in the unload handler will not block the initial navigation
  • OK /html/browsers/history/the-history-interface/traverse_the_history_4.html (#21383)
    • FAIL [expected PASS] subtest: Multiple history traversals, last would be aborted

      assert_array_equals: Pages opened during history navigation expected property 1 to be 5 but got 3 (expected array [6, 5] got [6, 3])
      

  • OK /html/browsers/history/the-history-interface/traverse_the_history_5.html (#21383)
    • FAIL [expected PASS] subtest: Multiple history traversals, last would be aborted

      assert_array_equals: Pages opened during history navigation expected property 1 to be 5 but got 3 (expected array [6, 5] got [6, 3])
      

  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-nonexistent.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with non-existent fragments should work.

      Test timed out
      

  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/update-the-rendering.html (#24145)
    • FAIL [expected TIMEOUT] subtest: "Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks

      assert_array_equals: animationFrame lengths differ, expected array ["autofocus", "scroll", "animationFrame"] length 3, got ["animationFrame"] length 1
      

  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigate_other_frame_popup.sub.html (#39702)
    • TIMEOUT [expected FAIL] subtest: Sandboxed iframe can not navigate other frame's popup

      Test timed out
      

  • OK /html/semantics/scripting-1/the-script-element/execution-timing/077.html (#22139)
    • FAIL [expected PASS] subtest: adding several types of scripts through the DOM and removing some of them confuses scheduler

      assert_array_equals: expected property 1 to be "Script #1 ran" but got "Script #3 ran" (expected array ["Script #2 ran", "Script #1 ran", "Script #3 ran", "Script #4 ran"] got ["Script #2 ran", "Script #3 ran", "Script #4 ran", "Script #1 ran"])
      

  • OK /html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.html (#33948)
    • FAIL [expected PASS] subtest: Revoking a blob URL immediately after calling import will not fail

      promise_test: Unhandled rejection with value: object "TypeError: Module fetching failed"
      

  • OK /html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.worker-module.html (#43510)
    • FAIL [expected PASS] subtest: Revoking a blob URL immediately after calling import will not fail

      promise_test: Unhandled rejection with value: object "TypeError: Module fetching failed"
      

  • OK /html/syntax/speculative-parsing/expect-no-linked-resources/no-speculative-fetch.tentative.optional.html
    • FAIL [expected PASS] subtest: expect-no-linked-resources hint was ignored

      assert_equals: speculative case fetched expected "" but got "fd0c535b-6956-4aa5-b935-3bfbb4457576"
      

  • OK /infrastructure/testdriver/click_iframe.html
    • FAIL [expected PASS] subtest: TestDriver click on a document in an iframe

      Unhandled rejection: assert_unreached: click failed Reached unreachable code
      

  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete > Original domComplete
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventEnd > Original domContentLoadedEventEnd
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart > Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload fetchStart > Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd > Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart > Original loadEventStart
  • TIMEOUT [expected OK] /pointerevents/compat/pointerevent_touch-action_two-finger_interaction.html
    • NOTRUN [expected PASS] subtest: touch two-finger pan on 'touch-action: pan-x pan-y'
    • NOTRUN [expected FAIL] subtest: touch two-finger pan on 'touch-action: pinch-zoom'
  • OK /resource-timing/buffer-full-add-then-clear.html (#40819)
    • FAIL [expected PASS] subtest: Test that if the buffer is cleared after entries were added to the secondary buffer, those entries make it into the primary one

      assert_equals: Number of entries does not match the expected value. expected 3 but got 0
      

  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
    • PASS [expected TIMEOUT] subtest: Navigate a frame via anchor with javascript:-urls w/ default policy in report-only mode.
    • FAIL [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ a default policy throwing an exception in enforcing mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

    • FAIL [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ a default policy throwing an exception in report-only mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

  • TIMEOUT [expected OK] /trusted-types/trusted-types-navigation.html?26-30 (#38807)
    • TIMEOUT [expected PASS] subtest: Navigate a window via form-submission with javascript:-urls in report-only mode.

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Navigate a window via form-submission with javascript:-urls w/ default policy in report-only mode.
    • NOTRUN [expected PASS] subtest: Navigate a frame via form-submission with javascript:-urls in enforcing mode.
    • NOTRUN [expected PASS] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in enforcing mode.
  • OK /visual-viewport/resize-event-order.html (#41981)
    • PASS [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.
  • OK /webdriver/tests/classic/execute_async_script/properties.py
    • FAIL [expected PASS] subtest: test_content_attribute

      AssertionError: no such window (404): No such window
      

  • OK [expected TIMEOUT] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • PASS [expected TIMEOUT] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe
  • OK /webxr/xrSession_features_deviceSupport.https.html (#24357)
    • FAIL [expected PASS] subtest: Immersive XRSession requests with no supported device should reject

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

Stable unexpected results that are known to be intermittent (18)
  • FAIL [expected PASS] /_mozilla/mozilla/sslfail.html (#10760)
  • TIMEOUT [expected OK] /_mozilla/mozilla/window_resize_event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • OK /beacon/beacon-basic.https.window.html (#41723)
    • PASS [expected FAIL] subtest: Payload size restriction should be accumulated: type = arraybuffer
    • FAIL [expected PASS] subtest: Payload size restriction should be accumulated: type = blob

      assert_false: expected false got true
      

  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(nastaliq)

      assert_equals: quoted generic(nastaliq) matches  @font-face rule expected 50 but got 30
      

  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted sans-serif (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted cursive (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted monospace (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted math (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(kai) (drawing text in a canvas)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(khmer-mul) (drawing text in a canvas)

      assert_equals: quoted generic(khmer-mul) matches  @font-face rule expected 40 but got 125
      

    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-rounded (drawing text in a canvas)
  • OK /dom/nodes/moveBefore/iframe-document-preserve.window.html (#43152)
    • FAIL [expected PASS] subtest: moveBefore(): cross-origin iframe is preserved: remove self

      assert_equals: iframe does not fire a second load event expected 1 but got 0
      

  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/accumulated-oversized-payload.https.window.html (#41705)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-mode
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • FAIL [expected PASS] subtest: aElement.click() before the load event must NOT replace

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?thereplacement" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20a%20%3D%20document.createElement(%22a%22)%3B%0A%20%20%20%20a.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%0A%20%20%20%20document.currentScript.before(a)%3B%0A%20%20%20%20a.click()%3B%0A%20%20"
      

  • ERROR [expected OK] /html/canvas/offscreen/text/2d.text.measure.getActualBoundingBox.tentative.html (#43710)
  • TIMEOUT /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus should support autofocus

      assert_equals: expected Element node <div autofocus=""></div> but got Element node <body><div autofocus=""></div></body>
      

    • TIMEOUT [expected NOTRUN] subtest: Host element with delegatesFocus including no focusable descendants should be skipped

      Test timed out
      

  • OK /html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html (#39694)
    • FAIL [expected PASS] subtest: Meta refresh is blocked by the allow-scripts sandbox flag at its creation time, not when refresh comes due

      uncaught exception: Error: assert_unreached: The iframe from which the meta came from must not refresh Reached unreachable code
      

  • OK /html/webappapis/user-prompts/print-during-unload.html (#35944)
    • FAIL [expected PASS] subtest: print() during unload

      assert_array_equals: expected property 1 to be "destination" but got "error: window.print is not a function" (expected array ["start", "destination"] got ["start", "error: window.print is not a function"])
      

  • OK /mixed-content/tentative/autoupgrades/mixed-content-cors.https.sub.html (#41123)
    • PASS [expected FAIL] subtest: Cross-Origin video should get upgraded even if CORS is set
  • OK [expected CRASH] /resource-timing/render-blocking-status-link.html (#41664)
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?01-05 (#38975)
    • PASS [expected TIMEOUT] subtest: Navigate a window via anchor with javascript:-urls in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ default policy in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a frame via anchor with javascript:-urls in enforcing mode.
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • PASS [expected TIMEOUT] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in report-only mode.
    • FAIL [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy throwing an exception in enforcing mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

    • FAIL [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy throwing an exception in report-only mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

    • FAIL [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy making the URL invalid in enforcing mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

  • OK /trusted-types/trusted-types-reporting.html (#43737)
    • PASS [expected FAIL] subtest: Trusted Type violation report: sample for SVGScriptElement href assignment by setAttribute
Stable unexpected results (1)
  • PASS [expected FAIL] /css/css-text/word-spacing/word-spacing-percent-001.html

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 8, 2026

⚠️ Try run (#24142085495) failed!

@sabbCodes
Copy link
Copy Markdown
Contributor Author

Hi @Loirooriol

Here's the new result to ./mach test-wpt tests/wpt/tests/css/css-text/word-spacing/word-spacing-percent-001.html

web-platform-test
~~~~~~~~~~~~~~~~~
Ran 1 checks (1 tests)
Expected results: 1
Unexpected results: 0
OK

let word_spacing = inherited_text_style.word_spacing.to_length().map(Au::from);
let word_spacing = inherited_text_style
.word_spacing
.to_length()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just use to_used_value() directly

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks :)

.unwrap_or_else(|| {
inherited_text_style
.word_spacing
.to_used_value(parent_style.clone_font().font_size.computed_size().into())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can share parent_style.clone_font().font_size.computed_size() with letter_spacing.

And in fact, better parent_style.get_font().font_size.computed_size() to avoid cloning the entire font.

flags.insert(ShapingFlags::DISABLE_KERNING_SHAPING_FLAG)
}
let word_spacing = inherited_text_style.word_spacing.to_length().map(Au::from);
let word_spacing = inherited_text_style
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you are at it, I would move let word_spacing to be next to let letter_spacing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want me to move them together?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like so;

let letter_spacing = inherited_text_style.letter_spacing.0.resolve(font_size);
        let word_spacing = inherited_text_style
            .word_spacing
            .to_used_value(font_size.into());

?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, after the logic to turn a zero letter_spacing into None, I guess. Or put word_spacing first.

Also, do you need the .into()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, compiler complains in its absence

.to_used_value(font_size);
    |              ------------- ^^^^^^^^^ expected `Au`, found `CSSPixelLength`
    |              |
    |              arguments to this method are incorrect
    |
note: method defined here
   --> /home/sabb/.cargo/git/checkouts/stylo-482338307e42a9ea/ddf2109/style/values/computed/length_percentage.rs:531:12
    |
531 |     pub fn to_used_value(&self, containing_length: Au) -> Au {
    |            ^^^^^^^^^^^^^
help: call `Into::into` on this expression to convert `CSSPixelLength` into `Au`
    |
380 |             .to_used_value(font_size.into());
    |                                     +++++++

``

Copy link
Copy Markdown
Member

@mrobinson mrobinson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let's wait to land this until #43974 lands.

@servo-highfive servo-highfive added S-needs-code-changes Changes have not yet been made that were requested by a reviewer. and removed S-awaiting-review There is new code that needs to be reviewed. labels Apr 8, 2026
@Loirooriol Loirooriol changed the title Make word-spacing use font-size layout: Resolve word-spacing percentages against computed font-size Apr 8, 2026
@sabbCodes
Copy link
Copy Markdown
Contributor Author

Please let's wait to land this until #43974 lands.

Right

.to_used_value(font_size.into());
let letter_spacing = inherited_text_style.letter_spacing.0.resolve(font_size);
let letter_spacing = if letter_spacing.px() != 0. {
Some(app_units::Au::from(letter_spacing))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: it may look more consistent like

        let font_size = parent_style.get_font().font_size.computed_size().into();
        let word_spacing = inherited_text_style.word_spacing.to_used_value(font_size);
        let letter_spacing = inherited_text_style.letter_spacing.0.to_used_value(font_size);
        let letter_spacing = if !letter_spacing.is_zero() {
            Some(letter_spacing)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It''l fail the ./mach test-tidy test if we do it like that, the ./mach fmt command wants it as is

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant using to_used_value() for both. But run ./mach fmt, sure

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, lemme try it.

Hope it builds successfully

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, using to_used_value() for letter_spacing introduces the following error;

[{
	"resource": "/home/sabb/servo/components/layout/flow/inline/text_run.rs",
	"owner": "rust-analyzer",
	"code": {
		"value": "E0308",
		"target": {
			"$mid": 1,
			"path": "/stable/error_codes/E0308.html",
			"scheme": "https",
			"authority": "doc.rust-lang.org"
		}
	},
	"severity": 8,
	"message": "expected Au, found CSSPixelLength",
	"source": "rust-analyzer",
	"startLineNumber": 381,
	"startColumn": 82,
	"endLineNumber": 381,
	"endColumn": 91,
	"origin": "extHost1"
}]
[{
	"resource": "/home/sabb/servo/components/layout/flow/inline/text_run.rs",
	"owner": "rustc",
	"code": {
		"value": "Click for full compiler diagnostic",
		"target": {
			"$mid": 1,
			"path": "/diagnostic message [3]",
			"scheme": "rust-analyzer-diagnostics-view",
			"query": "3",
			"fragment": "file:///home/sabb/servo/components/layout/flow/inline/text_run.rs"
		}
	},
	"severity": 8,
	"message": "no method named `px` found for struct `app_units::Au` in the current scope\nmethod not found in `app_units::Au`",
	"source": "rustc",
	"startLineNumber": 382,
	"startColumn": 48,
	"endLineNumber": 382,
	"endColumn": 50,
	"origin": "extHost1"
}]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use into() so that font_size is an Au

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did, there's a different error, I think that one was about the .into() not existing on Au

Lemme check again

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this is weird, lol

I think it wass my machine that was still rendering the previous error after I added the .into() yesterday, cause now it's stopped complaining.

But there's still this;

[{
	"resource": "/home/sabb/servo/components/layout/flow/inline/text_run.rs",
	"owner": "rustc",
	"code": {
		"value": "Click for full compiler diagnostic",
		"target": {
			"$mid": 1,
			"path": "/diagnostic message [0]",
			"scheme": "rust-analyzer-diagnostics-view",
			"query": "0",
			"fragment": "file:///home/sabb/servo/components/layout/flow/inline/text_run.rs"
		}
	},
	"severity": 8,
	"message": "no method named `px` found for struct `app_units::Au` in the current scope\nmethod not found in `app_units::Au`",
	"source": "rustc",
	"startLineNumber": 382,
	"startColumn": 48,
	"endLineNumber": 382,
	"endColumn": 50,
	"origin": "extHost1"
}]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check my code. Drop px()

@servo-highfive servo-highfive added S-awaiting-review There is new code that needs to be reviewed. S-needs-rebase There are merge conflict errors. and removed S-needs-code-changes Changes have not yet been made that were requested by a reviewer. labels Apr 8, 2026
@Loirooriol
Copy link
Copy Markdown
Contributor

You will also need to rebase after #43974

Signed-off-by: Sabb <sarafaabbas@gmail.com>
Signed-off-by: Sabb <sarafaabbas@gmail.com>
Signed-off-by: Sabb <sarafaabbas@gmail.com>
Signed-off-by: Sabb <sarafaabbas@gmail.com>
Signed-off-by: Sabb <sarafaabbas@gmail.com>
Signed-off-by: Sabb <sarafaabbas@gmail.com>
Signed-off-by: Sabb <sarafaabbas@gmail.com>
Signed-off-by: Sabb <sarafaabbas@gmail.com>
@servo-highfive servo-highfive removed the S-needs-rebase There are merge conflict errors. label Apr 9, 2026
.to_used_value(Au::from_f64_px(space_width))
})
};
let resolve_word_spacing_for_font = |_font: &FontRef| word_spacing;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can drop this lambda

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean the underscore? I added it cause compiler was complaining;

servo-layout v0.1.0 (/home/sabb/servo/components/layout)
warning: unused variable: `font`
   --> components/layout/flow/inline/text_run.rs:476:46
    |
476 | ...rd_spacing_for_font = |font: &FontRef| word_spacing;
    |                           ^^^^ help: if this is intentional, prefix it with an underscore: `_font`
    |
    = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I mean remove resolve_word_spacing_for_font.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do i drop them here too?

components/layout/flow/inline/text_run.rs:517:37
    |
517 | ...ome(resolve_word_spacing_for_font(&font));
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `resolve_word_spacing_for_font` in this scope
   --> components/layout/flow/inline/text_run.rs:549:41
    |
549 | ...ome(resolve_word_spacing_for_font(&font));
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope


Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Loirooriol Do you still want me to drop it?

Cause FontAndScriptInfo requires the word_spacing field, perhaps you have something else to replace this let word_spacing = Some(resolve_word_spacing_for_font(&font)); with?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, drop it everywhere, and drop the 2nd let word_spacing. Just use the original word_spacing variable, but wrap it in Some().

Signed-off-by: Sabb <sarafaabbas@gmail.com>
let parent_style = self.inline_styles.style.borrow().clone();
let inherited_text_style = parent_style.get_inherited_text().clone();
let font_size = parent_style.get_font().font_size.computed_size().into();
let word_spacing = inherited_text_style.word_spacing.to_used_value(font_size);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add Some() here, and drop the variables below.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Any other changes needed?

Signed-off-by: Sabb <sarafaabbas@gmail.com>
@Loirooriol Loirooriol requested a review from mrobinson April 10, 2026 13:41
@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Apr 10, 2026
@mrobinson mrobinson added this pull request to the merge queue Apr 10, 2026
@servo-highfive servo-highfive added the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Apr 10, 2026
Merged via the queue into servo:main with commit fbb37ac Apr 10, 2026
30 checks passed
@servo-highfive servo-highfive removed the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

word-spacing percentages should resolve against font-size

4 participants