Node-html-pdf: Problems with letter spacing and custom fonts

Created on 2 Jul 2018  路  12Comments  路  Source: marcbachmann/node-html-pdf

Hi!

I'm trying to generate a pdf which I save to the server so that the user can download it later. I currently have no issues generating and saving the pdf, but when the pdf is generated on the server the letter spacing varies and I'm not able to use custom fonts (see the attached image). When running the same node-application on macOS I have no issues with letter spacing or custom fonts. Any suggestions on what might be wrong?

CSS:
@font-face { font-family: 'Open Sans'; src: url('<%= assetpath %>/assets/fonts/Open_Sans/OpenSans-Regular.ttf'); font-weight: 400; } .styled-content { font-family: 'Open Sans', sans-serif; }

JS:
var options = {filename:filename, format:'A4', orientation:'portrait', type:'pdf', width:'1024px', zoomFactor:'0.55'}; Pdf.create(req.html, options).toBuffer(function(error_pdf, pdf_buffer) {/* <code used to save the pdf> */});

Some of the things I've tried so far:

  • Uploading the fonts to /usr/share/fonts/
  • Uploading the fonts to /usr/share/fonts/type1/ (converted to type1)
  • Uploading the fonts to /usr/share/fonts/type1/gsfonts/ (converted to type1)
  • Loading the fonts externally using fonts.google.com, typekit, etc.
  • Setting the basepath in options.
  • Setting the font-url to the absolute path in combination with "file://"
  • Downgrading phantomjs-prebuilt to 2.1.13

Note: I'm running the node-application on a linux instance using AWS.

skarmavbild 2018-07-02 kl 16 08 50

Most helpful comment

Thanks a lot @agiratech-reddysai ! You saved my day !

Just post an another way to do it in EBS less complicated.
Simply add a new file in .ebextensions with this content:

files:
  "/etc/fonts/conf.d/51-local.conf":
    mode: "000755"
    owner: root
    group: root
    content: |
      <?xml version='1.0'?>
      <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
      <fontconfig>
      <match target="font">
        <edit mode="assign" name="rgba">
        <const>rgb</const>
        </edit>
      </match>
      <match target="font">
        <edit mode="assign" name="hinting">
        <bool>true</bool>
        </edit>
      </match>
      <match target="font">
        <edit mode="assign" name="hintstyle">
        <const>hintslight</const>
        </edit>
      </match>
      <match target="font">
        <edit mode="assign" name="antialias">
        <bool>true</bool>
        </edit>
      </match>
      <match target="font">
        <edit mode="assign" name="lcdfilter">
        <const>lcddefault</const>
        </edit>
      </match>
      </fontconfig>

All 12 comments

Duplicate of #405

try to use .otf

Thanks for the suggestion! But sadly I still got the same issues. Although I've only tried it using the following method (as it runs best on my computer):
@font-face { font-family: 'OpenSans'; src: url('<%= assetpath %>/assets/fonts/Open_Sans/OpenSans-Regular.otf'); font-weight: 400; }

I will try to some more methods tomorrow, but I was wondering if there is any preferred way of loading the fonts?

use "file://" or "url" and should work

@Baawa, Facing the same issue, did you find any solution?

@agiratech-reddysai Unfortunately I never found a solution to this issue :/

Thanks for your response @Baawa, I found the solution to this issue.
I just overrided this file /etc/fonts/conf.d/51-local.conf with

<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
 <match target="font">
  <edit mode="assign" name="rgba">
   <const>rgb</const>
  </edit>
 </match>
 <match target="font">
  <edit mode="assign" name="hinting">
   <bool>true</bool>
  </edit>
 </match>
 <match target="font">
  <edit mode="assign" name="hintstyle">
   <const>hintslight</const>
  </edit>
 </match>
 <match target="font">
  <edit mode="assign" name="antialias">
   <bool>true</bool>
  </edit>
 </match>
 <match target="font">
  <edit mode="assign" name="lcdfilter">
   <const>lcddefault</const>
  </edit>
 </match>
</fontconfig>

and it's started to work as expected.

@agiratech-reddysai Thank you for sharing your solution! I'm using AWS Elastic Beanstalk so that might complicate things, but I'll try to add this to my CI script :)

@Baawa, I have a solution for EBS also.

  1. Create a file with the above configuration and place it in the s3 bucket.
  2. Create a .ebextensions directory in your application directory like myApp/.ebextentions.
  3. Create a config file under .ebextensions directory, the file name like myapp.config.
  4. Update the myapp.config file with below content(change it as per your requirement)
Resources:
  AWSEBAutoScalingGroup:
    Metadata:
      AWS::CloudFormation::Authentication:
        S3Auth:
          type: "s3"
          buckets: ["bucket-name"]
          roleName:
            "Fn::GetOptionSetting":
              Namespace: "aws:autoscaling:launchconfiguration"
              OptionName: "IamInstanceProfile"
              DefaultValue: "aws-elasticbeanstalk-ec2-role"
files:
  "/etc/fonts/conf.d/51-local.conf":
    mode: "000755"
    owner: root
    group: root
    authentication: "S3Auth"
    source: https://s3.amazonaws.com/bucket-name/font-config.conf

Using above configuration, we are just overriding the default configuration.
/etc/fonts/conf.d/51-local.conf is a empty file in server side so, you are not going to loss any defaults.
If you want to install any dependent packages etc., go with this doc https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html

I hope, it will help to you. If you have any queries, feel free to ping.

Thanks a lot @agiratech-reddysai ! You saved my day !

Just post an another way to do it in EBS less complicated.
Simply add a new file in .ebextensions with this content:

files:
  "/etc/fonts/conf.d/51-local.conf":
    mode: "000755"
    owner: root
    group: root
    content: |
      <?xml version='1.0'?>
      <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
      <fontconfig>
      <match target="font">
        <edit mode="assign" name="rgba">
        <const>rgb</const>
        </edit>
      </match>
      <match target="font">
        <edit mode="assign" name="hinting">
        <bool>true</bool>
        </edit>
      </match>
      <match target="font">
        <edit mode="assign" name="hintstyle">
        <const>hintslight</const>
        </edit>
      </match>
      <match target="font">
        <edit mode="assign" name="antialias">
        <bool>true</bool>
        </edit>
      </match>
      <match target="font">
        <edit mode="assign" name="lcdfilter">
        <const>lcddefault</const>
        </edit>
      </match>
      </fontconfig>

@Zagonine I added to .ebextensions, how do I deploy the directory with the rest of the project?

In case somebody doesn't know how to include the .ebextensions in the deploy, when your build is complete, add the .ebextensions folder in the build folder, and then deploy.

build folder
----index.js
----project/*
----.ebextensions/*

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cmoulliard picture cmoulliard  路  3Comments

RodolfoSilva picture RodolfoSilva  路  3Comments

jimit-hothi picture jimit-hothi  路  4Comments

aminjoharinia picture aminjoharinia  路  4Comments

ZBilel picture ZBilel  路  4Comments