Skip to content

Android: an outset boxShadow whose negative spread empties its shape paints a bar outside the view #60008

Open

Description

@YevheniiKotyrlo

Description

On Android, an outset boxShadow whose negative spread is more than half the view's height or width paints a bar outside the view, where its shadow shape is empty and Chrome paints nothing. A 100×50 view with boxShadow: '0 40px 0 -30px black' paints a black 40×10 bar 10 dp below itself, with or without a borderRadius.

OutsetBoxShadowDrawable.draw (L96-L101) insets the view's bounds by the spread and offsets them, and draws the result with Canvas.drawRect (L163-L166) or Path.addRoundRect (L142-L160) without checking it is still a rect. Past half the box it is inverted, and Skia sorts an inverted rect in both calls, so each paints the overlap between its edges. Blink skips a shadow whose spread empties its rect.

#59081 and #59097, open, change this drawable and keep the shadow rect as it is.

Steps to reproduce

The reproducer renders three 100×50 boxes on a white screen: one with boxShadow: '0 40px 0 -30px black', one with the same shadow and borderRadius: 8, and a control with boxShadow: '0 40px 0 -20px black', whose shadow shape is 60×10.

  1. Clone the reproducer and, with one Android 9 or newer device attached, run ./reproduce.sh. It builds and installs the release APK, takes a screenshot and counts the dark pixels in the 30 dp below each box.
  2. Or by hand: cd ReproducerApp && yarn install && cd android && ./gradlew assembleRelease && adb install -r app/build/outputs/apk/release/app-release.apk, and open the app.

Expected: the first two boxes paint no shadow, since their spread empties its shape, and the control keeps painting its 60×10 shape 10 dp below itself.
Seen: each of the first two boxes paints a black 40×10 bar 10 dp below itself.

React Native Version

0.90.0-nightly-20261113-6d587e873

Affected Platforms

Runtime - Android

Output of npx @react-native-community/cli info

System:
  OS: Windows 11 10.0.26300
  CPU: "(32) x64 AMD Ryzen 9 9950X3D 16-Core Processor          "
  Memory: 160.50 GB / 255.67 GB
Binaries:
  Node:
    version: 26.12.1
    path: C:\Program Files\nodejs\node.EXE
  Yarn:
    version: 1.22.22
    path: C:\Users\<user>\AppData\Roaming\npm\yarn.CMD
  npm:
    version: 12.2.1
    path: C:\Program Files\nodejs\npm.CMD
  Watchman: Not Found
SDKs:
  Android SDK: Not Found
  Windows SDK:
    AllowDevelopmentWithoutDevLicense: Enabled
    Versions:
      - 10.0.19041.0
      - 10.0.26100.0
IDEs:
  Android Studio: AI-262.9437.185.2621.16467767
  Visual Studio: Not Found
Languages:
  Java:
    version: 17.0.20.1
    path: C:\Program Files\Microsoft\jdk-17.0.20.101-hotspot\bin\javac.EXE
  Ruby: Not Found
npmPackages:
  "@react-native-community/cli":
    installed: 21.0.0-alpha.1
    wanted: 21.0.0-alpha.1
  react:
    installed: 19.3.0
    wanted: 19.3.0
  react-native:
    installed: 0.90.0-nightly-20261113-6d587e873
    wanted: 0.90.0-nightly-20261113-6d587e873
  react-native-windows: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found

Stacktrace or Logs

No error is logged. ./reproduce.sh at the reproducer's 74e6e06, on a Galaxy S23:

device: SM-S911B, Android 14 (API 34), arm64-v8a, 1080x2340 at 480 dpi
react-native 0.90.0-nightly-20261113-6d587e873
== ./gradlew :app:assembleRelease -PreactNativeArchitectures=arm64-v8a
screenshot: screenshots/boxes.png
view whose spread empties its shadow shape: 300x150 px at (391, 266); 3600 dark pixels in the 300x90 px below it, where its shadow shape is empty: spanning 120x30 px (40x10 dp), 30 dp from its left edge and 10 dp below it
rounded view whose spread empties its shadow shape: 300x150 px at (390, 697); 3600 dark pixels in the 300x90 px below it, where its shadow shape is empty: spanning 120x30 px (40x10 dp), 30 dp from its left edge and 10 dp below it
view whose spread leaves a shadow shape: 300x150 px at (391, 1128); 5400 dark pixels in the 300x90 px below it, where its shadow paints a 60x10 dp shape: spanning 180x30 px (60x10 dp), 20 dp from its left edge and 10 dp below it
SUMMARY: the view whose spread empties its shadow shape and the rounded view whose spread empties its shadow shape each paint a bar below them, where the spread empties the shadow shape

MANDATORY Reproducer

https://github.com/YevheniiKotyrlo/rn-outset-shadow-negative-spread

Screenshots and Videos

The reproducer's screenshot on the Galaxy S23, cropped to the boxes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions