2

I use my custom Persian font in jsPDF, but characters for this font show me wrong.

I hear

The IranNastaliq font uses the 'cswh' feature for such ligatures. 'cswh' is default-off according to the OpenType spec. The font should use 'calt' instead. It's unfortunate

So should I set 'cswh' in the jsPDF library? How can I do that in jsPDF code?

https://evenz.ir/pdf/js/

var doc = new jsPDF();
doc.addFont("test/reference/fonts/IranNastaliq-Web.ttf", "IranNastaliq", "normal");

doc.setFont("IranNastaliq"); // Set font
doc.setFontSize(150);

var persianText = "نگار شکار";

doc.text(persianText, 10, 60);

Enter image description here

3
  • 1
    1 - I don’t know if it’s possible with jsPDF or not, 2 - but I can suggest another solution, you can create an image of the word : img.src = 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg"><foreignObject width="' + canvas.width + '" height="' + canvas.height + '">' + parseandserialize('نگار') + '</foreignObject></svg>'); Commented 15 hours ago
  • In addition, IranNastaliq is a Persian font. Commented 14 hours ago
  • thanks but i need to use jsPDF to generate pdf for my software, svg will not help . Commented 12 hours ago

2 Answers 2

0
  1. Pre-shape text before passing to jsPDF

    • Use a library like PersianTools or [arabic-persian shaping libraries] to convert text into glyphs with correct contextual forms.

    • Example: run text through a shaping engine (like HarfBuzz via Node or opentype.js) → get shaped glyphs → feed them into jsPDF.

    js

    import { jsPDF } from "jspdf";
    import arabicReshaper from "arabic-persian-reshaper"; // example library
    
    var doc = new jsPDF();
    doc.addFont("IranNastaliq-Web.ttf", "IranNastaliq", "normal");
    doc.setFont("IranNastaliq");
    doc.setFontSize(150);
    
    var persianText = "نگار شکار";
    var shapedText = arabicReshaper(persianText); // converts to correct glyph sequence
    
    doc.text(shapedText, 10, 60);
    
    

    This way, jsPDF just draws glyphs — the shaping is already done.

  2. Convert text to SVG/Path before embedding

    • Use opentype.js to render the Persian text into vector paths.

    • Then add the path to jsPDF instead of raw text.

    js

    import { jsPDF } from "jspdf";
    import opentype from "opentype.js";
    
    opentype.load("IranNastaliq-Web.ttf", function(err, font) {
      if (err) throw err;
      var doc = new jsPDF();
      var path = font.getPath("نگار شکار", 10, 60, 150);
      doc.addSVG(path.toSVG(), 0, 0, 200, 200);
      doc.save("persian.pdf");
    });
    
    

    This bypasses jsPDF’s text rendering and ensures ligatures are preserved.

  3. Fallback: render text as image

    • If shaping libraries are too heavy, render the Persian text in HTML canvas with correct font, then export as image and insert into jsPDF.

    • Less elegant, but guaranteed correct appearance.

don't do this:

  • You cannot “set cswh” in jsPDF directly — it doesn’t expose OpenType feature toggles.

  • You cannot rely on jsPDF alone for complex script shaping.

Sign up to request clarification or add additional context in comments.

1 Comment

// Source - stackoverflow.com/a/79833432 // Posted by Ayoub Gmati // Retrieved 2025-11-30, License - CC BY-SA 4.0 import { jsPDF } from "jspdf"; import opentype from "opentype.js"; opentype.load("IranNastaliq-Web.ttf", function(err, font) { if (err) throw err; var doc = new jsPDF(); var path = font.getPath("نگار شکار", 10, 60, 150); doc.addSVG(path.toSVG(), 0, 0, 200, 200); doc.save("persian.pdf"); });
-1
  1. Pre-shape text before passing to jsPDF

    • Use a library like PersianTools or [arabic-persian shaping libraries] to convert text into glyphs with correct contextual forms.

    • Example: run text through a shaping engine (like HarfBuzz via Node or opentype.js) → get shaped glyphs → feed them into jsPDF.

    js

    javascriptimport { jsPDF } from "jspdf";
    import arabicReshaper from "arabic-persian-reshaper"; // example library
    
    var doc = new jsPDF();
    doc.addFont("IranNastaliq-Web.ttf", "IranNastaliq", "normal");
    doc.setFont("IranNastaliq");
    doc.setFontSize(150);
    
    var persianText = "نگار شکار";
    var shapedText = arabicReshaper(persianText); // converts to correct glyph sequence
    
    doc.text(shapedText, 10, 60);
    
    
    

    This way, jsPDF just draws glyphs — the shaping is already done.

  2. Convert text to SVG/Path before embedding

    • Use opentype.js to render the Persian text into vector paths.

    • Then add the path to jsPDF instead of raw text.

    js

    javascriptimport { jsPDF } from "jspdf";
    import opentype from "opentype.js";
    
    opentype.load("IranNastaliq-Web.ttf", function(err, font) {
      if (err) throw err;
      var doc = new jsPDF();
      var path = font.getPath("نگار شکار", 10, 60, 150);
      doc.addSVG(path.toSVG(), 0, 0, 200, 200);
      doc.save("persian.pdf");
    });
    
    
    

    This bypasses jsPDF’s text rendering and ensures ligatures are preserved.

  3. Fallback: render text as image

    • If shaping libraries are too heavy, render the Persian text in HTML canvas with correct font, then export as image and insert into jsPDF.

    • Less elegant, but guaranteed correct appearance.

don't do this:

  • You cannot “set cswh” in jsPDF directly — it doesn’t expose OpenType feature toggles.

  • You cannot rely on jsPDF alone for complex script shaping.

New contributor
DIWAKAR SUMBRIA is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.