3

How do I add unicode font in my GAE application using PyFPDF?

I have gone through the tutorials on: https://pyfpdf.readthedocs.io/en/latest/Unicode/index.html#metric-files

FPDF will try to automatically generate metrics (i.e. character widths) about TTF font files to speed up their processing.

Such metrics are stored using the Python Pickle format (.pkl extension), by default in the font directory (ensure read and write permission!). Additional information about the caching mechanism is defined in the add_font reference.

The problem here is PyFPDF will create the metrics file (.pkl) in the folder, it required write permission, GAE doesn't allow to write file, how should I do it?

Thank you!

Joel

Community
  • 1
  • 1
Joel T.
  • 402
  • 3
  • 15
  • 1
    You can try using GCS, see, for example, https://stackoverflow.com/a/39525052/4495081, but it may be tricky as the GCS-specific `open()` needs to be used instead of the regular filesystem one. You may need to hack/extend `fpdf.add_font()` (or its innards) and maybe other areas to get it working. – Dan Cornilescu Jan 14 '18 at 16:29
  • @DanCornilescu thanks for the info, I tried it and it works. But I see another problem is that it takes very long to load the PDF page, normally it takes only about 5 sec to load without embed unicode font, after adding the unicode font add_font(), it take more than 30 seconds, and sometime cause timeout error. Any clue to solve this issue? – Joel T. Jan 16 '18 at 09:18
  • Using a faster instance class would be one way, but costs will go up. Other than that you'd have to do some profiling to see what's taking that long. It may simply be that it's just much heavier processing. – Dan Cornilescu Jan 16 '18 at 13:26
  • 1
    Thanks DanCornilescu. The issue has been resolved, following what @VictorGCI suggested bellow by setting the FPDF_CACHE_MODE constant = 1, everything will just work perfectly. :) – Joel T. Jan 16 '18 at 13:45

2 Answers2

3

The add_font() function makes use of the FPDF_CACHE_MODE constant which looks like is the one specifying if writing the .pkl files or not. This constant may have three values (either 0, 1 or 2). If settled to 1 then it does not write the .pkl files. This constant is defined in the fpdf.py file of the library. Therefore you need to modify this file and set the constant to 1 before you do the deploy.

VictorGGl
  • 1,848
  • 10
  • 15
  • @VictorGCI Thank for the trick! It works perfectly. Has been spending hours to solve this issue, in fact just set the FPDF_CACHE_MODE = 1, everything will just work fine. – Joel T. Jan 16 '18 at 13:41
2

While the accepted solution works it requires you to include the fpdf source files into your project, which is not ideal if you just want to work with the fpdf package.

A solution that also works without changing the source file is to set the global variable FPDF_CACHE_MODE via the set_global() function, which is provided in the FPDF package.

Example:

import fpdf
fpdf.set_global("FPDF_CACHE_MODE", 1)
Erik Kalkoken
  • 30,467
  • 8
  • 79
  • 114
  • Let's say I have to use a version of `fpdf` that does not have this `set_global` method, how could I obtain the same result? I had no luck when trying to simply call `fpdf.FPDF_CACHE_MODE = 1` in my code. – etauger Apr 19 '23 at 19:49
  • Found a solution; I had to specify `fpdf.fpdf.FPDF_CACHE_MODE = 1` (two fpdf deep) in order for it to have an impact on the `add_font` method. This [answer](https://stackoverflow.com/a/12496239/17432370) helped me, but I am still unsure why it is working that way. – etauger Apr 20 '23 at 00:19
  • hey! Glad you found a solution. This answer is for an older version, maybe the current version has a slightly different API. But it seams to be the same variable that does the trick. – Erik Kalkoken Apr 20 '23 at 02:28