Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using custom font causes usePDF instance to indefinitely remain as 'loading' #2675

Open
NathZ1 opened this issue Mar 14, 2024 · 36 comments
Open

Comments

@NathZ1
Copy link

NathZ1 commented Mar 14, 2024

Describe the bug
Registering a custom font with Font.register() results in usePDF never generating the PDF as expected. Commenting out the use of the custom font in StyleSheet allows PDF to generate, which leads me to believe it is an issue with how @react-pdf/renderer instantiates custom fonts. There is no error thrown, making it very difficult to diagnose the issue...

To Reproduce
This minimal example of index.tsx shows the reproducible error (React 18, Webpack 5 configuration, NOT Create React App):

import React from 'react'
import ReactDOM from 'react-dom/client'
import { Document, Page, Text, Font, usePDF, StyleSheet } from '@react-pdf/renderer'
import ArialBold from './arial-bold.ttf'

Font.register({
  family: 'Arial',
  fonts: [
    {
      src: ArialBold,
      fontStyle: 'normal',
      fontWeight: 'bold'
    }
  ]
})

const styles = StyleSheet.create({
  heading: {
    //comment these 2 lines out and it will generate PDF properly
    fontFamily: 'Arial',
    fontWeight: 'bold',

    fontSize: 20,
    color: '#006699'
  }
})

const App = () => {
  const [instance] = usePDF({
    document: (
      <Document title={'Title'} author={'Author'} subject={'Subject'} pageMode="useNone">
        <Page size="A4">
          <Text style={styles.heading}>text1</Text>
          <Text>text2</Text>
          <Text>text3</Text>
        </Page>
      </Document>
    )
  })

  console.log('ArialBold', ArialBold)
  console.log('Font.getRegisteredFonts().', Font.getRegisteredFonts())
  console.log('instance', instance)

  return (
    <a href={instance.url || undefined} download={'filename.pdf'}>
      DOWNLOAD PDF
    </a>
  )
}

const root = ReactDOM.createRoot(document.getElementById('root')!)

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)

Output of console.logs shows the path to the font and the font being registered, however the instance.loading remains = true indefinately. I have followed the path to the font and the path is correct

14:25:01.850 index.tsx:39 ArialBold /media/arial-bold.ff5427169c7aaacb3946.ttf
14:25:01.850 index.tsx:40 Font.getRegisteredFonts(). {Arial: Font}
14:25:01.850 index.tsx:41 instance {url: null, blob: null, error: null, loading: true}

Expected behavior
PDF is available to download via instance.url

Desktop (please complete the following information):

  • OS: Windows 10
  • Browser: Chromium
  • React-pdf version: 3.3.8
@cw789
Copy link

cw789 commented Mar 14, 2024

It seems I'm encountering the same issue.

@raissska
Copy link

I have the same problem also.

@ali-yunes
Copy link

Same problem!

@brad-telus
Copy link

brad-telus commented Mar 14, 2024

I'm also running into this issue. I am producing a PDF via the renderToStream() function. After that I collect the stream into a byte array, so I can store the bytes into a cloud storage.

            const readableStreamToByteArray = (stream: NodeJS.ReadableStream): Promise<Array<Uint8Array>> => {
                  return new Promise((resolve, reject) => {
                       const chunks: Array<Uint8Array> = [];
                       stream.on('data', (chunk) => {
                            console.log(`loading chunk ${chunks.length + 1}...`)
                            chunks.push(chunk);
                       });
                       stream.on('error', () => reject(`Error occurred while reading pdf file`));
                       stream.on('end', () => resolve(chunks));
                 });
            }

            const pdfStream: NodeJS.ReadableStream = await renderToStream(
                <MyPdf content={"Hello World"} />
            );
            const byteArray = await readableStreamToByteArray(byteArray);
            

When running this code, with a custom font, I see that chunks of stream content are getting loaded, but the "end" stream event is never called. It simply hangs on the last chunk and the promise is never resolved

@alyywehby
Copy link

I have the same problem!!

@vipuljbhikadiya
Copy link

vipuljbhikadiya commented Mar 14, 2024

face same problem with next.js when using
const blob = await pdf(MyDoc).toBlob()

I am using diffrent fonts, but facing issue in only one font (Greycliff CF) , other all fonts are working.
also another point is issue arise only on my server, in localhost its working with "Greycliff CF" font

@Linkerbrain
Copy link

I have the same issue. When downloading an example google font from this list and importing that, it does work (for example with http://fonts.gstatic.com/s/roboto/v16/zN7GBFwfMP4uA6AR0HCoLQ.ttf)

Font.register({
    family: 'Roboto2',
    fonts: [
        { src: fromlink, fontWeight: "normal", fontStyle: "normal" },
    ],
});

                    const exampleDoc = <Document>
                        <Page>
                            <Text style={{ fontFamily: "Roboto2" }}>This is a test</Text>
                        </Page>
                    </Document>

                    const asPdf = pdf(exampleDoc);
                    console.log("asPdf", asPdf) // prints: Object { on: on4(event, listener), container: {…}, toBlob: toBlob2(), toBuffer: toBuffer2(), toString: toString8(), ... }

                    const str = asPdf.toString();
                    console.log("asPdf", str) // prints: <state>: "pending", <state>: "fulfilled", <value>: "%PDF-1.3\n%����\n9 0 obj\n<<\n/Type /Ex

                    const test = asPdf.toBlob().then(result => {
                        console.log(result); // prints: Blob { size: 4431, type: "application/pdf" }
                    }).catch(error => {
                        console.error("Error generating PDF", error);
                    });

However when I then open the same file in FontForge, and export it as "bad.ttf" without changing any of the settings, it suddenly Fails:

import fromlink from "../../font/roboto/bad.ttf";
Font.register({
    family: 'Roboto2',
    fonts: [
        { src: fromlink, fontWeight: "normal", fontStyle: "normal" },
    ],
});
                    const exampleDoc = <Document>
                        <Page>
                            <Text style={{ fontFamily: "Roboto2" }}>This is a test</Text>
                        </Page>
                    </Document>

                    const asPdf = pdf(exampleDoc);
                    console.log("asPdf", asPdf) // prints: Object { on: on4(event, listener), container: {…}, toBlob: toBlob2(), toBuffer: toBuffer2(), toString: toString8(), ... }

                    const str = asPdf.toString();
                    console.log("asPdf", str) // prints: <state>: "pending", <state>: "pending"

                    const test = asPdf.toBlob().then(result => {
                        console.log(result); // NEVER prints!
                    }).catch(error => {
                        console.error("Error generating PDF", error); // NEVER prints!
                    });

It also seems to fail on any other non google font in my experience. Can it be that it somewhere only accepts fonts that match the checksum of fonts available via google fonts? Is there any other unspecified encoding parameter that determines if it can handle the .ttf file? There really seems to be barely a difference in the files... I am lost

font files for reference

@brad-telus
Copy link

brad-telus commented Mar 14, 2024

Hi @Linkerbrain, I can confirm that using Google Fonts resolves my issue as well. Although this is a big annoyance on my side, since my project needs access to non-Google fonts.

@Linkerbrain
Copy link

Hi @Linkerbrain, I can confirm that using Google Fonts resolves my issue as well. Although this is a big annoyance on my side, since my project needs access to non-Google fonts.

For me that is also the case, custom fonts is an essential part of my project so this is a really breaking issue.

To debug, do you know when streaming the result with a google font, if the last chunks/end event include anything about the font? Maybe we could hotfix it by fake appending a standard end chunk after a set amount of time.

@brad-telus
Copy link

brad-telus commented Mar 14, 2024

@Linkerbrain I tried this with a setTimeout(() => resolve(chunks), 10000), and when that timeout was hit the resulting PDF did not have any text in it. It was able to render background colours and images, but the text was not present.

So, it appears that the text literally cannot be rendered.

@SouadAli1010
Copy link

same issue as well

@bcattonsimply
Copy link

This is happening to me as well.

@thebigbluebox
Copy link

The way we resolved this was by going back to using the system packaged fonts. We had to fully abandon the use of imported fonts for now.

@NathZ1
Copy link
Author

NathZ1 commented Mar 15, 2024

The way we resolved this was by going back to using the system packaged fonts. We had to fully abandon the use of imported fonts for now.

Not really an option for a lot of users that have to adhere to style guides... :(

@cduff
Copy link

cduff commented Mar 15, 2024

I was hit by this too. After some investigation, it seems to have been caused by the underlying restructure dependency updating from 3.0.0 to 3.0.1.

@Skywalker13
Copy link

Skywalker13 commented Mar 15, 2024

I was hit by this too. After some investigation, it seems to have been caused by the underlying restructure dependency updating from 3.0.0 to 3.0.1.

Have you tried a downgrade with overrides in your base package.json for restructure?

@cduff
Copy link

cduff commented Mar 15, 2024

I was hit by this too. After some investigation, it seems to have been caused by the underlying restructure dependency updating from 3.0.0 to 3.0.1.

Have you tried a downgrade with overrides in your base package.json for restructure?

Yes, worked for me.

@Skywalker13
Copy link

I was hit by this too. After some investigation, it seems to have been caused by the underlying restructure dependency updating from 3.0.0 to 3.0.1.

Have you tried a downgrade with overrides in your base package.json for restructure?

Yes, worked for me.

Great, I spend hours yesterday to find the broken dependency without success. Thank you!

@PelosiTech
Copy link

PelosiTech commented Mar 15, 2024

I was hit by this too. After some investigation, it seems to have been caused by the underlying restructure dependency updating from 3.0.0 to 3.0.1.

@cduff Appreciate you posting this. Thank you, this fixed worked. By adding this to the Resolutions/Overrides. These issues have been fixed.

NPM
package.json
"overrides": { "restructure": "3.0.0" }
or
Yarn/PNPM
package.json
"resolutions": { "restructure": "3.0.0" }

What was your process to be able to find this? Curious for future issues. Did you look into the lock file, look into fontkit and dependencies and go one by one to see recent upgrades?

@nikischin
Copy link
Contributor

I do have the same issue. However, I noticed it's not the Font.register which does break my code, but the usage of the font which is registered within the styles. Not sure if it does make a difference but might be a small hint for debugging the issue.

@cduff
Copy link

cduff commented Mar 17, 2024

What was your process to be able to find this? Curious for future issues. Did you look into the lock file, look into fontkit and dependencies and go one by one to see recent upgrades?

@PelosiTech I noticed it broke from one deployment to the next even though the version of @react-pdf/renderer remained the same. From the git commit log I could see npm update had been run. I did a diff on package-lock.json and compared to the list of dependencies of @react-pdf/renderer retrieved using npm list --all. There was a single package that featured in both lists - the restructure package, updated from 3.0.0 to 3.0.1.

@NathZ1
Copy link
Author

NathZ1 commented Mar 17, 2024

I do have the same issue. However, I noticed it's not the Font.register which does break my code, but the usage of the font which is registered within the styles. Not sure if it does make a difference but might be a small hint for debugging the issue.

Yes, that's correct. In my example I originally posted, commenting out the use of the custom font in the stylesheet fixes the issue.

At the moment, overriding the restructure package back to 3.0.0 is the correct workaround, as others have noted above.

@cduff
Copy link

cduff commented Mar 18, 2024

I'm guessing a bug was introduced into restructure in 3.0.1. Just now I can't see any new issues listed in its repo related to this: https://github.com/foliojs/restructure/issues.

I'm not familiar enough with the internal workings of react-pdf and its use of restructure to be able to efficiently do this. I wonder if we can get help from a maintainer for this?

@diegomura
FYI @devongovett

@brad-telus
Copy link

Hi @diegomura, any updates on this issue? can we add a lock file to ensure this doesn't happen again?

@tirmey
Copy link

tirmey commented Apr 3, 2024

Two days fighting this very issue!
Indeed, overriding "restrucuture" module to use v. 3.0.0 solves it. Thank yall, so much!

@buster95
Copy link

buster95 commented Apr 4, 2024

oh gosh same problem with fonts
I'm using following code with custom fonts

const fileBlob = await pdf(<My Doc />).toBlob()

using last version of library 3.4.2
but toBlob() function never throw me errors just break the code never finish their execution
I've removed font register and works again

@srl295
Copy link

srl295 commented Apr 5, 2024

Hi. I'm new to these tools, but I'm trying to create a repro so I can investigate what's happening in restructure. Can anyone give some pointers on how to get from a simple repro?

What I'm trying currently:

e7c99e7b141a88f62525b70b68367fd0 /mnt/c/Windows/Fonts/arialbd.ttf

  • npm i and npm start

@srl295
Copy link

srl295 commented Apr 5, 2024

also it seems the intermediate dependency is
@react-pdf/render -> @react-pdf/font -> fontkit -> restructure

@srl295
Copy link

srl295 commented Apr 5, 2024

I have a smaller repro see foliojs/fontkit#331 (comment)

And (edit) have a fix PR in foliojs/restructure#62

edit the restructure PR was merged..

@Frontend-io
Copy link

I was hit by this too. After some investigation, it seems to have been caused by the underlying restructure dependency updating from 3.0.0 to 3.0.1.

@cduff Appreciate you posting this. Thank you, this fixed worked. By adding this to the Resolutions/Overrides. These issues have been fixed.

NPM package.json "overrides": { "restructure": "3.0.0" } or Yarn/PNPM package.json "resolutions": { "restructure": "3.0.0" }

What was your process to be able to find this? Curious for future issues. Did you look into the lock file, look into fontkit and dependencies and go one by one to see recent upgrades?

Thanks man, you made my day! Been debugging this issue for the past two nights!

@srl295
Copy link

srl295 commented Apr 19, 2024

@Frontend-io I have a merged PR in the dep's dep that fixes it. Just waiting for @devongovett to make a new restructure release to patch.

@ashkankiani
Copy link

I have the same problem also.

@sergical
Copy link

I was hit by this too. After some investigation, it seems to have been caused by the underlying restructure dependency updating from 3.0.0 to 3.0.1.

You saved my life

@srl295
Copy link

srl295 commented May 21, 2024

I'm still waiting on restructure to publish a 3.0.2 with the actual fix. It's already merged.

belanglos added a commit to KTH/kursplan-api that referenced this issue May 31, 2024
and install npm version of react-pdf
Overriding restructure was needed because of this issue: diegomura/react-pdf#2675
belanglos added a commit to KTH/kursplan-api that referenced this issue May 31, 2024
and install npm version of react-pdf
Overriding restructure was needed because of this issue: diegomura/react-pdf#2675
belanglos added a commit to KTH/kursplan-api that referenced this issue May 31, 2024
and install npm version of react-pdf
Overriding restructure was needed because of this issue: diegomura/react-pdf#2675
belanglos added a commit to KTH/kursplan-api that referenced this issue Jun 3, 2024
and install npm version of react-pdf
Overriding restructure was needed because of this issue: diegomura/react-pdf#2675
@karlhorky
Copy link
Contributor

karlhorky commented Jun 13, 2024

@cduff Appreciate you posting this. Thank you, this fixed worked. By adding this to the Resolutions/Overrides. These issues have been fixed.

NPM package.json "overrides": { "restructure": "3.0.0" } or Yarn/PNPM package.json "resolutions": { "restructure": "3.0.0" }

@PelosiTech thanks for the workaround!

You could also update your comment for those using pnpm Overrides:

{
  "pnpm": {
    "overrides": {
      "restructure": "3.0.0"
    }
  }
}

@karlhorky
Copy link
Contributor

karlhorky commented Jun 16, 2024

Devon released restructure@3.0.2 with the fix from @srl295, which I can confirm fixes the issue with custom fonts in our apps using @react-pdf/renderer.

@NathZ1 if this also resolved for you, I guess the issue can be closed?

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

No branches or pull requests