Skip to content

layout: Pass degrees to the WebRender hue rotate filter#41063

Merged
yezhizhen merged 3 commits intoservo:mainfrom
AnonMiraj:fix_huerotate
Dec 7, 2025
Merged

layout: Pass degrees to the WebRender hue rotate filter#41063
yezhizhen merged 3 commits intoservo:mainfrom
AnonMiraj:fix_huerotate

Conversation

@AnonMiraj
Copy link
Copy Markdown
Contributor

@AnonMiraj AnonMiraj commented Dec 5, 2025

Fixes the hue-rotate() CSS filter. The problem was that Servo used angle.radians instead of angle.degrees, so the hue rotation was applied incorrectly. Switching to degrees makes the filter render as expected.

image

Testing: the demo html file now works as expected. Added a new test.
Fixes: #40955

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Dec 5, 2025
Copy link
Copy Markdown
Member

@yezhizhen yezhizhen left a comment

Choose a reason for hiding this comment

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

Thanks! Let's see if there are tests covering this. (This reminds me of primary school math time :D)

@yezhizhen yezhizhen added the T-linux-wpt Do a try run of the WPT label Dec 5, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Dec 5, 2025
@github-actions
Copy link
Copy Markdown

github-actions bot commented Dec 5, 2025

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

@github-actions
Copy link
Copy Markdown

github-actions bot commented Dec 5, 2025

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

Flaky unexpected result (30)
  • OK /IndexedDB/idbfactory_open.any.html
    • FAIL [expected PASS] subtest: Calling open() with version argument 1.5 should not throw.

      assert_equals: version expected 1 but got 9007199254740991
      

  • 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/webxr/create_session.https.html
    • FAIL [expected PASS] subtest: create_session

      can't access property "simulateDeviceConnection", navigator.xr.test is undefined
      

  • OK /_mozilla/webxr/obtain_frame.https.html
    • FAIL [expected PASS] subtest: obtain_frame

      promise_test: Unhandled rejection with value: object "TypeError: can't access property "simulateDeviceConnection", navigator.xr.test is undefined"
      

  • ERROR [expected TIMEOUT] /_mozilla/webxr/sessionavailable.https.html
  • FAIL [expected PASS] /css/css-backgrounds/background-size-042.html
  • OK /css/css-fonts/generic-family-keywords-002.html (#40929)
    • PASS [expected FAIL] subtest: font-family: -webkit-serif treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-sans-serif treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-cursive treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-fantasy treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-monospace treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-system-ui treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-math treated as <font-family>, not <generic-name>
    • FAIL [expected PASS] subtest: font-family: -webkit-generic(fangsong) treated as <font-family>, not <generic-name>

      assert_equals: expected 50 but got 30
      

    • FAIL [expected PASS] subtest: font-family: -webkit-generic(kai) treated as <font-family>, not <generic-name>

      assert_equals: expected 50 but got 30
      

    • FAIL [expected PASS] subtest: font-family: -webkit-generic(khmer-mul) treated as <font-family>, not <generic-name>

      assert_equals: expected 50 but got 30
      

    • And 12 more unexpected results...
  • OK /custom-elements/form-associated/ElementInternals-setFormValue.html (#29174)
    • PASS [expected FAIL] subtest: Single value - empty name exists
    • PASS [expected FAIL] subtest: Single value - Non-empty name exists
  • 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/history/the-history-interface/traverse_the_history_4.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • 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])
      

  • CRASH [expected OK] /html/canvas/element/drawing-images-to-the-canvas/2d.drawImage.negativedir.html
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/update-the-rendering.html (#24145)
    • TIMEOUT [expected FAIL] subtest: "Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks

      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)
    • PASS [expected FAIL] subtest: Meta refresh is blocked by the allow-scripts sandbox flag at its creation time, not when refresh comes due
  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • FAIL [expected PASS] subtest: multipart/form-data: Basic test (formdata event)

      assert_equals: expected "\r\nContent-Disposition: form-data; name=\"basic\"\r\n\r\ntest\r\n--\r\n" but got ""
      

  • OK /html/semantics/forms/form-submission-0/text-plain.window.html (#28687)
    • FAIL [expected PASS] subtest: text/plain: Basic File test (normal form)

      assert_equals: expected "basic=file-test.txt\r\n" but got ""
      

    • PASS [expected FAIL] subtest: text/plain: 0x00 in filename (formdata event)
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • FAIL [expected PASS] subtest: application/x-www-form-urlencoded: Basic File test (normal form)

      assert_equals: expected "basic=file-test.txt" but got ""
      

    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: 0x00 in name (normal form)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: 0x00 in value (formdata event)
  • TIMEOUT [expected ERROR] /html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html (#40347)
  • OK [expected ERROR] /html/user-activation/no-activation-thru-escape-key.html (#40343)
  • 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 /preload/preload-invalid-resources.html (#39091)
    • PASS [expected FAIL] subtest: Preloading an invalid image (invalid data) should preload and not re-fetch
  • CRASH [expected OK] /trusted-types/Node-multiple-arguments.html
  • CRASH [expected OK] /trusted-types/eval-csp-no-tt.html
  • TIMEOUT /trusted-types/trusted-types-navigation.html?06-10 (#37920)
    • PASS [expected FAIL] subtest: Navigate a frame via anchor with javascript:-urls in report-only mode.
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?26-30 (#38807)
    • PASS [expected TIMEOUT] subtest: Navigate a window via form-submission with javascript:-urls in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ default policy in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a frame via form-submission with javascript:-urls in enforcing mode.
    • PASS [expected NOTRUN] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in enforcing mode.
  • CRASH [expected OK] /trusted-types/trusted-types-reporting-for-Document-execCommand.html
  • CRASH [expected OK] /webaudio/the-audio-api/the-convolvernode-interface/realtime-conv.html
  • OK [expected ERROR] /webxr/render_state_update.https.html (#27535)
  • 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 (20)
  • OK /IndexedDB/idbobjectstore_getAll.any.html (#39276)
    • PASS [expected FAIL] subtest: Get all values with transaction.commit()
  • OK /IndexedDB/idbobjectstore_getAll.any.worker.html (#39400)
    • PASS [expected FAIL] subtest: Get all values with transaction.commit()
  • 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 /_webgl/conformance/textures/misc/texture-upload-size.html (#21770)
    • PASS [expected FAIL] subtest: WebGL test #45
    • PASS [expected FAIL] subtest: WebGL test #47
    • PASS [expected FAIL] subtest: WebGL test #49
    • PASS [expected FAIL] subtest: WebGL test #51
    • FAIL [expected PASS] subtest: WebGL test #53

      assert_true: Texture was smaller than the expected size 2x2 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #55

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : when calling texSubImage2D with the same texture upload with offset 1, 1 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #57

      assert_true: Texture was smaller than the expected size 2x2 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #59

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : when calling texSubImage2D with the same texture upload with offset 1, 1 expected true got false
      

    • PASS [expected FAIL] subtest: WebGL test #61
    • PASS [expected FAIL] subtest: WebGL test #63
    • And 6 more unexpected results...
  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • FAIL [expected PASS] subtest: @font-face override update with appended sheet 1

      assert_equals: expected "80px" but got "38.3166666666667px"
      

    • FAIL [expected PASS] subtest: @font-face override update with appended sheet 2

      assert_equals: expected "80px" but got "38.3166666666667px"
      

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

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

    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(khmer-mul)

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

  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-mode
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Cross-site

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-site destination

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • OK /fetch/metadata/generated/element-img-environment-change.https.sub.html (#30111)
    • FAIL [expected PASS] subtest: sec-fetch-site - Cross-site, no attributes

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

    • FAIL [expected PASS] subtest: sec-fetch-site - Cross-Site -> Same-Site, no attributes

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

    • PASS [expected FAIL] subtest: sec-fetch-site - Cross-Site -> Cross-Site, no attributes
    • FAIL [expected PASS] subtest: sec-fetch-site - Same-Origin -> Same Origin, no attributes

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

    • PASS [expected FAIL] subtest: sec-fetch-site - Same-Origin -> Same-Site, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-site - Same-Site -> Cross-Site, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-mode - attributes: crossorigin
    • FAIL [expected PASS] subtest: sec-fetch-mode - attributes: crossorigin=anonymous

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

    • PASS [expected FAIL] subtest: sec-fetch-mode - attributes: crossorigin=use-credentials
    • PASS [expected FAIL] subtest: sec-fetch-user - no attributes
    • And 1 more unexpected results...
  • OK /fetch/metadata/generated/element-img-environment-change.sub.html (#30111)
    • PASS [expected FAIL] subtest: sec-fetch-site - Not sent to non-trustworthy same-origin destination, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-site - Not sent to non-trustworthy same-site destination, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-mode - Not sent to non-trustworthy cross-site destination, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-dest - Not sent to non-trustworthy cross-site destination, no attributes
  • ERROR /fetch/metadata/generated/serviceworker.https.sub.html (#36247)
    • FAIL [expected PASS] subtest: sec-fetch-site - Same origin, no options - registration

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • 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/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • PASS [expected FAIL] subtest: aElement.click() before the load event must NOT replace
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • TIMEOUT [expected NOTRUN] subtest: Non-HTMLElement should not support autofocus

      Test timed out
      

    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus should support autofocus
    • NOTRUN [expected FAIL] subtest: Host element with delegatesFocus including no focusable descendants should be skipped
    • NOTRUN [expected FAIL] subtest: Area element should support autofocus
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • FAIL [expected PASS] subtest: Reload domContentLoadedEventEnd > Original domContentLoadedEventEnd

      assert_true: Reload domContentLoadedEventEnd > Original domContentLoadedEventEnd expected true got false
      

  • OK /preload/preload-error.sub.html (#37177)
    • PASS [expected FAIL] subtest: 404 (fetch): main
    • FAIL [expected PASS] subtest: CORS (fetch): main

      assert_greater_than: http://not-web-platform.test:8000/preload/resources/dummy.xml?pipe=header%28Access-Control-Allow-Origin%2C*%29&label=fetch should be loaded expected a number greater than 0 but got 0
      

  • OK /resource-timing/buffer-full-add-then-clear.html (#40819)
    • PASS [expected FAIL] subtest: Test that if the buffer is cleared after entries were added to the secondary buffer, those entries make it into the primary one
  • 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!\""
      

  • TIMEOUT [expected OK] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • TIMEOUT [expected PASS] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe

      Test timed out
      

Stable unexpected results (1)
  • FAIL [expected PASS] /css/filter-effects/svg-image-root-filter.html

@github-actions
Copy link
Copy Markdown

github-actions bot commented Dec 5, 2025

⚠️ Try run (#19952101166) failed.

@yezhizhen
Copy link
Copy Markdown
Member

yezhizhen commented Dec 5, 2025

Can you investigate a bit about why /css/filter-effects/svg-image-root-filter.html fails? @AnonMiraj

@Loirooriol
Copy link
Copy Markdown
Contributor

It fails because of the way that SVG is treated, same as

<!DOCTYPE html>
<style>body > * { border: solid }</style>
<img src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' style='background: cyan'></svg>">
<svg style='background: cyan'></svg>

So just mark it as failing.

But this needs a new automated test. See https://web-platform-tests.org/writing-tests/reftests.html

You can e.g. start with a red square, hue-rotate to green, then compare with /css/reference/ref-filled-green-200px-square.html or similar.

@yezhizhen yezhizhen added the S-needs-tests New tests have been requested by a reviewer. label Dec 5, 2025
@mrobinson mrobinson changed the title fix small typo in hue rotate layout: Pass degrees to the WebRender hue rotate filter Dec 5, 2025
@mrobinson
Copy link
Copy Markdown
Member

Updated the title, because this isn't just a "typo!" Thanks for catching this.

@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

🤖 Opened new upstream WPT pull request (web-platform-tests/wpt#56546) with upstreamable changes.

Signed-off-by: anonmiraj <[email protected]>
@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#56546).

@servo-wpt-sync
Copy link
Copy Markdown
Collaborator

✍ Updated existing upstream WPT pull request (web-platform-tests/wpt#56546) title and body.

Copy link
Copy Markdown
Member

@yezhizhen yezhizhen left a comment

Choose a reason for hiding this comment

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

Thanks. I updated the body.

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Dec 7, 2025
@yezhizhen yezhizhen added this pull request to the merge queue Dec 7, 2025
@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 Dec 7, 2025
Merged via the queue into servo:main with commit ce2a51a Dec 7, 2025
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 Dec 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-needs-tests New tests have been requested by a reviewer.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for hue-rotate css filter

6 participants