react-native-skia icon indicating copy to clipboard operation
react-native-skia copied to clipboard

[Web] Error: Couldn't create typeface for

Open tlow92 opened this issue 1 year ago • 7 comments

Hi,

I am currently upgrading from expo 51 to 52 and noticed that after the upgrade no fonts are rendered in my skia canvas due to an error:

Font.js:67 Uncaught (in promise) Error: Couldn't create typeface for Inter-Regular
    at Font.js:67:17
    at async Promise.all (index 0)

I am adding inter fonts like this in all skia components and it used to work just fine

const fonts = useFonts({
  'Inter-Regular': [require('@tamagui/font-inter/otf/Inter-Regular.otf')],
});

After then I'm using them in the styles for paragraph

 Skia.ParagraphBuilder.Make({}, fonts).pushStyle({
  fontFamilies: ['Inter-Regular'],
}).addText(text).build()

It works fine in iOS (even after upgrade to expo 52) but not in Web anymore.

Tested with react-native-skia 1.5.0 and 1.6.0

tlow92 avatar Dec 03 '24 10:12 tlow92

can you share a reproduction?

wcandillon avatar Dec 03 '24 12:12 wcandillon

@wcandillon Sure, I added a skia paragraph using inter font to a fresh expo 52 create-expo-app. https://github.com/tlow92/react-native-skia-typeface-issue

Let me know if you need more

tlow92 avatar Dec 04 '24 08:12 tlow92

I found something, but I am not sure about the root cause and the consequences (I'm sure resolveAsset is used for a purpose), maybe you can help understanding this.

For some reason Platform.resolveAsset(typefaceToLoad) is undefined on web when removing the resolveAsset call and just passing typefaceToLoad typefaces are created and displayed correctly.

https://github.com/Shopify/react-native-skia/blob/42f81f05a66c6e083eb232ad9cc55b8e72405413/packages/skia/src/skia/core/Font.ts#L106

Patch used:

diff --git a/node_modules/@shopify/react-native-skia/lib/module/skia/core/Font.js b/node_modules/@shopify/react-native-skia/lib/module/skia/core/Font.js
index 25896be..58085c1 100644
--- a/node_modules/@shopify/react-native-skia/lib/module/skia/core/Font.js
+++ b/node_modules/@shopify/react-native-skia/lib/module/skia/core/Font.js
@@ -61,7 +61,7 @@ export const listFontFamilies = (fontMgr = Skia.FontMgr.System()) => new Array(f
 const loadTypefaces = typefacesToLoad => {
   const promises = Object.keys(typefacesToLoad).flatMap(familyName => {
     return typefacesToLoad[familyName].map(typefaceToLoad => {
-      return Skia.Data.fromURI(Platform.resolveAsset(typefaceToLoad)).then(data => {
+      return Skia.Data.fromURI(typefaceToLoad).then(data => {
         const tf = Skia.Typeface.MakeFreeTypeFaceFromData(data);
         if (tf === null) {
           throw new Error(`Couldn't create typeface for ${familyName}`);

tlow92 avatar Dec 05 '24 13:12 tlow92

same for me (in expo web)

as a workaround for developing I am using Noto: [{ default: require("../assets/fonts/NotoColorEmoji.ttf") }], instead of Noto: [require("../assets/fonts/NotoColorEmoji.ttf")],

typescript is complaining and it is definitely not a right solution, but I can proceed with my explorations

megabuz avatar Dec 31 '24 00:12 megabuz

same for me (in expo web)

as a workaround for developing I am using Noto: [{ default: require("../assets/fonts/NotoColorEmoji.ttf") }], instead of Noto: [require("../assets/fonts/NotoColorEmoji.ttf")],

typescript is complaining and it is definitely not a right solution, but I can proceed with my explorations

I'm having the same issues as well on skia 1.11.7

your workaround works for me

daniel112 avatar Feb 19 '25 18:02 daniel112

same for me (in expo web)

as a workaround for developing I am using Noto: [{ default: require("../assets/fonts/NotoColorEmoji.ttf") }], instead of Noto: [require("../assets/fonts/NotoColorEmoji.ttf")],

typescript is complaining and it is definitely not a right solution, but I can proceed with my explorations

This works for me in web, but on iOS I'm getting

 ERROR  Warning: Error: Value is a number, expected a String

with this workaround.

tlow92 avatar Mar 11 '25 08:03 tlow92

This works to me

 const customFontMgr = useFonts({
    OrbitronBold: [
      Platform.OS === 'web'
        ? { default: require('./YourFont.ttf') }
        : require('./YourFont.ttf') ,
    ],
  });

daehyeonmun2021 avatar Apr 07 '25 04:04 daehyeonmun2021