foliojs / pdfkit

A JavaScript PDF generation library for Node and the browser
http://pdfkit.org/
MIT License
9.86k stars 1.15k forks source link

Right-to-Left (RTL) support for Hebrew and Arabic #219

Open boustanihani opened 10 years ago

boustanihani commented 10 years ago

Please add Right-to-Left (RTL) support for languages like Hebrew and Arabic...

Something like:

doc.rtl(true);

doc.text('...', {rtl: true});
RMS21 commented 3 years ago

I was able to use Persian font like this, I used this link http://pdfkit.org/docs/text.html#fonts

doc.font("your language font here")
   .text("text");

in my case, I used a Persian font you can use the font you need

rodrigonzalz commented 3 years ago

How is this still not supported?

pubmikeb commented 3 years ago

Wow, 7 years and still no full RTL-support out of box?…

NadavRosenberg commented 3 years ago

So I tried pretty much everything but nothing works. I tried twitter-cldr-js like this:

const bidiText = TwitterCldr.Bidi.from_string('hello שלום world', { direction: "RTL" });
bidiText.reorder_visually();
return bidiText.toString();

but it gets rendered like this: world םולשhello. Trying icu-bidi results in:

PS C:\Users\...> npm i icu-bidi
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'salt@0.5.5',
npm WARN EBADENGINE   required: { node: '>=0.6.x <=0.11.x' },
npm WARN EBADENGINE   current: { node: 'v14.17.0', npm: '7.20.6' }
npm WARN EBADENGINE }
npm ERR! code 1
npm ERR! path ...
\icu-bidi
npm ERR! command failed
npm ERR! command ...
k-to-build
npm ERR! 'node-pre-gyp' is not recognized as an internal or external command,
npm ERR! operable program or batch file.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\...
ebug.log

The "solution":

const textWithDoubleSpaces = '!world ,שלום'.replace(' ', '  ');
return textWithDoubleSpaces.split(' ').reverse().join('  ');

will handle Hebrew but not combination of RTL and LTR (it's result with world! ,שלום). unicode-bidirectional give me the following error: image

Any working suggestions? 🙏

ghost commented 2 years ago

How come this superior library isn't supporting RTL languages?!! That's ridiculous:) Though the package has implemented dozens of great functionalities, it's utterly incapable of supporting RTL text. 7 years and still no support:| That's a complete shame for the core developers!

naizapp commented 2 years ago

For me I get all the arabic letters parsed correctly on { rtl: true }, but only the numbers are in reverse direction. So I wrote a function, pass the string into it before adding it to the text() function of PdfKit

Before

مروحة (002 - 001 م)

Code

revNumsInString = (s) => {
    var x = 0, keep = "", r = 0;
    s.replace(/(?:[\d])/gi, (i, q) => {keep += (r == q - 1 ? "" : "|") + i; r = q;});
    keep = keep.split("|").map(x => x.split("").reverse().join("")).join("");
    return s.replace(/(?:[\d])/gi, (i) =>keep[x++]);
}

Result

مروحة (200 - 100 م)
advance512 commented 2 years ago

@AmirABody Kinda wondering, why would say this is a superior library, then?

devongovett commented 2 years ago

It requires a higher level layout algorithm than what pdfkit offers, for example https://github.com/foliojs/textkit. React PDF uses it under the hood: https://github.com/diegomura/react-pdf. Not sure if it supports bidi yet but the architecture is there to support it. Personally I think pdfkit is too low level for advanced text layout, and that it belongs in a higher level library like React PDF or pdfmake, but I also don't work on pdfkit much anymore.

r4wand commented 10 months ago

still an issue 9 years later.

DirkSW commented 8 months ago

to my understanding there are 2 challenges:

  1. bi-directional text rendering (to support RTL and LTR and mixed) --> the words must be in the right order
  2. layout of the document
    • PDF with locale: e.g. ar (arabic) shall be rendered from right to left
    • PDF with locale: e.g. en (english) shall be rendered from left to right

regarding point 1. which was discussed above i think the solution might be to use from opentype specification ... https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist the feature rtla this works with pdfkit already since long time...

please test something like

var doc = new PDFDocument({}) const customFont = fs.readFileSync('./NotoSansArabic-Regular.ttf') doc.registerFont(Regular, customFont) doc.fontSize(15) doc.font(Regular).fillColor("black").text("مرحبا كيف حالك") doc.font(Regular).fillColor("black").text("مرحبا كيف حالك" , {features: ['rtla']}) doc.font(Regular).fillColor("black").text("مرحبا كيف حالك" , {features: ['']})

additionally you can mix arabic and non arabic texts and it shall render correctly

or am i wrong ?