プログラムでPDFを出力するにはライブラリを使用します。文字の出力にはフォントが用いますが、英語の場合と異なり、日本語については少し手間が必要です。
今回は、C#で日本語をPDF出力してみます。ライブラリにはPDFSharpを利用します。
ライブラリ名 | 今回利用したバージョン | 言語 | ライセンス | レポジトリ |
---|---|---|---|---|
PDFSharp | 1.50.4820-RC1 | C# | MIT | NuGet |
なお、C#にはiTextSharpという強力なPDF作成ライブラリがあります。しかし、無料バージョンのライセンスがAGPLであり、業務での運用に支障を来す場合があるので、ここではMITライセンスのPDFSharpを利用します。
本記事の目次
使用フォント
日本語のフォントには、フリーの源真ゴシックを用います。源真ゴシックは「源ノ角ゴシック(AdobeがGoogleと共同開発したオープンソースの Pan-CJK フォントファミリー)」を日本語環境で使いやすいように改変したフォントです。実際とても使い勝手がよく、商用利用ができるので重宝します。詳細およびダウンロードは以下のサイトを参照してください。
上記のサイトからダウンロードした源真ゴシックには、数種類のフォントファイル(TTF形式)が含まれます。今回はそのなかから、GenShinGothic-Monospace-Medium.ttf
を用いました。
他のよく利用されるフリーフォント
当初はフリーフォントといえば、独立行政法人情報処理推進機構 (IPA) によって配布されているIPAフォント でした。その後、AdobeとGoogleが以下のようなフォントを公開し、さらにライセンスに従った改変と再配布が許容されているので派生フォントも登場しています。今回は、源ノ角ゴシックの派生フォントである「源真ゴシック」を利用させていただきました。
作成するPDF
A4用紙の真ん中に「こんにちは、世界!」と出力するPDFファイルを作成します。
プログラムの作成
プロジェクト構成
プロジェクトは以下の構成で作成します。フォントファイルはfontsフォルダー
にコピーします。
- PdfCreate01 プロジェクト
- fonts
- GenShinGothic-Monospace-Medium.ttf 重要:埋め込みリソースにする
- Program.cs
- JapaneseFontResolver.cs
フォントファイルのビルドアクションは埋め込みリソースにしてください。以下のように、Visual Studioのフォントファイルのプロパティで設定できます。
ライブラリの参照への追加
ツール ▶ NuGetパッケージマネージャー ▶ パッケージマネージャーコンソールでPMコンソールを開き以下のコマンドを実行し、ライブラリを参照に追加します。
PM> Install-Package PdfSharp -Version 1.50.4820-RC1
1. メインプログラム(Program.cs)
最初に、カスタムのフォントリゾルバー(JapaneseFontResolver
)を登録しておきます。これによりカスタムのフォントファミリー名(Gen Shin Gothic
)を利用できるようになります。
最後で作成したPDFファイルを関連付けられているプログラムで表示します。Windows10であれば通常はEdgeブラウザーで表示されます。
using PdfSharp;
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using System.Diagnostics;
namespace PdfCreate01
{
class Program
{
static void Main(string[] args)
{
// フォントリゾルバーのグローバル登録
PdfSharp.Fonts.GlobalFontSettings.FontResolver = new JapaneseFontResolver();
// 新規ドキュメントを作成
PdfDocument document = new PdfDocument();
document.Info.Title = "Created with PDFsharp";
// 白紙をつくる(A4縦)
PdfPage page = document.AddPage();
page.Size = PageSize.A4;
page.Orientation = PageOrientation.Portrait;
// XGraphicsオブジェクトを取得
XGraphics gfx = XGraphics.FromPdfPage(page);
// フォント
XFont font = new XFont("Gen Shin Gothic", 20, XFontStyle.Regular);
// 文字列描画
gfx.DrawString(
"こんにちは、世界!",
font,
XBrushes.Black,
new XRect(0, 0, page.Width, page.Height),
XStringFormats.Center // 真ん中に描画
);
// PDF保存(カレントディレクトリ)
const string filename = "HelloWorld.pdf";
document.Save(filename);
// デフォルトプログラムで表示
Process.Start(filename);
}
}
}
2. フォントリゾルバー(JapaneseFontResolver.cs)
PDFSharp1.50(現在はRC版)から、IFontResolver
というインターフェースが提供されました。これでフォントリゾルバーを実装することで任意のフォントファイルを読み込み登録できます。実装方法は以下のサイトを参考にしました。
Using private fonts with PDFsharp 1.50 beta 2/3 or MigraDoc
フォントファイルを埋め込みリソースにしているので、「プロジェクト名.フォルダ名.ファイル名」(PdfCreate01.fonts.GenShinGothic-Monospace-Medium.ttf
)で読み込みできます。リソースでなくファイルのままだと絶対パスを指定しなければならないので面倒になります。
using PdfSharp.Fonts;
using System;
using System.IO;
using System.Reflection;
namespace PdfCreate01
{
// 日本語フォントのためのフォントリゾルバー
public class JapaneseFontResolver : IFontResolver
{
// 源真ゴシック( http://jikasei.me/font/genshin/)
private static readonly string GEN_SHIN_GOTHIC_MEDIUM_TTF =
"PdfCreate01.fonts.GenShinGothic-Monospace-Medium.ttf";
public byte[] GetFont(string faceName)
{
switch (faceName)
{
case "GenShinGothic#Medium":
return LoadFontData(GEN_SHIN_GOTHIC_MEDIUM_TTF);
}
return null;
}
public FontResolverInfo ResolveTypeface(
string familyName, bool isBold, bool isItalic)
{
var fontName = familyName.ToLower();
switch (fontName)
{
case "gen shin gothic":
return new FontResolverInfo("GenShinGothic#Medium");
}
// デフォルトのフォント
return PlatformFontResolver.ResolveTypeface("Arial", isBold, isItalic);
}
// 埋め込みリソースからフォントファイルを読み込む
private byte[] LoadFontData(string resourceName)
{
var assembly = Assembly.GetExecutingAssembly();
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
if (stream == null)
throw new ArgumentException("No resource with name " + resourceName);
int count = (int)stream.Length;
byte[] data = new byte[count];
stream.Read(data, 0, count);
return data;
}
}
}
}
今回は源真ゴシックのMediumの1つだけを登録していますが、複数登録しておくことも可能です。
最後に
iText(iTextSharp) のライセンスがAGPLになってからはPDFSharpを利用していますが、ほとんど不自由していません。日本語フォントも以前から利用する方法はありましたが、バージョン1.50からIFontResolverが追加され、非常に使いやすくなりました。是非参考にしてください。
また、Apache PDFBox をIKVM.NETで実装されたJava仮想マシンで実行する方法もあるようです(NuGetにもあります )。こちらは試したことがありませんが、PDFBoxに慣れている場合は検討してみてもよいと思います。