Skip to content

fix: support Android font assets in Skia - #1473

Open
whydidoo wants to merge 3 commits into
callstack:mainfrom
whydidoo:fix/android-font-assets
Open

whydidoo wants to merge 3 commits into
callstack:mainfrom
whydidoo:fix/android-font-assets

Conversation

@whydidoo

@whydidoo whydidoo commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fixes #1472.

Skia loads bundled Android fonts from res/raw, while Re.Pack previously emitted them only to res/font.

  • Emit an additional res/raw copy for TTF, OTF, and TTC fonts, preserving existing R.font and XML font-family references.
  • Generate res/raw/keep.xml so resource shrinking preserves assets loaded by name from JavaScript.

Test plan

  • Tested real TTF, OTF, TTC fonts and images with Skia 2.11.2 on Android 13 and iOS 26.5 using Metro, Webpack, and Rspack 2.1.3.
  • Verified Android R.font and XML font-family references in release builds.
  • Verified resource shrinking with assets referenced only from JavaScript; removing keep.xml caused those resources to be removed.

@changeset-bot

changeset-bot Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 38fcef1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@callstack/repack Patch
@callstack/repack-plugin-expo-modules Patch
@callstack/repack-plugin-nativewind Patch
@callstack/repack-plugin-reanimated Patch
@callstack/repack-dev-server Patch
@callstack/repack-init Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Oct 1, 2026

Copy link
Copy Markdown

@whydidoo is attempting to deploy a commit to the Callstack Team on Vercel.

A member of the Team first needs to authorize it.

@whydidoo
whydidoo requested review from bartekkrok and dannyhw October 1, 2026 20:10
// Keep resources loaded by name from JavaScript.
const keepFile = Promise.all(tasks).then(async () => {
const keepPath = path.join(this.config.assetsDest, 'raw', 'keep.xml');
const content = `<resources xmlns:tools="http://schemas.android.com/tools" tools:keep="${resources.join(',')}" />\n`;

@dannyhw dannyhw Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The keep file works, but the way it's added doesn't quite match how AssetsCopyProcessor is built. Everything else in the class is a job that enqueueChunk pushes onto queue, and execute() just runs the queue. Here execute() takes on Android-specific logic, and the keep-file write waits on Promise.all(tasks) even though it doesn't need the copied files. On top of that, isRemote exists only so the remote processors can opt out.

How about making it a normal queued job behind its own method, called only for the local processor?

const androidResourceRegExp = /^(drawable|raw|font)(?:-[^/]+)?\/([^/]+)\.[^/.]+$/;

// Resources resolved by name at runtime are invisible to the resource shrinker
// (mirrors Metro's createKeepFileAsync).
enqueueAndroidKeepFile() {
  if (!this.androidResources.size) return;
  const keepPath = path.join(this.config.assetsDest, 'raw', 'keep.xml');
  const resources = [...this.androidResources].sort().join(',');
  this.queue.push(async () => {
    await this.filesystem.promises.mkdir(path.dirname(keepPath), { recursive: true });
    await this.filesystem.promises.writeFile(
      keepPath,
      `<resources xmlns:tools="http://schemas.android.com/tools" tools:keep="${resources}" />\n`
    );
  });
}
// OutputPlugin.ts, after the localChunks loop
localAssetsCopyProcessor?.enqueueAndroidKeepFile();

With that, execute() stays as it is on main and isRemote can be removed. Separately, OutputPlugin creates a new processor on every compilation, so the androidResources.clear() and the "earlier execution" test aren't needed.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, Danny! That’s a really good point. I’ve updated it as you suggested

@whydidoo
whydidoo requested a review from dannyhw October 2, 2026 08:26

This branch has not been deployed

No deployments
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.

Android release assets differ from Metro: fonts go to res/font/ and no raw/keep.xml is written

2 participants