Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added pack.binlog
Binary file not shown.
Binary file not shown.
Binary file not shown.
4 changes: 2 additions & 2 deletions src/foundation/nuget/src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
<DebugBuildMessage>***** THIS IS A DEBUG BUILD - DO NOT PUBLISH *****%0d</DebugBuildMessage>

<!--<NuGetProjectUrl>https://docs.pdfsharp.net</NuGetProjectUrl>-->
<NuGetProjectUrl>https://docs.pdfsharp.net</NuGetProjectUrl>
<NuGetTags_PdfSharp>PDFsharp PDF creation</NuGetTags_PdfSharp>
<NuGetProjectUrl>https://github.com/ronenfe/PDFsharp</NuGetProjectUrl>
<NuGetTags_PdfSharp>PDFsharp PDF creation Hebrew</NuGetTags_PdfSharp>
<NuGetTags_MigraDoc>MigraDoc PDFsharp PDF Document Generation</NuGetTags_MigraDoc>
</PropertyGroup>

Expand Down
10 changes: 8 additions & 2 deletions src/foundation/nuget/src/PDFsharp.NuGet/PDFsharp.NuGet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@
<IsPackable>true</IsPackable>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<NuspecFile>$(MSBuildThisFileDirectory)$(MSBuildProjectName).nuspec</NuspecFile>
<NuGetId>PDFsharp</NuGetId>
<NuGetTitle>PDFsharp for Windows and Linux</NuGetTitle>
<!-- Override package identity for a custom package build -->
<PackageId>PdfSharpWithHebrewSupport</PackageId>
<Version>6.2.3-hebrew2</Version>
<Authors>ronenfe</Authors>
<Owners>ronenfe</Owners>
<RepositoryUrl>https://github.com/ronenfe/PDFsharp</RepositoryUrl>
<NuGetId>PdfSharpWithHebrewSupport</NuGetId>
<NuGetTitle>PDFsharp for Windows and Linux (custom Hebrew-support build)</NuGetTitle>
<NuGetDescription Condition=" '$(Configuration)'=='Debug' ">$(DebugBuildMessage)%0D$(NuGetDescription)</NuGetDescription>
<NuGetSummary>A .NET library for processing PDF.</NuGetSummary>
<NuGetTags>$(NuGetTags_PdfSharp)</NuGetTags>
Expand Down
62 changes: 62 additions & 0 deletions src/foundation/nuget/src/PDFsharp.NuGet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,65 @@ See [docs.pdfsharp.net](https://docs.pdfsharp.net) for details.
See [https://www.pdfsharp.com](https://www.pdfsharp.com) for professional support offers, premium technical advice, and contract work options.
Choose a support plan that suits your needs. We offer a variety of options, from small projects to large teams, with flexible response times.
Our team provides PDFsharp expert assistance, including implementation, optimization, and tailored solutions.
# PdfSharpWithHebrewSupport

PdfSharpWithHebrewSupport is a small, backwards-compatible customization of PDFsharp that adds a simple Hebrew‑script (RTL) preprocessing step before text is drawn or measured. It reorders RTL runs for Hebrew-script characters so Hebrew/Yiddish text renders in natural visual order without full shaping engines.

Version: 6.2.3-hebrew1
Targets: `net8.0`, `net9.0`, `net10.0`, `netstandard2.0`
License: MIT (based on PDFsharp)

## Features
- Preprocesses text passed to PDFsharp to reverse RTL runs for characters in:
- Hebrew block (U+0590..U+05FF)
- Hebrew presentation forms (U+FB1D..U+FB4F)
- Minimal change: uses the existing PDFsharp render pipeline and keeps API compatibility.
- Includes unit tests that verify mixed LTR/RTL run reordering.

## Why use this
PDFsharp does not include a full Unicode BiDi + shaping engine. For Hebrew and other Hebrew‑script languages, a simple run reordering is often enough. This package provides that preprocessing without adding heavy dependencies.

## Install
dotnet CLI:
```
dotnet add package PdfSharpWithHebrewSupport --version 6.2.3-hebrew1
```

PackageReference:

```xml
<PackageReference Include="PdfSharpWithHebrewSupport" Version="6.2.3-hebrew1" />
```

## Usage
Install the package and use PDFsharp as usual. The package hooks into the render pipeline and reorders RTL runs before text is measured or drawn.

Example — inspect preprocessed text:
```csharp
var renderEvents = new PdfSharp.Events.RenderEvents();
renderEvents.PrepareTextEvent += (s, e) =>
{
// e.Text has had Hebrew-script RTL runs reordered already
Console.WriteLine(e.Text);
};
```

If you need custom behavior, you can still subscribe to `PrepareTextEvent` and modify `e.Text`.

## Limitations
- This is a heuristic limited to Hebrew-script characters. It does NOT:
- Implement the full Unicode BiDi algorithm for every edge case.
- Provide contextual glyph shaping (Arabic, Persian, Urdu, Syriac, N’Ko, Adlam, etc.)
- For Arabic-family or other joining scripts you must use a shaping engine (e.g., HarfBuzz) and feed shaped glyphs into the renderer.

## Changelog (high level)
- 6.2.3-hebrew1: Added Hebrew-script RTL preprocessing and unit tests to reorder RTL runs prior to rendering.

## Source & Attribution
This package is built from PDFsharp sources (original authors: empira Software GmbH). This fork/custom build is published by the package author listed on nuget.org.

Original project: https://github.com/empira/PDFsharp
This fork: https://github.com/ronenfe/PDFsharp

## Support
Open issues on the package repository for bug reports or requests (RTL ranges, tests, or shaping integration guidance).
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>PdfSharpWithHebrewSupport</id>
<version>6.2.3-hebrew3</version>
<description>PDFsharp with added Hebrew-script RTL preprocessor for simple RTL languages (Hebrew, Yiddish). Built from PDFsharp sources with limited RTL preprocessing applied.</description>
<summary>PDFsharp customized build with Hebrew-script RTL run reordering.</summary>
<authors>ronenfe</authors>
<owners>ronenfe</owners>
<projectUrl>https://github.com/ronenfe/PDFsharp</projectUrl>
<license type="expression">MIT</license>
<icon>images\PDFsharp-128x128.png</icon>
<readme>README.md</readme>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Added Hebrew-script RTL preprocessing and unit tests (ReverseRtlTests).</releaseNotes>
<copyright>Copyright (c) 2005-2025 empira Software GmbH; modifications by ronenfe</copyright>
<tags>pdf pdfsharp hebrew rtl</tags>
<repository type="git" url="https://github.com/ronenfe/PDFsharp" branch="master" commit="" />
<title>PdfSharpWithHebrewSupport</title>
<dependencies>
<group targetFramework="net8.0">
<dependency id="Microsoft.Extensions.Logging" version="8.0.1" />
<dependency id="System.Security.Cryptography.Pkcs" version="8.0.1" />
</group>
<group targetFramework="net9.0">
<dependency id="Microsoft.Extensions.Logging" version="8.0.1" />
<dependency id="System.Security.Cryptography.Pkcs" version="8.0.1" />
</group>
<group targetFramework="net10.0">
<dependency id="Microsoft.Extensions.Logging" version="8.0.1" />
<dependency id="System.Security.Cryptography.Pkcs" version="8.0.1" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="Microsoft.Extensions.Logging" version="8.0.1" />
<dependency id="System.Security.Cryptography.Pkcs" version="8.0.1" />
</group>
</dependencies>
</metadata>
<files>
<file src="bin\$config$\net8.0\**\*.*" target="lib\net8.0\" exclude="**\*NuGet*"/>
<file src="bin\$config$\net9.0\**\*.*" target="lib\net9.0\" exclude="**\*NuGet*"/>
<file src="bin\$config$\net10.0\**\*.*" target="lib\net10.0\" exclude="**\*NuGet*"/>
<file src="bin\$config$\netstandard2.0\**\PDFsharp*.*" target="lib\netstandard2.0\" exclude="**\*NuGet*"/>
<file src="README.md" />
<file src="..\..\..\..\assets\pdfsharp\images\PDFsharp-128x128.png" target="images\" />
</files>
</package>
9 changes: 9 additions & 0 deletions src/foundation/nuget/src/PdfSharpWithHebrewSupport/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# PdfSharpWithHebrewSupport

PdfSharpWithHebrewSupport is a small, backwards-compatible customization of PDFsharp that adds a simple Hebrew?script (RTL) preprocessing step before text is drawn or measured. It reorders RTL runs for Hebrew-script characters so Hebrew/Yiddish text renders in natural visual order without full shaping engines.

Version: 6.2.3-hebrew3

License: MIT

For details see the original PDFsharp project: https://github.com/empira/PDFsharp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>PdfSharpWithHebrewSupport</id>
<version>6.2.3-hebrew1</version>
<description>PDFsharp with added Hebrew-script RTL preprocessor for simple RTL languages (Hebrew, Yiddish). Built from PDFsharp sources with limited RTL preprocessing applied.</description>
<summary>PDFsharp customized build with Hebrew-script RTL run reordering.</summary>
<authors>ronenfe</authors>
<owners>ronenfe</owners>
<projectUrl>https://github.com/ronenfe/PDFsharp</projectUrl>
<license type="expression">MIT</license>
<icon>images\PDFsharp-128x128.png</icon>
<readme>README.md</readme>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Added Hebrew-script RTL preprocessing and unit tests (ReverseRtlTests).</releaseNotes>
<copyright>Copyright (c) 2005-2025 empira Software GmbH; modifications by ronenfe</copyright>
<tags>pdf pdfsharp hebrew rtl</tags>
<repository type="git" url="https://github.com/ronenfe/PDFsharp" branch="master" commit="" />
<title>PdfSharpWithHebrewSupport</title>
<dependencies>
<group targetFramework="net8.0">
<dependency id="Microsoft.Extensions.Logging" version="$Logging_PackageVersion$" />
<dependency id="System.Security.Cryptography.Pkcs" version="$Cryptography_PackageVersion$" />
</group>
<group targetFramework="net9.0">
<dependency id="Microsoft.Extensions.Logging" version="$Logging_PackageVersion$" />
<dependency id="System.Security.Cryptography.Pkcs" version="$Cryptography_PackageVersion$" />
</group>
<group targetFramework="net10.0">
<dependency id="Microsoft.Extensions.Logging" version="$Logging_PackageVersion$" />
<dependency id="System.Security.Cryptography.Pkcs" version="$Cryptography_PackageVersion$" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="Microsoft.Extensions.Logging" version="$Logging_PackageVersion$" />
<dependency id="System.Security.Cryptography.Pkcs" version="$Cryptography_PackageVersion$" />
</group>
</dependencies>
</metadata>
<files>
<file src="bin\$config$\net8.0\**\*.*" target="lib\net8.0\" exclude="**\*NuGet*"/>
<file src="bin\$config$\net9.0\**\*.*" target="lib\net9.0\" exclude="**\*NuGet*"/>
<file src="bin\$config$\net10.0\**\*.*" target="lib\net10.0\" exclude="**\*NuGet*"/>
<file src="bin\$config$\netstandard2.0\**\PDFsharp*.*" target="lib\netstandard2.0\" exclude="**\*NuGet*"/>
<file src="README.md" />
<file src="..\..\..\..\assets\pdfsharp\images\PDFsharp-128x128.png" target="images\" />
</files>
</package>
9 changes: 9 additions & 0 deletions src/foundation/nugget/src/PdfSharpWithHebrewSupport/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# PdfSharpWithHebrewSupport

This package is a customized build of PDFsharp that adds a simple Hebrew-script RTL preprocessing step to reverse RTL runs for Hebrew-script languages (Hebrew, Yiddish) before rendering.

Version: 6.2.3-hebrew1

License: MIT

For details see the original PDFsharp project: https://github.com/empira/PDFsharp
66 changes: 66 additions & 0 deletions src/foundation/src/PDFsharp/src/PdfSharp/Events/RenderEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using PdfSharp.Drawing;
using PdfSharp.Fonts;
using PdfSharp.Pdf;
// using PdfSharp.Internal; // Not required - local preprocessor used to avoid cross-file reference issues

namespace PdfSharp.Events
{
Expand Down Expand Up @@ -78,6 +79,12 @@ public class RenderEvents
/// <param name="args">The PrepareTextEventArgs of the event.</param>
public void OnPrepareTextEvent(object sender, PrepareTextEventArgs args)
{
// Preprocess text (e.g. reverse RTL runs) before any event handlers are invoked.
if (args != null && !string.IsNullOrEmpty(args.Text))
{
args.Text = ReverseRtlRunsAndOrder(args.Text);
}

PrepareTextEvent?.Invoke(sender, args);
}

Expand All @@ -100,5 +107,64 @@ public void OnRenderTextEvent(object sender, RenderTextEventArgs args)
/// EventHandler for RenderTextEvent.
/// </summary>
public event RenderTextEventHandler? RenderTextEvent;

// Local text preprocessor to ensure the method is always available during build.
// Only detect Hebrew-script characters (covers Hebrew, Yiddish, Ladino written in Hebrew script,
// and presentation forms). These languages do not require complex shaping.
private static bool IsRtl(char c)
{
int code = c;
// Hebrew block and Hebrew presentation forms
return (code >= 0x0590 && code <= 0x05FF) || (code >= 0xFB1D && code <= 0xFB4F);
}

private static string ReverseString(string s)
{
var arr = s.ToCharArray();
System.Array.Reverse(arr);
return new string(arr);
}

private static string ReverseRtlRunsAndOrder(string text)
{
if (string.IsNullOrEmpty(text))
return text;

var runs = new System.Collections.Generic.List<string>();
var run = new System.Text.StringBuilder();
bool runIsHebrew = IsRtl(text[0]);

foreach (var c in text)
{
if (IsRtl(c) == runIsHebrew)
{
run.Append(c);
}
else
{
if (runIsHebrew)
runs.Add(ReverseString(run.ToString()));
else
runs.Add(run.ToString());

run.Clear();
run.Append(c);
runIsHebrew = IsRtl(c);
}
}

if (runIsHebrew)
runs.Add(ReverseString(run.ToString()));
else
runs.Add(run.ToString());

runs.Reverse();

var sb = new System.Text.StringBuilder();
foreach (var r in runs)
sb.Append(r);

return sb.ToString();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System.Text;
using System.Collections.Generic;

namespace PdfSharp.Internal
{
public static class TextPreprocessor
{
// Check if a char is Hebrew
private static bool IsHebrew(char c)
{
return c >= 0x0590 && c <= 0x05FF;
}

// Reverse each Hebrew run and reverse the order of runs
public static string ReverseHebrewRunsAndOrder(string text)
{
if (string.IsNullOrEmpty(text)) return text;

var runs = new List<string>();
var run = new StringBuilder();
bool runIsHebrew = IsHebrew(text[0]);

foreach (var c in text)
{
if (IsHebrew(c) == runIsHebrew)
{
run.Append(c);
}
else
{
// Flush previous run
if (runIsHebrew)
runs.Add(ReverseString(run.ToString()));
else
runs.Add(run.ToString());

run.Clear();
run.Append(c);
runIsHebrew = IsHebrew(c);
}
}

// Flush last run
if (runIsHebrew)
runs.Add(ReverseString(run.ToString()));
else
runs.Add(run.ToString());

// Reverse the order of runs for proper RTL layout
runs.Reverse();

var sb = new StringBuilder();
foreach (var r in runs)
{
sb.Append(r);
}

return sb.ToString();
}

private static string ReverseString(string s)
{
var arr = s.ToCharArray();
System.Array.Reverse(arr);
return new string(arr);
}
}
}
Loading