Skip to content

Conversation

@Saadnajmi
Copy link
Collaborator

@Saadnajmi Saadnajmi commented Nov 26, 2025

Summary:

Needs #2783 to merge first.
Resolves #2738

There were a couple of issues with our macOS image rendering code that caused borders and shadows to not render properly in Fabric:

  1. Our shim for UIGraphicsImageRenderer on macOS (RCTUIGraphicsImageRenderer) called [NSImage imageWithActions:flipped:drawingHandler], which would not render the imade right away but instead when it's about to be displayed (presumably so that it can generate a proper CGContext for the screen the image is on). This meant that CGImage bitmap would sometimes just return as 0x0
  2. NSImage unlike UIImage does not have a CGImage property, so we used the method CGImageForProposedRect: to get one. Unfortunately, that returns an autoreleased CGImage, and when we later set that to RCTViewComponentViews' layer.contents, it would not be retained.

This manifested as borders and shadows not rendering, or rendering and then dissapearing on a resize.

To fix the first issue, apparently we can just call [image lockFocus] and [image unlockFocus] in succession to force it to render a bitmap.

To fix the second issue, we need some way to cache the CGImage. I propose a new class: RCTUIImage.

RCTUIImage, like RCTUIView is a subclass of NSImage with some extra properties and methods to make it more compatible with iOS code. In our case, we add the extra code to cache a CGImage, with proper retain and release calls. We can then have RCTUIGraphicsImageRenderer return our new subclass, and update all callers appropiately. The end result it we can actually remove some diffs, and have our macOS image handling behave closer to iOS.

While doing this work, I realized our NSImage / UIImage shims were kinda messy, and with the new subclass to introduce weird runtime edge cases. I split out #2783 to help clean up and clarify what image class we're using in the rest of the codebase.

Test Plan:

RNTester seems better :)

Screen.Recording.2025-11-26.at.3.39.04.PM.mov

@Saadnajmi Saadnajmi force-pushed the borders-shadows branch 2 times, most recently from cf2a071 to 3ffb7f9 Compare December 20, 2025 23:37
@Saadnajmi Saadnajmi force-pushed the borders-shadows branch 2 times, most recently from 3aea85d to 9981fbb Compare December 23, 2025 06:02
@Saadnajmi Saadnajmi changed the title fix(fabric): borders and shadows render consistently feat: Introduce RCTUIImage (2/2) Dec 23, 2025
@Saadnajmi Saadnajmi marked this pull request as ready for review December 23, 2025 06:20
@Saadnajmi Saadnajmi requested a review from a team as a code owner December 23, 2025 06:20
Saadnajmi added a commit that referenced this pull request Dec 23, 2025
## Summary:

This PR is split out from #2766 to help make it smaller.

Previously we had the code `@compatibility_alias UIImage NSImage` which
is basically an objective C runtime way of doing `#define UIImage
NSImage`. We don't quite like this, since we are defining the symbol
`UIImage` in an Appkit context. We have a better pattern we can copy
from RCTPlatformView --> RCTPlatformImage. The `RCTPlatform` prefix
basically means it's NS<blah> on Appkit and UI<blah> on UIKit. This is
as opposed to something like RCTUIView, where on iOS it's a typedef, but
on macOS it's a subclass that adds stuff to NSView to make it more
compatible with UIView.

All in all, this should mostly be a rigorous find/replace to make the
code slightly more strict, but have no behavioral changes

## Test Plan:

RNTester runs locally.
@Saadnajmi Saadnajmi force-pushed the borders-shadows branch 2 times, most recently from 1092a5f to 96efd22 Compare December 23, 2025 23:01
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.

[Fabric] TextInput is missing border rendering

1 participant