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

KeyError: '.notdef' when adding a font with add_font() #1161

Closed
Gdesau opened this issue May 8, 2024 · 5 comments
Closed

KeyError: '.notdef' when adding a font with add_font() #1161

Gdesau opened this issue May 8, 2024 · 5 comments

Comments

@Gdesau
Copy link

Gdesau commented May 8, 2024

Hello everyone, I'm trying to add a unicode Times New Roman font but I get a KeyError. Here is my code:

The function:

import os
from fpdf import FPDF

def trans_txt_to_pdf(trans_txt, output_dir):
    """
    Takes a .txt file of a transcription and
    creates a pdf of the transcription with
    the file name as title.

    Parameters
    ----------
    trans_txt: path to the .txt file containing
    the transcription (str)
    output_dir: path to the directory where
    to save the pdf created (str)

    Returns
    -------
    trans_pdf: path to the pdf created (str)
    
    """
    # Instantiate the pdf object
    pdf = FPDF()
    # Add a page
    pdf.add_page()
    # Add a unicode font to avoid error with
    # characters
    pdf.add_font(
        'tnr-uni',
        style='',
        fname='/System/Library/Fonts/Supplemental/Times New Roman.ttf'
    )
    pdf.add_font(
        'tnr-uni',
        style='b',
        fname='/System/Library/Fonts/Supplemental/Times New Roman Bold.ttf'
    )
    # Set the font parameters for title
    pdf.set_font('times-new-roman', 'bu', 18)
    # Retrieve the .txt file name
    trans_name = os.path.splitext(
        trans_txt.split('/')[-1]
    )[0]
    # Add the title cell
    pdf.cell(w=0, text=trans_name, align='C')
    # Linebreak
    pdf.ln(12)
    # Set the font parameters for the
    # transcription
    pdf.set_font(
        family='times-new-roman',
        style='',
        size=12
    )
    # Insert the transcription
    ## Open the .txt file in read mode
    with open(trans_txt, 'r') as txt_file:
        ## Read the lines of .txt file
        transcritpion = txt_file.read()
    # Close the .txt file to avoid issues
    txt_file.close()
    ## Insert them into the pdf
    pdf.multi_cell(0, 8, transcritpion)
    ## Linebreak
    pdf.ln()
    # Create the output path
    ## Add the .pdf extension to
    ## transcription title
    file_name = trans_name+'.pdf'
    ## Concatenate output dir and file name
    out_path = os.path.join(
        output_dir, file_name
    )
    # Save the pdf to a .pdf file, use .encode()
    # to avoid UnicodeEncodeError
    pdf.output(out_path)
    # Return the path to the created pdf file
    return out_path

The code where I use the function:

pdf_dir = '/Users/my_user/Dev/projects/project_dir/files/pdf'
trans_txt_to_pdf('/Users/my_user/Dev/projects/project_dir/files/txt/test_court_transcription.txt', pdf_dir)

And here is the error I get:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[27], line 1
----> 1 trans_txt_to_pdf('/Users/my_user/Dev/projects/project_dir/files/txt/test_court_transcription.txt', pdf_dir)

Cell In[26], line 30, in trans_txt_to_pdf(trans_txt, output_dir)
     23 # Add a unicode font to avoid error with
     24 # characters
     25 pdf.add_font(
     26     'tnr-uni',
     27     style='',
     28     fname='/System/Library/Fonts/Supplemental/Times New Roman.ttf'
     29 )
---> 30 pdf.add_font(
     31     'tnr-uni',
     32     style='b',
     33     fname='/System/Library/Fonts/Supplemental/Times New Roman Bold.ttf'
     34 )
     35 # Set the font parameters for title
     36 pdf.set_font('times-new-roman', 'bu', 18)

File ~/anaconda3/envs/my_env/lib/python3.11/site-packages/fpdf/fpdf.py:1854, in FPDF.add_font(self, family, style, fname, uni)
   1848     warnings.warn(
   1849         f"Core font or font already added '{fontkey}': doing nothing",
   1850         stacklevel=get_stack_level(),
   1851     )
   1852     return
-> 1854 self.fonts[fontkey] = TTFFont(self, font_file_path, fontkey, style)

File ~/anaconda3/envs/my_env/lib/python3.11/site-packages/fpdf/fonts.py:169, in TTFFont.__init__(self, fpdf, font_file_path, fontkey, style)
    164 self.ttfont = ttLib.TTFont(
    165     self.ttffile, recalcTimestamp=False, fontNumber=0, lazy=True
    166 )
    168 self.scale = 1000 / self.ttfont["head"].unitsPerEm
--> 169 default_width = round(self.scale * self.ttfont["hmtx"].metrics[".notdef"][0])
    171 try:
    172     cap_height = self.ttfont["OS/2"].sCapHeight

KeyError: '.notdef'

My Environment

  • Operating System: Mac OS Sonoma 14.4.1
  • Python version: 3.11.9
  • fpdf2 version used: 2.7.8

Does anyone have any idea on how to fix this? It's weird because it was working with the Arial font.
Thanks in advance!

@Gdesau Gdesau added the bug label May 8, 2024
@gmischler
Copy link
Collaborator

As far as I understand, it is mandatory for a TTF font to include a ".notdef" glyph (with metrics). This glyph is used in a lot of software when the actually requested glyph is not present in the font (usually displaying as a box, possibly with a question mark or X inside).

Your error message looks like this glyph (specifically: its size information) is missing from your font. If that is indeed the case, then there's little we can do about it, other than maybe produce a more informative error message.

@Gdesau
Copy link
Author

Gdesau commented May 8, 2024

Hi @gmischler, thanks a lot for your quick answer! Maybe it's due to the fact that it's the system version of "Times New Roman" or you think that it doesn't contain this glyph at all?

@gmischler
Copy link
Collaborator

Apple has some of their own specialities with regards to font file formats. I'm not sure if we have ever systematically tested our code with Apple fonts. It's possible that we might need to do something a little bit differently with those.

Of course, it is also still possible that you're just dealing with a broken font...

@Lucas-C
Copy link
Member

Lucas-C commented May 13, 2024

Do you have any other request regarding this @Gdesau? Or can this issue be closed?

@Gdesau
Copy link
Author

Gdesau commented May 13, 2024

Hi @Lucas-C, the issue can be closed, thanks @gmischler for your precious help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants