在 PdfSharp 中使用私有字体
在 PdfSharp 中使用私有字体
在 PdfSharp 1.5 中提供了在 Web 服务器上使用私有字体的示例,见:http://www.pdfsharp.net/wiki/(X(1)S(mg0wojiafv2wdqhklvachrti))/FontResolver-sample.ashx。
注意:FontResolver 是一个全局对象,应用于 PdfSharp 库的所有消费者。也被 MigraDoc 库用于创建 PDF 文档。
1. 私有字体
JetBrain 是一套适合程序员使用的字体,我从 https://www.jetbrains.com/lp/mono/ 下载了它,下载下来的文件是一个 Zip 包,解压之后,里面是多个 TrueType 格式的字体文件,文件名的氛围两部分组成,以中划线分隔,前面都是 JetBrainsMono,后面是字体的风格。例如,对于普通的字体来说,就是 JetBrainsMono-Regular.ttf 这个字体文件。粗体对应的字体文件是 JetBrainsMono-Bold.ttf,而斜体对应的字体文件是 JetBrains-Mono-Italic.ttf。
我还下载了一个微软雅慧的 TrueType 字体文件。名称为 YaHei.ttf。通过它来使用中文字体。
字体族和字体
这里有两个概念:字体家族 Font Family 和 字体 Font Face。
Font Family 是一套字体的名称,例如,对于 JetBrains Mono 字体家族来说,这就是一套字体的名称。而一套字体内部,有包括了普通字体,粗体,斜体等等多种具体的字体。这些最终的字体称为 Font Face。
当使用字体的时候,我们需要提供字体家族的名称,具体对应的样式,它们组合起来,我们可以得到实际使用的字体文件,最终得到 TrueType 字体数据。
下面的示例将展示如何使用这两种字体。
2. IFontResolver 接口
PdfSharp 通过 IFontResolver 接口定义了如何获取字体。该接口定义如下。见:https://github.com/empira/PDFsharp/blob/master/src/PdfSharp/Fonts/IFontResolver.cs
namespace PdfSharp.Fonts
{
/// <summary>
/// Provides functionality that converts a requested typeface into a physical font.
/// </summary>
public interface IFontResolver
{
/// <summary>
/// Converts specified information about a required typeface into a specific font.
/// </summary>
/// <param name="familyName">Name of the font family.</param>
/// <param name="isBold">Set to <c>true</c> when a bold fontface is required.</param>
/// <param name="isItalic">Set to <c>true</c> when an italic fontface is required.</param>
/// <returns>Information about the physical font, or null if the request cannot be satisfied.</returns>
FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic);
//FontResolverInfo ResolveTypeface(Typeface); TODO in PDFsharp 2.0
/// <summary>
/// Gets the bytes of a physical font with specified face name.
/// </summary>
/// <param name="faceName">A face name previously retrieved by ResolveTypeface.</param>
byte[] GetFont(string faceName);
}
}
接口定义了两个方法。
2.1 ResolveTypeface
获得字体信息。将需要使用的特定字体信息表示为一个 FontResolverInfo 对象。需要提供字体家族名称,是否粗体,是否泄题。
对于字体来说,我们需要提供一个字体族的名称来代表一类字体,在内部,我们需要针对每种具体的字形,定义出针对每种字形的字符串名称。通过字符串常量定义出来。
/// <summary>
/// The font family names that can be used in the constructor of XFont.
/// Used in the first parameter of ResolveTypeface.
/// Family names are given in lower case because the implementation of JetBrainsMonoFontResolver ignores case.
/// </summary>
static class FamilyNames
{
public const string JetBrainsMonoRegular = "JetBrains Mono";
public const string HansRegular = "Hans";
}
内部在实际使用字体的时候,使用的是字形名称。对于字形信息,定义如下的字符串常量。
/// <summary>
/// The internal names that uniquely identify a font's type faces (i.e. a physical font file).
/// Used in the first parameter of the FontResolverInfo constructor.
/// </summary>
static class FaceNames
{
public const string JetBrainsMonoRegular = "JetBrainsMono-Regular";
public const string JetBrainsMonoBold = "JetBrainsMono-Bold";
public const string JetBrainsMonoBoldItalic = "JetBrainsMono-Bold-Italic";
public const string HansRegular = "SourceHanSerif";
}
在 ResolveTypeface() 方法内部,需要实现将字体族名称和样式的组合对应到实际的字形映射。
针对对应的字体族名称,以及所希望使用的字体样式,来找到对应的字形名称。
public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
{
// Note: PDFsharp calls ResolveTypeface only once for each unique combination
// of familyName, isBold, and isItalic.
string lowerFamilyName = familyName.ToLowerInvariant();
// Looking for a JetBrains Mono font?
if (lowerFamilyName.StartsWith("jetBrains mono") || lowerFamilyName.StartsWith("hans"))
{
// Bold simulation is not recommended, but used here for demonstration.
bool simulateBold = false;
// Since Segoe WP typefaces do not contain any italic font
// always simulate italic if it is requested.
bool simulateItalic = false;
string faceName;
// In this sample family names are case sensitive. You can relax this in your own implementation
// and make them case insensitive.
switch (familyName)
{
case FamilyNames.JetBrainsMonoRegular:
faceName = FaceNames.JetBrainsMonoRegular;
break;
case FamilyNames.HansRegular:
faceName = FaceNames.HansRegular;
break;
default:
Debug.Assert(false, "Unknown JetBrains Mono font: " + lowerFamilyName);
goto case FamilyNames.JetBrainsMonoRegular; // Alternatively throw an exception in this case.
}
// Tell the caller the effective typeface name and whether bold or italic should be simulated.
return new FontResolverInfo(faceName, simulateBold, simulateItalic);
}
// Return null means that the typeface cannot be resolved and PDFsharp stops working.
// Alternatively forward call to PlatformFontResolver.
return PlatformFontResolver.ResolveTypeface(familyName, isBold, isItalic);
}
使用系统字体
如果没有提供对应的私有字体,使用平台所提供的字体。
return PlatformFontResolver.ResolveTypeface(familyName, isBold, isItalic);
2.2 GetFont()
根据字符串格式的字体名称,获得 TrueType 字体数据。注意这里使用的是字体名称而不是字体族名称。实际返回的是 TrueType 字体数据。
public byte[] GetFont(string faceName)
{
// Note: PDFsharp never calls GetFont twice with the same face name.
// Return the bytes of a font.
switch (faceName)
{
case FaceNames.JetBrainsMonoBold:
return FontDataHelper.JetBrainsMonoBold;
case FaceNames.JetBrainsMonoRegular:
return FontDataHelper.JetBrainsMonoRegular;
case FaceNames.HansRegular:
return FontDataHelper.HanSerif;
}
// PDFsharp never calls GetFont with a face name that was not returned by ResolveTypeface.
throw new ArgumentException(String.Format("Invalid typeface name '{0}'", faceName));
}
3. 实现
using PdfSharp.Fonts;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/*
* An sample at: https://github.com/empira/PDFsharp-samples/blob/master/samples/core/FontResolver/SegoeWpFontResolver.cs
*/
namespace pdfSharpStarter.PrivateFonts
{
public class JetBrainsMonoFontResolver : IFontResolver
{
/// <summary>
/// The font family names that can be used in the constructor of XFont.
/// Used in the first parameter of ResolveTypeface.
/// Family names are given in lower case because the implementation of JetBrainsMonoFontResolver ignores case.
/// </summary>
static class FamilyNames
{
public const string JetBrainsMonoRegular = "JetBrains Mono";
public const string HansRegular = "Hans";
}
/// <summary>
/// The internal names that uniquely identify a font's type faces (i.e. a physical font file).
/// Used in the first parameter of the FontResolverInfo constructor.
/// </summary>
static class FaceNames
{
public const string JetBrainsMonoRegular = "JetBrainsMono-Regular";
public const string JetBrainsMonoBold = "JetBrainsMono-Bold";
public const string JetBrainsMonoBoldItalic = "JetBrainsMono-Bold-Italic";
public const string HansRegular = "SourceHanSerif";
}
/// <summary>
/// Converts specified information about a required typeface into a specific font.
/// </summary>
/// <param name="familyName">Name of the font family.</param>
/// <param name="isBold">Set to <c>true</c> when a bold fontface is required.</param>
/// <param name="isItalic">Set to <c>true</c> when an italic fontface is required.</param>
/// <returns>
/// Information about the physical font, or null if the request cannot be satisfied.
/// </returns>
public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
{
// Note: PDFsharp calls ResolveTypeface only once for each unique combination
// of familyName, isBold, and isItalic.
string lowerFamilyName = familyName.ToLowerInvariant();
// Looking for a JetBrains Mono font?
if (lowerFamilyName.StartsWith("jetBrains mono") || lowerFamilyName.StartsWith("hans"))
{
// Bold simulation is not recommended, but used here for demonstration.
bool simulateBold = false;
// Since Segoe WP typefaces do not contain any italic font
// always simulate italic if it is requested.
bool simulateItalic = false;
string faceName;
// In this sample family names are case sensitive. You can relax this in your own implementation
// and make them case insensitive.
switch (familyName)
{
case FamilyNames.JetBrainsMonoRegular:
faceName = FaceNames.JetBrainsMonoRegular;
break;
case FamilyNames.HansRegular:
faceName = FaceNames.HansRegular;
break;
default:
Debug.Assert(false, "Unknown JetBrains Mono font: " + lowerFamilyName);
goto case FamilyNames.JetBrainsMonoRegular; // Alternatively throw an exception in this case.
}
// Tell the caller the effective typeface name and whether bold or italic should be simulated.
return new FontResolverInfo(faceName, simulateBold, simulateItalic);
}
// Return null means that the typeface cannot be resolved and PDFsharp stops working.
// Alternatively forward call to PlatformFontResolver.
return PlatformFontResolver.ResolveTypeface(familyName, isBold, isItalic);
}
public byte[] GetFont(string faceName)
{
// Note: PDFsharp never calls GetFont twice with the same face name.
// Return the bytes of a font.
switch (faceName)
{
case FaceNames.JetBrainsMonoBold:
return FontDataHelper.JetBrainsMonoBold;
case FaceNames.JetBrainsMonoRegular:
return FontDataHelper.JetBrainsMonoRegular;
case FaceNames.HansRegular:
return FontDataHelper.HanSerif;
}
// PDFsharp never calls GetFont with a face name that was not returned by ResolveTypeface.
throw new ArgumentException(String.Format("Invalid typeface name '{0}'", faceName));
}
}
}
辅助类
这里使用了嵌入到程序集内的资源。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace pdfSharpStarter.PrivateFonts
{
/*
* pdfSharpStarter.Resources.ttf.JetBrainsMono-Bold.ttf
* pdfSharpStarter.Resources.ttf.JetBrainsMono-Light.ttf
* pdfSharpStarter.Resources.ttf.JetBrainsMono-Regular.ttf
*/
public static class FontDataHelper
{
public static byte[] JetBrainsMonoRegular
{
get { return LoadFontData("pdfSharpStarter.Resources.ttf.JetBrainsMono-Regular.ttf"); }
}
public static byte[] JetBrainsMonoBold
{
get { return LoadFontData("pdfSharpStarter.Resources.ttf.JetBrainsMono-Bold.ttf"); }
}
public static byte[] HanSerif
{
get { return LoadFontData("pdfSharpStarter.Resources.YaHei.ttf"); }
}
static byte[] LoadFontData(string name)
{
Assembly assembly = typeof(FontDataHelper).Assembly;
using (Stream stream = assembly.GetManifestResourceStream(name))
{
if (stream == null)
throw new ArgumentException("No resource with name " + name);
var count = (int)stream.Length;
var data = new byte[count];
stream.Read(data, 0, count);
return data;
}
}
}
}
4. 使用私有字体
注册
// REgister font resolver before start using PDFSharp
PdfSharp.Fonts.GlobalFontSettings.FontResolver
= new PrivateFonts.JetBrainsMonoFontResolver();
使用字体
下面创建了 2 种字体进行绘制。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace pdfSharpStarter.PrivateFonts
{
/*
* REgister font resolver before start using PDFSharp
*
* PdfSharp.Fonts.GlobalFontSettings.FontResolver
* = new PrivateFonts.JetBrainsMonoFontResolver();
*/
public class PrivateFontsSample
{
public static void Demo()
{
// Create a new PDF document.
var document = new PdfSharp.Pdf.PdfDocument();
document.Info.Title = "Font Resolver Sample";
// Create an empty page in this document.
var page = document.AddPage();
page.Size = PdfSharp.PageSize.A4;
// Get an XGraphics object for drawing on this PDF page.
var gfx = PdfSharp.Drawing.XGraphics.FromPdfPage(page);
// Create some fonts.
const double fontSize = 24;
PdfSharp.Drawing.XPdfFontOptions options
= new PdfSharp.Drawing.XPdfFontOptions(
PdfSharp.Pdf.PdfFontEncoding.Unicode);
var font = new PdfSharp.Drawing.XFont("JetBrains Mono", fontSize, PdfSharp.Drawing.XFontStyle.Regular, options);
var cfont = new PdfSharp.Drawing.XFont("Hans", fontSize, PdfSharp.Drawing.XFontStyle.Regular, options);
// Draw the text.
const double x = 40;
double y = 50;
const string ctext = "字体:JetBrains Mono";
gfx.DrawString(ctext, cfont, PdfSharp.Drawing.XBrushes.Black, x, y);
y += 60;
const string text1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
gfx.DrawString(text1, font, PdfSharp.Drawing.XBrushes.Black, x, y);
y += 60;
const string text2 = "abcdefghijklmnopqrstuvwxyz";
gfx.DrawString(text2, font, PdfSharp.Drawing.XBrushes.Black, x, y);
y += 60;
const string text3 = "0123456789";
gfx.DrawString(text3, font, PdfSharp.Drawing.XBrushes.Black, x, y);
y += 60;
// Save the document...
const string filename = "../../../Output/FontResolver_tempfile.pdf";
document.Save(filename);
// ...and start a viewer.
}
}
}
在 PdfSharp 中使用私有字体的更多相关文章
- 在CSS中通过@font-face属性来实现网页中嵌入特殊字体。
首先获取要使用字体的三种文件格式.EOT..TTF或.OTF..SVG,确保能在主流浏览器中都能正常显示该字体..EOT,适用于Internet Explorer 4.0+.TTF或.OTF,适用于F ...
- 使用pango-Cairo列出系统中的有效字体
使用pango-Cairo列出系统中的有效字体,代码来源于gtk-app-devel-list fonts list using pango #include <glib.h> #incl ...
- OC中的私有变量和description
.OC中的私有变量 在类的实现即.m @implementation中也可以声明成员变量,但是因为在其他文件中通常都只 是包含头文件而不会包含实现文件,所以在.m文件中声明的成员变量是@private ...
- 网页中导入特殊字体@font-face属性详解
@font-face是CSS3中的一个模块,他主要是把自己定义的Web字体嵌入到你的网页中. 语法规则 首先我们一起来看看@font-face的语法规则: @font-face { font-fami ...
- Bootstrap中glyphicons-halflings-regular.woff字体报404错notfound
今天查看网站的源代码,发现有个glyphicons-halflings-regular.woff文件没有找到,因为我的网站使用了bootstrap的Glyphicons 字体图标,因此需要加载Glyp ...
- PHP通过反射方法调用执行类中的私有方法
PHP 5 具有完整的反射 API,添加了对类.接口.函数.方法和扩展进行反向工程的能力. 下面我们演示一下如何通过反射,来调用执行一个类中的私有方法: <?php //MyClass这个类中包 ...
- Oracle EBS的BIP报表中显示特殊字体
http://oracleseeker.com/2009/08/25/font_mapping_setup_for_special_character_print_in_oracle_ebs_bip/ ...
- Eclipse中项目面板字体的修改
修改eclipse安装目录中的如下文件,添加黄色标记部分,并设定自己需要的字体大小(这里是10px)即可: \eclipse\plugins\org.eclipse.ui.themes_1.1.1.v ...
- PowerDesigner修改设计图中文字的字体大小等样式
设计图中默认的字体是对英文比较合适的,中文就看不清楚了,特别不美观.但是可以通过修改“Display Preferences”适应我们的汉字. 我使用的PowerDesigner版本是15.1(测试版 ...
- web中的中文字体的英文名称
自从font-face出现以后,字体样式就不再是web开发者的难题了,但是对于移动端的中文来说,问题还是存在的,因为中文文件大小最少要3M+,即使选择性的加载某个字的字体,那也会出现不易替换的问题,所 ...
随机推荐
- C#/.NET/.NET Core技术前沿周刊 | 第 8 期(2024年10.01-10.06)
前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...
- excel江湖异闻录--修迪斯.嗦狸
因为技术出类拔萃,同学都尊称他为"修神",修神的python.vba.Javascript.java.数据库.批处理等众多编程语言都是极强的,以笔者的见识来判断,大佬的vba已经是 ...
- .NET高级调试 - 3.12 sosex实用的几个命令介绍
简介 sosex是sos的一个拓展,主要目的是将一些繁琐的排查过程脚本化,比如探测死锁,设置断点等.更加方便快捷协助我们排查问题. 比较可惜的是,在.net core中不可用,作者已经不更新了. 更多 ...
- 云原生爱好者周刊:K8s Security SIG 发布 Kubernetes 策略管理白皮书
云原生一周动态要闻: Istio 1.13 发布 CNCF 宣布 2021 年云原生调查结果 运行时安全项目 Falco 添加可扩展插件框架 Grafana 8.3.6 发布 开源项目推荐 文章推荐 ...
- JavaScript String 对象-常用知识点
JavaScript String 对象-常用知识点 对象用于处理文本(字符串). 对象创建方法: new String(). String 对象属性 属性 描述 constructor 对创建该对象 ...
- buck电路 & boost电路
buck电路 buck电路是直流的降压电路,我们下面给大家讲下,如何把12V的直流电压降压成5V的直流电压 1.buck电路拓扑:12V----->5V 2.降压原理 a.开关闭合,电流走向 电 ...
- 每日学学Java开发规范,代码格式(附阿里巴巴Java开发手册(终极版))
前言 每次去不同的公司,码不同的代码,适应不同的规范,经常被老大教育规范问题,我都有点走火入魔的感觉,还是要去看看阿里巴巴Java开发规范,从中熟悉一下,纠正自己,码出高效,码出质量. 想细看的可以去 ...
- mysql隐蔽的索引规则导致数据全表扫描
索引是为了加速数据的检索,但是不合理的表结构或适应不当则会起到反作用.我们在项目中就遇到过类似的问题,两个十万级别的数据表,在做连接查询的时候,查询时间达到了7000多秒还没有查出结果. 首先说明,关 ...
- 面试:靠着这篇笔记,我拿下了16k车载测试offer!
如何写简历个人技能个人技能一般不要超过10条,一般在8条内. 一.测试流程和技术 1.熟悉车载系统研发和测试流程,能独立编写各种测试文档. 2.熟悉车载系统测试用例设计思路,能独立编写仪表和车机的测试 ...
- C++面经(持续更新)
一. c,c++区别<九大点> c: 面向过程 c++: 面向对象(封装,继承,多态) 对象:对数据和作用于数据的操作组成的封装实体 类:描叙了一组有相同属性和方法的对象<虚拟> ...