Comments (9)
Thank you. I used NewFontResolver as an example to develop CustomFontResolver. The key difference is that NewFontResolver contains the predefined list of fonts, while CustomFontResolver can load any existing font.
from pdfsharp.
- Getting a warning when building with the "Arial" font called, possibly all fonts.
info: PdfSharp.Snippets.Font.FailsafeFontResolver[0] 'Arial' bold was substituted by a SegoeWP font.
You use a FontResolver that uses SegoeWP for every unknown font (including Arial). It's a feature, not a bug. If you want Arial, then use a font resolver that supports Arial.
- Vertical spacing of fonts doesn't seem to be correct. Spacing slightly favors the bottom.
Looks correct. Fonts need room for dots and accents above the letters ("ÄÖÜÁÀ").
There also is gfx.MeasureString
.
See also:
http://pdfsharp.net/wiki/TextLayout-sample.ashx
https://github.com/empira/PDFsharp/blob/master/src/foundation/src/PDFsharp/src/PdfSharp/Drawing.Layout/XTextFormatter.cs
from pdfsharp.
Thanks for the detailed explanation. The "Arial" font issue was fixed by implementing IFontResolver. Don't generally use fonts like that, so didn't think about it. Makes sense though. That said, "Arial" doesn't seem to leave as much spacing. At any rate, thank you!
from pdfsharp.
Hello,
Thank you for your work of porting the libs to .NET6.
Could you provide an example how to "use a font resolver that supports Arial" ?
Even the example that uses Arial actually creates a document with the Segoe font. I've tested the example on Windows 11, Arial is installed.
FailsafeFontResolver also tries to load the specified font before Segoe. Despite that, Arial was not loaded.
from pdfsharp.
Could you provide an example how to "use a font resolver that supports Arial"?
A good place to ask this question would be the PDFsharp support forum.
There you can find the EZFontResolver sample:
https://forum.pdfsharp.net/viewtopic.php?f=8&t=3244
And this IFontResolver sample:
https://forum.pdfsharp.net/viewtopic.php?f=8&t=3073
In the PDFsharp source code you can find this sample:
https://github.com/empira/PDFsharp/blob/master/src/foundation/src/shared/src/PdfSharp.Snippets/Font/fontresolving/ExoticFontsFontResolver.cs
https://github.com/empira/PDFsharp/blob/master/src/foundation/src/shared/src/PdfSharp.Snippets/Font/fontresolving/ExoticFontsDataHelper.cs
https://github.com/empira/PDFsharp/blob/master/src/foundation/src/shared/src/PdfSharp.Snippets/Font/fontresolving/ExoticFontResolverSnippet.cs
I admit that these samples do not use "Arial", but replacing "ubuntu" by "Arial" is left as an exercise to the reader.
from pdfsharp.
Thank you.
If anyone is interested, topic is continued here
from pdfsharp.
Just for information, this and this links describe the approach for solving the similar font problem, used by ClosedXML library that generates Excel workbooks.
from pdfsharp.
This font resolver might be useful to someone:
#nullable disable
using PdfSharp.Fonts;
using PdfSharp.Snippets.Font;
using PdfSharp.WPFonts;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace PdfSharpTest
{
public class CustomFontResolver : IFontResolver
{
/// <summary>
/// Identifies a font.
/// </summary>
private readonly record struct FontKey(
string FamilyName,
bool IsBold,
bool IsItalic)
{
public string GetFaceName() =>
(string.IsNullOrEmpty(FamilyName) ? "Empty" : FamilyName) +
(IsBold ? "-Bold" : "") +
(IsItalic ? "-Italic" : "");
};
/// <summary>
/// Represents information associated with a font.
/// </summary>
private class FontMeta
{
public string FileName { get; init; }
}
/// <summary>
/// Specifies how to search for the font.
/// </summary>
private static readonly EnumerationOptions FontSearchOptions = new()
{
RecurseSubdirectories = true,
MatchCasing = MatchCasing.CaseInsensitive,
AttributesToSkip = 0,
IgnoreInaccessible = true
};
private readonly SegoeWpFontResolver fallbackFontResolver;
private readonly Dictionary<string, FontMeta> fontsByFace;
/// <summary>
/// Initializes a new instance of the class.
/// </summary>
public CustomFontResolver()
{
fallbackFontResolver = new SegoeWpFontResolver();
fontsByFace = new Dictionary<string, FontMeta>();
}
/// <summary>
/// Finds the specified font in the file system.
/// </summary>
private static FontResolverInfo FindFont(FontKey fontKey, out string fileName)
{
if (string.IsNullOrEmpty(fontKey.FamilyName))
{
fileName = "";
return null;
}
try
{
ICollection<string> fontDirectories = GetFontDirectories();
ICollection<string> desiredNames = GetDesiredNames(fontKey);
ICollection<string> candidateNames = GetCandidateNames(fontKey);
FileInfo candidateFileInfo = null;
foreach (string fontDirectory in fontDirectories)
{
if (!Directory.Exists(fontDirectory))
continue;
foreach (FileInfo fileInfo in new DirectoryInfo(fontDirectory)
.EnumerateFiles(fontKey.FamilyName + "*.ttf", FontSearchOptions))
{
if (desiredNames.Any(name => name.Equals(fileInfo.Name, StringComparison.OrdinalIgnoreCase)))
{
fileName = fileInfo.FullName;
return new FontResolverInfo(fontKey.GetFaceName(), false, false);
}
if (candidateFileInfo == null &&
candidateNames.Any(name => name.Equals(fileInfo.Name, StringComparison.OrdinalIgnoreCase)))
{
candidateFileInfo = fileInfo;
}
}
}
if (candidateFileInfo != null)
{
fileName = candidateFileInfo.FullName;
return new FontResolverInfo(fontKey.GetFaceName(), fontKey.IsBold, fontKey.IsItalic);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
fileName = "";
return null;
}
/// <summary>
/// Gets the font directories depending on the OS.
/// </summary>
private static ICollection<string> GetFontDirectories()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return new string[]
{
@"C:\Windows\Fonts\",
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
@"Microsoft\Windows\Fonts")
};
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return new string[]
{
"/usr/share/fonts/truetype/"
};
}
else
{
return Array.Empty<string>();
}
}
/// <summary>
/// Gets desired font file names.
/// </summary>
private static ICollection<string> GetDesiredNames(FontKey fontKey)
{
if (fontKey.IsBold && fontKey.IsItalic)
{
return new string[]
{
fontKey.FamilyName + "bi.ttf",
fontKey.FamilyName + "-BoldItalic.ttf",
fontKey.FamilyName + "-BoldOblique.ttf"
};
}
else if (fontKey.IsBold)
{
return new string[]
{
fontKey.FamilyName + "bd.ttf",
fontKey.FamilyName + "-Bold.ttf"
};
}
else if (fontKey.IsItalic)
{
return new string[]
{
fontKey.FamilyName + "i.ttf",
fontKey.FamilyName + "-Italic.ttf",
fontKey.FamilyName + "-Oblique.ttf"
};
}
else
{
return new string[]
{
fontKey.FamilyName + ".ttf",
fontKey.FamilyName + "-Regular.ttf"
};
}
}
/// <summary>
/// Gets possible font file names.
/// </summary>
private static ICollection<string> GetCandidateNames(FontKey fontKey)
{
if (fontKey.IsBold || fontKey.IsItalic)
{
return new string[]
{
fontKey.FamilyName + ".ttf",
fontKey.FamilyName + "-Regular.ttf"
};
}
else
{
return Array.Empty<string>();
}
}
/// <summary>
/// Converts specified information about a required typeface into a specific font.
/// </summary>
/// <remarks>
/// PDFsharp calls ResolveTypeface only once for each unique combination of familyName, isBold, and isItalic.
/// </remarks>
public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
{
FontKey fontKey = new(familyName, isBold, isItalic);
FontResolverInfo resolverInfo =
FindFont(fontKey, out string fileName) ??
fallbackFontResolver.ResolveTypeface(isBold
? SegoeWpFontResolver.FamilyNames.SegoeWPBold
: SegoeWpFontResolver.FamilyNames.SegoeWP,
false, isItalic) ??
new FontResolverInfo(fontKey.GetFaceName(), isBold, isItalic);
fontsByFace[resolverInfo.FaceName] = new FontMeta { FileName = fileName };
return resolverInfo;
}
/// <summary>
/// Gets the bytes of a physical font with specified face name.
/// </summary>
/// <remarks>
/// A face name previously retrieved by ResolveTypeface.
/// PDFsharp never calls GetFont twice with the same face name.
/// </remarks>
public byte[] GetFont(string faceName)
{
try
{
if (fontsByFace.TryGetValue(faceName, out FontMeta fontMeta))
{
byte[] font = string.IsNullOrEmpty(fontMeta.FileName)
? fallbackFontResolver.GetFont(faceName)
: File.ReadAllBytes(fontMeta.FileName);
if (font != null)
return font;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
return FontDataHelper.SegoeWP;
}
}
}
from pdfsharp.
This font resolver might be useful to someone:
The NewFontResolver
that comes with PDFsharp might be useful, too. It was tested with Windows and Linux, but not with MacOS.
See:
src/foundation/src/shared/src/PdfSharp.Snippets/Font/fontresolving/NewFontResolver.cs
The name might change with future releases of PDFsharp.
from pdfsharp.
Related Issues (20)
- How to convert Byte[] to XImage in PdfSharp HOT 3
- DrawMatrixCode seems to be returns null always in .Net8 HOT 1
- Add initialization of XGraphicsPath from its native counterpart HOT 2
- How to build PDF Sharp with Strong name? HOT 3
- AddImage from Stream HOT 1
- Performance improvements HOT 2
- IndexOutOfRangeException when displaying a PNG HOT 3
- Exception when displaying some JPG with Core build HOT 3
- Colors from a PdfTextField are not stored HOT 2
- Rendering a document throws an `InvalidOperationException` if a paragraph gets close to the bottom of a page HOT 3
- IVS support HOT 1
- Invalid Surrogate Pair Check HOT 5
- Cannot open pdf file when SecuritySettings.OwnerPassword is set HOT 4
- MemoryStream's internal buffer cannot be accessed. HOT 1
- 6.1.0-preview-1 errors when opening file in framework 4.8 HOT 2
- The DrawImage Function Fails During Resizing HOT 1
- Allow table rows/cells to break across pages
- Initializing Migradoc DefaultPageSetup throws when CurrentCulture is a neutral culture HOT 2
- After pasting the image with a transparent background color into a PDF, it becomes a black background HOT 1
- Can't retrieve stream length error - in old version? HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pdfsharp.