Search code examples
htmlcssfontsjspdf

Is there a way to specify font-stretch to custom font in jsPDF?


I am using jsPDF to generate PDF and I need to load a custom font with multiple font-stretch values (normal, condensed and expanded) from a Font Family I defined which supports it.

However, I don't see how I can specify that font-stretch property when loading the font.

This is how I declare my Font Family in CSS

@font-face {
  font-family: Bahnschrift;
  src: url("~@/assets/fonts/Bahnschrift/bahnschrift-normal.ttf") format("truetype");
  font-stretch: normal;
}

@font-face {
  font-family: Bahnschrift;
  src: url("~@/assets/fonts/Bahnschrift/bahnschrift-condensed.ttf") format("truetype");
  font-stretch: condensed;
}

@font-face {
  font-family: Bahnschrift;
  src: url("~@/assets/fonts/Bahnschrift/bahnschrift-expanded.ttf") format("truetype");
  font-stretch: expanded;
}

This is how I load the three custom fonts into jsPDF

Here, in line 5 is where I think I should declare the condensed / expanded variations, but the other possible values I am aware of are Italic, Bold and their combinations

import { jsPDF } from "jspdf"
var font = "<base64 font file>"
var callAddFont = function () {
this.addFileToVFS('Bahnschrift-normal.ttf', font);
this.addFont('Bahnschrift-normal.ttf', 'Bahnschrift', 'normal');
};
jsPDF.API.events.push(['addFonts', callAddFont])
import { jsPDF } from "jspdf"
var font = "<base64 font file>"
var callAddFont = function () {
this.addFileToVFS('Bahnschrift-condensed.ttf', font);
this.addFont('Bahnschrift-condensed.ttf', 'Bahnschrift', 'normal');   // I think I should be able to set condensed here
};
jsPDF.API.events.push(['addFonts', callAddFont])
import { jsPDF } from "jspdf"
var font = "<base64 font file>"
var callAddFont = function () {
this.addFileToVFS('Bahnschrift-expanded.ttf', font);
this.addFont('Bahnschrift-expanded.ttf', 'Bahnschrift', 'normal');   // I think I should be able to set expanded here
};
jsPDF.API.events.push(['addFonts', callAddFont])

Finally, I use the font like this

const font = `normal normal 400 16px Bahnschrift`;
await document.fonts.load(font);
pdf.font = font;
const font = `condensed normal 400 16px Bahnschrift`;
await document.fonts.load(font);
pdf.font = font;
const font = `expanded normal 400 16px Bahnschrift`;
await document.fonts.load(font);
pdf.font = font;

Could anyone help me out here please?


Solution

  • Finally I found a solution and I am posting it here in case someone else is struggling with this.

    I declared different font families for each variation, so there is no need to specify the variation as a property, but just use the corresponding font family.

    My code looks like this now

    Here are my font families declarations

    @font-face {
      font-family: Bahnschrift-normal;
      src: url("~@/assets/fonts/Bahnschrift/bahnschrift-normal.ttf") format("truetype");
    }
    
    @font-face {
      font-family: Bahnschrift-condensed;
      src: url("~@/assets/fonts/Bahnschrift/bahnschrift-condensed.ttf") format("truetype");
    }
    
    @font-face {
      font-family: Bahnschrift-expanded;
      src: url("~@/assets/fonts/Bahnschrift/bahnschrift-expanded.ttf") format("truetype");
    }
    

    Then I load fonts into jsPDF like this

    import { jsPDF } from "jspdf"
    var font = "<base64 font file>"
    var callAddFont = function () {
    this.addFileToVFS('Bahnschrift-normal.ttf', font);
    this.addFont('Bahnschrift-normal.ttf', 'Bahnschrift-normal', 'normal');
    };
    jsPDF.API.events.push(['addFonts', callAddFont])
    
    import { jsPDF } from "jspdf"
    var font = "<base64 font file>"
    var callAddFont = function () {
    this.addFileToVFS('Bahnschrift-condensed.ttf', font);
    this.addFont('Bahnschrift-condensed.ttf', 'Bahnschrift-condensed', 'normal');
    };
    jsPDF.API.events.push(['addFonts', callAddFont])
    
    import { jsPDF } from "jspdf"
    var font = "<base64 font file>"
    var callAddFont = function () {
    this.addFileToVFS('Bahnschrift-expanded.ttf', font);
    this.addFont('Bahnschrift-expanded.ttf', 'Bahnschrift-expanded', 'normal');
    };
    jsPDF.API.events.push(['addFonts', callAddFont])
    

    And then I use the fonts like this

    const font = `normal normal 400 16px Bahnschrift-normal`;
    await document.fonts.load(font);
    pdf.font = font;
    
    const font = `normal normal 400 16px Bahnschrift-condensed`;
    await document.fonts.load(font);
    pdf.font = font;
    
    const font = `normal normal 400 16px Bahnschrift-expanded`;
    await document.fonts.load(font);
    pdf.font = font;
    

    As a side note, do not use numbers in font family names, jsPDF does not load them as expected. I encountered this problem in my troubleshooting trip and spent a lot of time with it.

    I hope this helps someone.