NimでPDFを作成
Nim言語については、初心者に毛が生えたぐらいの知識しかない未熟者です。
早々ですが、Nim言語でPDFを作成したいと思いませんか?、調べてみました。
nimPDF
というライブラリがありましたので、今回はこれが動かせるかどうか検証していきます。
環境
私のPC環境はWindowsであるため、Nightly build版で動作させています。
- OS: Windows11
- Nim 1.9.1 (v2.0 RC版 2023/02/18)
- nimPDF 0.4.3 (2年前から一切更新なし)
nimPDFの特徴
- 画像は、
PNG
,JPEG
,BMP
が対応しています。 - フォントは、
TTF
,TTC
が対応しています。 - 色彩は、
RGB
,CMYK
が対応しています。 - フォーム機能については、対応しているらしいが、未確認
PDFの動作確認
1. nimPDFライブラリのインストール
nimble install nimPDF
GitHubにnimPDFライブラリは存在しますが、ドキュメントは一切ありません。唯一あったのは、Adobe PDFのマニュアルのみ。
2. フォントの設定
日本語フォントについては、フリーで配布されている物は、ほぼ全て文字化けします。
唯一問題なかったのは、Lineの子会社であるLINE Seed JPが配布しているフォントのみでした。(GoogleフォントのNoto Sans JPについては、フォント形式がOTFであるため、未確認。)
TTFフォントをダウンロードした後、ソースがあるフォルダに、fonts
フォルダを作成し、その中にフォントを入れます。
3. 画像の設定
画像は、ソース内にresources
フォルダを作成し、その中に配置しておきます。
4. PDF作成プログラム
#[
nimPDFの注意点
importは、import nimPDF/nimPDFに設定する
日本語フォントは、フリーで配布されている日本語フォントは文字化けするが、唯一、LINE Seed JP_TTFは文字化けしない
イタリック書体にすると文字化けする
縦書き文字は、半角英語は問題ないが、日本語は文字が詰まって表示される
読み込むフォントは、fontsフォルダを作成し、TTFがTTCファイルを置く
読み込む画像は、resourcesフォルダを作成し、画像を置く
]#
import nimPDF/nimPDF
# 色の設定
const COLOR_WHITE = initRGB(1.0, 1.0, 1.0)
const COLOR_BLACK = initRGB(0.0, 0.0, 0.0)
const COLOR_RED = initRGB(1.0, 0.0, 0.0)
const COLOR_GREEN = initRGB(0.0, 0.5, 0.0)
const COLOR_YELLOW = initRGB(1.0, 1.0, 0.0)
const COLOR_BLUE = initRGB(0.0, 0.0, 1.0)
const COLOR_GRAY = initRGB(0.4, 0.4, 0.4)
const COLOR_LIGHT_GRAY = initRGB(0.6, 0.6, 0.6)
var doc = newPDF() # PDFオブジェクトを生成
doc.addPage(getSizeFromName("A4"), PGO_PORTRAIT) # ページの生成(サイズはA4)
doc.setFillColor(COLOR_BLACK) # 色はブラック
doc.setFont("LINE Seed JP_TTF", {FS_REGULAR}, 6, ENC_WINANSI)
doc.drawText(15, 15, "あいうえお かきくけこ さしすせそ たちつてと なにぬねの はひふへほ")
doc.drawText(15, 15+8, "アイウエオ カキクケコ サシスセソ タチツテト ナニヌネノ ハヒフヘホ")
doc.drawText(15, 15+16, "アイウエオ カキクケコ サシスセソ タチツテト ナニヌネノ ハヒフヘホ")
doc.drawText(15, 15+24, "@?%$#”!()=〇±※←")
doc.drawVText(120, 55, "あいうえお かきくけこ") # 縦書き全角文字
doc.drawVText(100, 55, "Hello World") # 縦書き英字
# 四角形を生成
doc.setLineWidth(1.0) # 線の太さ
doc.setStrokeColor(COLOR_BLACK) # 線の色
doc.drawRect(15, 50, 60, 10); # 矩形 x y width height
doc.stroke() # 描画
# 四角形を生成
doc.setLineWidth(0.5) # 線の太さ
doc.setStrokeColor(COLOR_BLACK) # 線の色
doc.drawRect(15, 70, 60, 10); # 矩形 x y width height
doc.setFillColor(COLOR_YELLOW) # 矩形の色
doc.fillAndStroke() # 描画
# 画像を読み込み・貼り付け
var img = doc.loadImage("king.png") # 画像の読み込み
doc.saveState()
doc.scale(0.3, 15, 30) # 画像を0.3倍に縮小 15はx座標 30はy座標
doc.drawImage(15, 320, img) # 画像の貼り付け 左下の座標
doc.restoreState()
# PDF作成
if not doc.writePDF("sample01.pdf"):
echo "書き込み不可能: sample01.pdf"
プログラムの説明
-
initRGB
でRGB色を取得し、setFillColor
で描画色を設定します。(引数は、0.0~1.0を設定で、256じゃない理由は知りません。) - PDFオブジェクトを生成後に、
addPage
ページ設定を行います。 - フォント設定を行う
setFont
は、フォントファミリー名、スタイル型、サイズ、エンコードの順に設定を行います。 -
drawVText
は縦書きで表示しますが、日本語だと文字が重なり、使い物になりません。また、英語半角は表示はされますが、何故か左寄りに表示されます。 - 画像の読み込み後に、
saveState
とrestoreState
を設定していますが、それぞれ何をしている関数かわかりません。無くても画像は出力されます。
下記のようにターミナル上から実行
nim r --hints:off .\sample01.nim
出力結果
- ソースと同一ディレクトリに
sample01.pdf
ファイルが作成されますので、PDFReaderかブラウザで表示出来ます。
5. 格子のみのPDF作成プログラム
#[
格子状の線を引くPDFを作成
]#
import nimPDF/nimPDF
import math
var doc = newPDF()
let size = getSizeFromName("A4")
doc.addPage(size, PGO_PORTRAIT)
const gray_thin = initRGB(0.5,0.5,0.5)
const gray_bold = initRGB(0.8,0.8,0.8)
doc.setFillColor(gray_thin)
doc.setStrokeColor(gray_bold)
let width = size.width.toMM
let height = size.height.toMM
# 横線の描画 5mm間隔で線を引く
var y = 0.0
while y < height:
if `mod`(y, 10.0) == 0.0:
doc.setLineWidth(0.5)
else:
doc.setLineWidth(0.1)
doc.moveTo(0, y)
doc.lineTo(width, y)
doc.stroke()
y += 5.0
# 縦線の描画 5mm間隔で線を引く
var x = 0.0
while x < width:
if `mod`(x, 10) == 0:
doc.setLineWidth(0.5)
else:
doc.setLineWidth(0.1)
doc.moveTo(x, 0)
doc.lineTo(x, height)
doc.stroke()
x += 5.0
const COLOR_BLACK = initRGB(0.0, 0.0, 0.0)
doc.setFillColor(COLOR_BLACK)
doc.setFont("LINE Seed JP_TTF", {FS_BOLD}, 3, ENC_WINANSI)
# 縦軸の文字
y = 0.0
while y < height:
if (`mod`(y,10.0) == 0) and (y > 0):
doc.drawText(5, y - 2, $y)
y += 5.0
# 横軸の文字
x = 0
while x < width:
if (`mod`(x,50) == 0) and (x > 0):
doc.drawText(x, 5, $x)
doc.drawText(x, height - 5, $x)
x += 5.0
if not doc.writePDF("sample02.pdf"):
echo "書き込み不可能: sample02.pdf"
プログラムの説明
getSizeFromName("A4")
関数でA4サイズを求め、横軸・縦軸に5mm間隔でラインを引きます。
起点moveTo
から終点lineTo
を設定した後、stroke
で線を描画するだけのプログラムです。
下記のようにターミナル上から実行
nim r --hints:off .\sample02.nim
出力結果
- ソースと同一ディレクトリに
sample02.pdf
ファイルが作成されますので、PDFReaderかブラウザで表示出来ます。
おわりに
簡単ではありますが、nimPDF
の使い方を解説してみました。
日本語フォントについては、試行錯誤しましたが、LINE Seed JPなら出力される事はわかりました。ただ、それ以外のフリーフォントは文字化けします。多分、nimPDF
のバグなんでしょうね。後、スタイル形式をイタリック文字にすると文字化けします。また縦文字も文字が重なり使い物になりませんので、注意が必要です。
nimPDF
にはドキュメントが一切ありませんが、sample内のソースを見てもわかる通り、ある程度、感覚でPDFを作成する事は可能です。
ただ、壁にぶち当たると、ソース解析が必要になりますが…
Discussion