Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process bidirectional text in conformance to Unicode standards #1096

Merged
merged 15 commits into from
Feb 9, 2024
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
## [2.7.8] - Not released yet
### Added
* support for `<path>` elements in SVG `<clipPath>` elements
* support for `bidirectional` text shaping - thanks to @andersonhc
* documentation on how to combine `fpdf2` with [mistletoe](https://pypi.org/project/kaleido/) in order to [generate PDF documents from Markdown (link)](https://py-pdf.github.io/fpdf2/CombineWithMistletoeoToUseMarkdown.html)
* tutorial in Dutch: [Handleiding](https://py-pdf.github.io/fpdf2/Tutorial-nl.md) - thanks to @Polderrider
* support for `Table` cells that span multiple rows via the `rowspan` attribute, which can be combined with `colspan` - thanks to @mjasperse
Expand Down
12 changes: 2 additions & 10 deletions docs/Unicode.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,9 @@ Many non-latin writing systems have complex ways to combine characters, ligature
To make sure those scripts to be rendered correctly, [text shaping](TextShaping.html) must be enabled with `.set_text_shaping(True)`.


### Right-to-Left & Arabic Script workaround ###
### Right-to-Left scripts ###

Arabic, Hebrew and other scripts written right-to-left (RTL) should work correctly when text is added that only contains one script at a time. As of release 2.7.6, more complete support for mixing RTL and LTR text is being worked on.
In the mean time, there is a temporary solution for Arabic and other RTL scripts using two additional libraries `python-bidi` and `arabic-reshaper`. It works for most languages; only a few (rare) Arabic characters aren't supported. Using it on other scripts (eg. when the input is unknown or mixed scripts) does not affect them:
```python
from arabic_reshaper import reshape
from bidi.algorithm import get_display

some_text = 'اَلْعَرَبِيَّةُכַּף סוֹפִית'
fixed_text = get_display(reshape(some_text))
```
When [text shaping](TextShaping.html) is enabled, `fpdf2` will apply the [Unicode Bidirectional Algorithm](https://www.unicode.org/reports/tr9/) to render correctly any text, including bidirectional (mix of right-to-left and left-to-right scripts).

## Example ##

Expand Down
763 changes: 763 additions & 0 deletions fpdf/bidi.py

Large diffs are not rendered by default.

15 changes: 7 additions & 8 deletions fpdf/fonts.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,17 +286,16 @@ def perform_harfbuzz_shaping(self, text, font_size_pt, text_shaping_parms):
buf = hb.Buffer()
buf.cluster_level = 1
buf.add_str("".join(text))
buf.guess_segment_properties()
features = text_shaping_parms["features"]
if (
text_shaping_parms["direction"]
or text_shaping_parms["script"]
or text_shaping_parms["language"]
):
buf.direction = text_shaping_parms["direction"]
if text_shaping_parms["fragment_direction"]:
buf.direction = (
"RTL" if text_shaping_parms["fragment_direction"] == "R" else "LTR"
)
if text_shaping_parms["script"]:
buf.script = text_shaping_parms["script"]
if text_shaping_parms["language"]:
buf.language = text_shaping_parms["language"]
else:
buf.guess_segment_properties()
hb.shape(self.hbfont, buf, features)
return buf.glyph_infos, buf.glyph_positions

Expand Down
Loading
Loading