-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Custom font loading issue #334
Comments
I have the same question. I haven't been able to use a custom font successfully. It would be helpful to know what font types are supported (.otf, .ttf, .woff, etc) and how to fetch them via URL without running into CORS issues (both during development and in production). |
The React PDF Playground has a link to Does anyone know if these TTF links exist for all Google Fonts? |
Nope. Not sure if they do. Sorry |
@emorling I recently came across to this repo https://github.com/google/fonts that has all the google fonts in .ttf format |
@jasonbarry Only .ttf fonts supported for the moment |
Closing this since all points had been cleared |
Here you can find a similar link to all google fonts: |
I think this information would be valuable in the docs. 😃 |
Are WOFF/WOFF2 formats supported? I've been trying to import both in files and from Google Font CDN links but to no avail. |
lol, it took me two days and a look at ~50 github issues in this repo to find this random comment in a 2018 issue to confirm that only ttf is working. Which is really troublesome since ttf is a largely deprecated format and lots of new fonts are only released as otf (which is also a better and more modern format in every way). The original fontkit also seems to support otf/woff, so (obviously without knowing the full picture) it sounds like not too far fetched? @diegomura what are the major show-stoppers? Where do we stand, is there a specific point where I could help? |
Yes, you just have to use |
@diegomura Has this changed since you wrote this comment? Because .woff fonts seem to work fine, whereas .woff2 seem to be problematic. |
Until woff2 is supported. I've created a python script which accepts Google fonts URL, it downloads and converts file into ttf and saves them in ./fonts directory, it then generates react PDF Font.register with all of the font styles,weights and references to the ttf converted font files. Usage:python get-fonts.py "<URL>" <unicode-range> Example:python get-fonts.py "https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,900;1,300;1,400;1,900&display=swap" latin Downloads & Converts font files, then create output.ts file example:import { Font } from '@react-pdf/renderer';
type FontWeight = 'normal' | 'bold' | 'light' | undefined;
type FontStyle = 'normal' | 'italic' | 'oblique' | undefined;
Font.register({
family: 'Roboto:ital,wght@0,300;0,400;0,900;1,300;1,400;1,900',
fonts: [
{
src: 'fonts/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.ttf',
fontStyle: 'italic' as FontStyle,
fontWeight: '300' as FontWeight,
},
{
src: 'fonts/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.ttf',
fontStyle: 'italic' as FontStyle,
fontWeight: '300' as FontWeight,
},
{
src: 'fonts/KFOkCnqEu92Fr1Mu51xHIzIFKw.ttf',
fontStyle: 'italic' as FontStyle,
fontWeight: '400' as FontWeight,
},
{
src: 'fonts/KFOkCnqEu92Fr1Mu51xGIzIFKw.ttf',
fontStyle: 'italic' as FontStyle,
fontWeight: '400' as FontWeight,
},
{
src: 'fonts/KFOjCnqEu92Fr1Mu51TLBCc1CsTKlA.ttf',
fontStyle: 'italic' as FontStyle,
fontWeight: '900' as FontWeight,
},
{
src: 'fonts/KFOjCnqEu92Fr1Mu51TLBCc0CsTKlA.ttf',
fontStyle: 'italic' as FontStyle,
fontWeight: '900' as FontWeight,
},
{
src: 'fonts/KFOlCnqEu92Fr1MmSU5fCxc4EsA.ttf',
fontStyle: 'normal' as FontStyle,
fontWeight: '300' as FontWeight,
},
{
src: 'fonts/KFOlCnqEu92Fr1MmSU5fChc4EsA.ttf',
fontStyle: 'normal' as FontStyle,
fontWeight: '300' as FontWeight,
},
{
src: 'fonts/KFOmCnqEu92Fr1Mu7WxKOzY.ttf',
fontStyle: 'normal' as FontStyle,
fontWeight: '400' as FontWeight,
},
{
src: 'fonts/KFOmCnqEu92Fr1Mu7GxKOzY.ttf',
fontStyle: 'normal' as FontStyle,
fontWeight: '400' as FontWeight,
},
{
src: 'fonts/KFOlCnqEu92Fr1MmYUtfCxc4EsA.ttf',
fontStyle: 'normal' as FontStyle,
fontWeight: '900' as FontWeight,
},
{
src: 'fonts/KFOlCnqEu92Fr1MmYUtfChc4EsA.ttf',
fontStyle: 'normal' as FontStyle,
fontWeight: '900' as FontWeight,
},
],
}); Code:import os
import requests
from fontTools.ttLib import TTFont
from bs4 import BeautifulSoup
from tqdm import tqdm
import sys
import subprocess
def download_and_convert_fonts(url: str, unicode_range: str):
# Set headers to mimic a request from a Chrome browser
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
}
# Parse the file for each font and style and weight and font family name
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
font_faces = soup.string.split('@font-face')
# Create a temp directory to store downloaded fonts
temp_dir = "fonts"
os.makedirs(temp_dir, exist_ok=True)
# Create a list to store font registration details
font_registers = []
# Extract the font family name from the URL
family_name = url.split('family=')[1].split('&')[0].replace('+', ' ')
# Progress bar setup
total_fonts = len([font_face for font_face in font_faces if 'src:' in font_face and unicode_range in font_face])
print(f"Total number of fonts to be processed: {total_fonts}")
pbar = tqdm(total=total_fonts, desc=f"Processing fonts for family: {family_name}")
for font_face in font_faces:
if 'src:' in font_face and unicode_range in font_face:
font_family = font_face.split("font-family: '")[1].split("';")[0]
font_style = font_face.split("font-style: ")[1].split(";")[0]
font_weight = font_face.split("font-weight: ")[1].split(";")[0]
font_url = font_face.split("src: url(")[1].split(") format('")[0]
# Get the font from the URL into temp directory
font_response = requests.get(font_url)
font_filename = os.path.join(temp_dir, font_url.split('/')[-1])
with open(font_filename, 'wb') as font_file:
font_file.write(font_response.content)
# Convert WOFF2 to TTF if necessary using pyftsubset
if font_filename.endswith('.woff2'):
ttf_filename = font_filename.replace('.woff2', '.ttf')
subprocess.run(['pyftsubset', font_filename, '--output-file=' + ttf_filename], check=True)
else:
ttf_filename = font_filename
# Use font tools to convert to a ttf and save it in current directory
font = TTFont(ttf_filename)
font.save(ttf_filename)
# Add to font registration list
font_registers.append({
"family": font_family,
"src": ttf_filename,
"fontStyle": font_style,
"fontWeight": font_weight
})
# Update progress bar
pbar.update(1)
pbar.close()
# Create output.ts with Font.register
with open('output.ts', 'w') as output_file:
output_file.write("import { Font } from '@react-pdf/renderer';\n\n")
output_file.write("type FontWeight = 'normal' | 'bold' | 'light' | undefined;\n")
output_file.write("type FontStyle = 'normal' | 'italic' | 'oblique' | undefined;\n\n")
output_file.write("Font.register({\n")
output_file.write(f" family: '{family_name}',\n")
output_file.write(" fonts: [\n")
for font in font_registers:
output_file.write(f" {{\n")
output_file.write(f" src: '{font['src']}',\n")
output_file.write(f" fontStyle: '{font['fontStyle']}' as FontStyle,\n")
output_file.write(f" fontWeight: '{font['fontWeight']}' as FontWeight,\n")
output_file.write(f" }},\n")
output_file.write(" ],\n")
output_file.write("});\n")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python get-fonts.py <URL> <unicode-range>")
sys.exit(1)
url = sys.argv[1]
unicode_range = sys.argv[2]
download_and_convert_fonts(url, unicode_range) |
I can confirm that WOFF fonts work, but WOFF2 fonts do not. I've opened a PR to document WOFF support here: |
OS:
Linux
React-pdf version:
"@react-pdf/renderer": "1.0.0-alpha.18"
Description:
I have a problem with load custom font.
In docs we can read "Specifies the source of the font. This can either be a valid URL, or an absolute path if you're using react-pdf on Node."
So in first approach i tried include font from google font
https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu72xKOzY.woff2
but this format is not support.
So in second approach I tried upload Roboto font in tff format to my private hosting but in DEMO code there was some message about mix content http/https .. so I upload font into github which has https protocol.
Also I tried served locally font in my react app but there is message error:
" No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3005' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."
I built local server for serving font with enabled cors but it doesn't work
I provide react demo where I tried generate pdf with some custom pdf.
https://codesandbox.io/s/5k72n7zq2n
I think there is a problem with fetch method. Exactly in file react-pdf.browser.es.js with
fetchFont method
var fetchFont = function fetchFont(src) {
return fetch(src).then(function (response) {
if (response.buffer) {
return response.buffer();
}
return response.arrayBuffer();
}).then(function (arrayBuffer) {
return Buffer.from(arrayBuffer);
});
};
I think that fetch method should include some headers and cors mode for fetching successfully any resources
So the final questions is:
How do I use some custom font ?
The text was updated successfully, but these errors were encountered: