react-pdf icon indicating copy to clipboard operation
react-pdf copied to clipboard

Error: Font family not registered

Open reinhardatovos opened this issue 2 years ago • 2 comments

Describe the bug Hi, I'm trying to use custom fonts within my pdf document - on my local machine everything is working fine, but on stage I get an Error when rendering the PDF: Error: Font family not registered: WorkSans. Please register it calling Font.register() method.

I am using 2 custom font families, I already tried to reduce it to 1 which gives me also the same error. I tried both, Font.register() outside and inside the React component, I also tried to log the registered Font Families via Font.getRegisteredFontFamilies() and Font.getRegisteredFonts() -> Log says that they my >Font Families are registered (see Screenshot)

font error

I really dont know whats happening, since in logs my FontFamilies are shown...

I would appreciate every bit of advice, thank you.

import ReactPDF, { Document, Font, Image, Page, StyleSheet, Text, View } from '@react-pdf/renderer';
import sourceSansPro from './../../public/fonts/SourceSansPro/SourceSansPro400.ttf';
import sourceSansSemibold from './../../public/fonts/SourceSansPro/SourceSansPro600.ttf';
import workSansSemibold from './../../public/fonts/WorkSans/WorkSans600.ttf';
import workSansBold from './../../public/fonts/WorkSans/WorkSans700.ttf';
import ...

const CertificatePDF = ({ data }: CertificateProps) => {
  Font.clear();
  Font.reset();

  Font.register({
    family: 'WorkSans',
    fonts: [
      { src: workSansSemibold, fontWeight: 600 },
      { src: workSansBold, fontWeight: 700 },
    ],
  });

  Font.register({
    family: 'SourceSansPro',
    fonts: [{ src: sourceSansPro }, { src: sourceSansSemibold, fontWeight: 600 }],
  });

  console.log(
    'font register should have happened',
    workSansSemibold,
    workSansBold,
    sourceSansPro,
    sourceSansSemibold
  );

  const greyColor = '#3F494F';

  const styles = StyleSheet.create({
    locationDate: {
      fontFamily: "SourceSansPro",
      position: "absolute",
      left: 0,
      bottom: 0,
      fontSize: 12,
      fontWeight: 600,
      color: greyColor,
      maxWidth: "50%",
      paddingRight: "5px",
    },
    signatureName: {
      fontFamily: "SourceSansPro",
      width: "100%",
    },
   certification: {
      fontFamily: "WorkSans",
      fontSize: 14,
      fontWeight: 600,
    },
    // more ...
  });

  console.log('registered getRegisteredFontFamilies', Font.getRegisteredFontFamilies());
  console.log('registered getRegisteredFonts', Font.getRegisteredFonts());

  const [isFontLoaded, setIsFontLoaded] = useState<boolean>(false);

  const loadFonts = useCallback(async () => {
    await Promise.all([
      Font.load({ fontFamily: 'WorkSans', fontWeight: 600 }),
      Font.load({ fontFamily: 'WorkSans', fontWeight: 700 }),
      Font.load({ fontFamily: 'SourceSansPro' }),
      Font.load({ fontFamily: 'SourceSansPro', fontWeight: 600 }),
    ]);
    setIsFontLoaded(true);
    console.log(Font.getRegisteredFontFamilies());
    console.log('fonts loaded');
  }, []);

  useEffect(() => {
    loadFonts();
  }, [loadFonts]);
  

  if (!isFontLoaded) {
    // tslint:disable-next-line:no-console
    console.log('isFontLoaded is FALSE');
    return (
      <Document title={data.fileName}>
        <Page size="A4" style={styles.page} />
      </Document>
    );
  }
  console.log('rendering certificate...');
  return (
    <Document title={data.fileName}>
      <Page size="A4" style={styles.page}>
        <View style={styles.background}>
          <BackgroundPattern />
        </View>
        <View style={[styles.background, { transform: 'scaleX(-1)' }]}>
          <BackgroundPattern />
        </View>
        <View style={styles.heading}>
          <Header color={data.color} />
        </View>
        <View style={styles.badge}>
          <Badge color={data.color} />
          {data.logo && <Image src={data.logo} style={styles.clientLogo} />}
        </View>
        <View style={styles.mainContainer}>
          <View style={styles.fullWidth}>
            <Text style={[styles.certification, { color: data.color }]}>
              {t('certification').toUpperCase()}
            </Text>
            <Text
              style={[styles.participant, { fontSize: participantFontSize, top: participantTop }]}
            >
              {data.participantName}
            </Text>
            <View style={styles.seperatorContainer}>
              <Seperator />
            </View>
            <View style={styles.participationContainer}>
              {data.type === 'assessment' ? (
                <Text style={styles.participate}>{t('took and passed the exam')}</Text>
              ) : (
                <Text style={styles.participate}>{t('participated in')}</Text>
              )}
              <Text style={[styles.assessmentName, { fontSize: eventFontSize, top: eventTop }]}>
                {data.assessmentName}
              </Text>
              <Text style={styles.assessmentDate}>
                {t('on')} {data.assessmentDate}
              </Text>
            </View>
          </View>
          {getBackgroundImage(data)}
          <View style={styles.bottomArea}>
            {data.description && (
              <View style={styles.description}>
                <Text>{data.description}</Text>
              </View>
            )}
            {data.qrCode && (
              <View style={styles.qrContainer}>
                <Image src={data.qrCode} />
              </View>
            )}
            <View style={styles.locationDate}>
              <Text>
                {data.location && data.location !== '' && `${data.location}, `}
                {data.signatureDate}
              </Text>
            </View>
            <View style={styles.signatureContainer}>
              <View style={styles.signatureImageContainer}>
                {data.signatureImage && (
                  <Image src={data.signatureImage} style={styles.signatureGraphic} />
                )}
              </View>
              <View style={styles.signatureName}>
                <Text>{data.signatureName}</Text>
              </View>
            </View>
          </View>
        </View>
      </Page>
    </Document>
  );
};
// Render in DOM
export default CertificatePDF;

reinhardatovos avatar Aug 08 '23 09:08 reinhardatovos

I'm experiencing a similar issue - When attempting to use React PDF on the server, with custom (ttf) fonts and esbuild, the following error is produced:

/Projects/react-pdf-font-loading-issue/node_modules/yoga-layout/binaries/wasm-async-node.js:11
process.on("uncaughtException",function(a){throw a;});process.on("unhandledRejection",function(a){throw a;});g.inspect=function(){return"[Emscripten Module object]"};var ia=g.print||console.log.bind(console),v=g.printErr||console.warn.bind(console);Object.assign(g,ba);ba=null;var ja;g.wasmBinary&&(ja=g.wasmBinary);var noExitRuntime=g.noExitRuntime||!0;"object"!=typeof WebAssembly&&w("no native wasm support detected");var ka,la=!1;

Error: Font family not registered: roboto. Please register it calling Font.register() method.

Steps to reproduce Clone the following repo:

git clone https://github.com/joepk90/react-pdf-font-loading-issue.git

Install dependancies:

cd react-pdf-font-loading-issue
yarn

Run the following command to see reproduce the error:

make generate-pdf

Environment Browser (if applicable): React-PDF version: 3.4.4 React version: 18.3.1 Node: 18.16.0

joepk90 avatar Jun 10 '24 10:06 joepk90

Have the same issue right now

vhrechukha avatar Jun 27 '24 12:06 vhrechukha