[{"data":1,"prerenderedAt":5698},["ShallowReactive",2],{"blog-ja-unidoc-migration":3},{"id":4,"title":5,"author":6,"body":10,"date":5658,"description":5659,"draft":5660,"extension":5661,"howTo":5662,"image":5688,"meta":5689,"navigation":304,"path":5690,"seo":5691,"stem":5692,"tags":5693,"updated":5688,"__hash__":5697},"blogJa/ja/blog/016.unidoc-migration.md","unipdf の AGPL/商用ライセンスから gpdf へ移行する",{"name":7,"url":8,"avatar":9},"野田大貴","https://nadai.dev/ja/about","https://nadai.dev/og-default.png",{"type":11,"value":12,"toc":5641},"minimark",[13,18,46,61,72,75,79,82,85,107,114,117,120,250,257,260,263,410,531,549,556,560,571,880,911,915,918,923,1297,1302,1732,1741,1745,1762,1766,2382,2385,2389,2783,2795,2806,2813,2817,2820,2824,3087,3093,3097,3550,3565,3568,3572,3587,3591,3880,3883,3887,4547,4554,4558,4564,4568,5034,5038,5325,5336,5339,5345,5441,5444,5447,5451,5454,5493,5498,5502,5508,5520,5541,5547,5566,5572,5576,5579,5596,5609,5612,5638],[14,15,17],"h2",{"id":16},"tldr","TL;DR",[19,20,21,25,26,29,30,29,33,36,37,41,42,45],"p",{},[22,23,24],"strong",{},"gpdf"," は ",[22,27,28],{},"MIT ライセンス","・",[22,31,32],{},"外部依存ゼロ",[22,34,35],{},"ライセンスキー登録なし"," の純 Go PDF ライブラリ。",[38,39,40],"code",{},"unidoc/unipdf"," を CJK や AcroForm のために使っているが、AGPL 条項が法務に止められたり、商用ライセンス費用の根拠説明がしんどい状況なら、この記事が unipdf の ",[38,43,44],{},"creator"," API から gpdf への移行マップになる。",[19,47,48,49,52,53,56,57,60],{},"先期、知人のフィンテック企業で ",[38,50,51],{},"github.com/unidoc/unipdf/v3"," を OSS 承認フローに乗せた。返ってきた回答は ",[22,54,55],{},"AGPL-3.0"," の横に赤い X、そして法務からの一文 — 「",[22,58,59],{},"クローズドソースの製品に組み込めません。商用ライセンスを取得するか、削除してください。","」。商用見積りの開発者あたり年額を 12 名分で計算した結果、全員が再度検索結果を開き直すことになった。",[19,62,63,64,67,68,71],{},"これは README には載らない unipdf の側面。技術的にはむしろ優秀で、機能も成熟しメンテも継続的。ただし ",[22,65,66],{},"デュアルライセンス",": オープン用途は AGPL v3、それ以外は ",[22,69,70],{},"商用ライセンスが必須","。AGPL v3 は実用されている copyleft の中で最強の部類で、ネットワーク越しに使われるサービスに unipdf をリンクすると、§13 によりサービス全体のソース公開義務が発生する。たいていの会社の法務部はこれを通さない。",[19,73,74],{},"すでに unipdf 製のコードがあって、ライセンスが監査で引っかかった、あるいは更新時期が来ている — ならこの記事は移行マップ。新規で「Go の PDF どうしよう」で unipdf に手が伸びかけているなら、これが請求書を伴わない代替案。",[14,76,78],{"id":77},"agpl-か有料が実運用で意味すること","「AGPL か有料」が実運用で意味すること",[19,80,81],{},"Go ライブラリの中には「AGPL」ラベルだけ貼ってあって意味を深く考えずに使われているものもあるが、unipdf は違う。リポジトリのライセンスファイルは AGPL v3 そのままで、README は商用利用にキーが必要だと明記し、バイナリ自体がそれを強制する。起動時に license を登録せず unipdf API を呼ぶと、エラーまたは出力 PDF 全ページに透かし。",[19,83,84],{},"実用上、以下の 3 モードのどれかに入る:",[86,87,88,95,101],"ol",{},[89,90,91,94],"li",{},[22,92,93],{},"AGPL モード","。自社サービスのコードを AGPL v3 で公開する。unipdf に触れる部分、そしてリンクされている全コードは、ネットワーク越しに利用するユーザーから請求された場合に開示する義務が発生する。社内ツールや SaaS では現実的でない。",[89,96,97,100],{},[22,98,99],{},"商用モード","。UniDoc に開発者あたり年額を支払う。価格は変動するが直近の公開見積りはおおむね開発者 1 名・年・四桁ドル、metering またはライセンスキー登録の呼び出しを全バイナリで行う必要がある。キーはシークレットとして扱われ、シークレットマネージャに置いて全コンテナに注入される。",[89,102,103,106],{},[22,104,105],{},"トライアル / 評価モード","。期間限定で無料。出力に透かしが入る。本番では使えない。",[19,108,109,110,113],{},"どのモードも本質的に間違ってはいない。UniDoc は実在の会社が実在のエンジニアでメンテしている製品で、価格はそのコストを反映している。",[22,111,112],{},"ただし、そのライセンス選択は全レイヤーに波及する"," — 法務レビュー、シークレットローテーション、財務の更新フロー、デプロイ面 (全コンテナにキーが必要)。gpdf は MIT なので、その列がスプレッドシートからまるごと消える。",[14,115,116],{"id":116},"失うものと残るもの",[19,118,119],{},"API の話に入る前に正直に整理しておく。unipdf にあって gpdf にない機能はある:",[121,122,123,138],"table",{},[124,125,126],"thead",{},[127,128,129,133,136],"tr",{},[130,131,132],"th",{},"機能",[130,134,135],{},"unipdf",[130,137,24],{},[139,140,141,152,162,172,182,191,201,211,221,230,239],"tbody",{},[127,142,143,147,150],{},[144,145,146],"td",{},"PDF 生成",[144,148,149],{},"✅",[144,151,149],{},[127,153,154,157,159],{},[144,155,156],{},"TrueType / CJK フォント",[144,158,149],{},[144,160,161],{},"✅ (CGO 不使用、自動サブセット化)",[127,163,164,167,169],{},[144,165,166],{},"AES-128/256 暗号化",[144,168,149],{},[144,170,171],{},"✅ (ISO 32000-2 Rev 6、純 Go 実装)",[127,173,174,177,179],{},[144,175,176],{},"PKCS#7 / PAdES 署名",[144,178,149],{},[144,180,181],{},"✅ (RFC 3161 TSA 対応)",[127,183,184,187,189],{},[144,185,186],{},"PDF/A-1b/2b",[144,188,149],{},[144,190,149],{},[127,192,193,196,198],{},[144,194,195],{},"AcroForm — 既存フィールドの記入",[144,197,149],{},[144,199,200],{},"✅ (フラット化のみ。新規フィールド作成は未対応)",[127,202,203,206,208],{},[144,204,205],{},"AcroForm — 新規フィールド作成",[144,207,149],{},[144,209,210],{},"❌",[127,212,213,216,218],{},[144,214,215],{},"PDF 解析 / テキスト抽出",[144,217,149],{},[144,219,220],{},"❌ (gpdf は生成専用)",[127,222,223,226,228],{},[144,224,225],{},"OCR",[144,227,149],{},[144,229,210],{},[127,231,232,235,237],{},[144,233,234],{},"PDF 黒塗り (redaction)",[144,236,149],{},[144,238,210],{},[127,240,241,244,247],{},[144,242,243],{},"HTML レンダリング",[144,245,246],{},"一部",[144,248,249],{},"❌ (別レンダラで生成して merge する想定)",[19,251,252,253,256],{},"PDF 解析・OCR・redaction が必要な経路は、この移行ではカバーしきれない。それらの経路だけ unipdf を残す (該当バイナリの商用ライセンスは引き続き必要)、または読み取り側を別ライブラリに切るのが現実解。",[22,254,255],{},"生成・暗号化・署名・フォント・CJK"," ─ これは大半の unipdf 請求の対象 ─ については gpdf で完全に置き換えられる。",[14,258,259],{"id":259},"ライセンス登録コードを削除する",[19,261,262],{},"これは移行で最小の diff だが、後の作業を実感させる重要な一歩。unipdf バイナリは起動時にキー登録が必要で、いくつかバリエーションがある:",[264,265,270],"pre",{"className":266,"code":267,"language":268,"meta":269,"style":269},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","// API キー (metering)\nimport \"github.com/unidoc/unipdf/v3/common/license\"\n\nfunc init() {\n    if err := license.SetMeteredKey(os.Getenv(\"UNIDOC_API_KEY\")); err != nil {\n        log.Fatal(err)\n    }\n}\n","go","",[38,271,272,281,299,306,322,379,398,404],{"__ignoreMap":269},[273,274,277],"span",{"class":275,"line":276},"line",1,[273,278,280],{"class":279},"sHwdD","// API キー (metering)\n",[273,282,284,288,292,296],{"class":275,"line":283},2,[273,285,287],{"class":286},"s7zQu","import",[273,289,291],{"class":290},"sMK4o"," \"",[273,293,295],{"class":294},"sBMFI","github.com/unidoc/unipdf/v3/common/license",[273,297,298],{"class":290},"\"\n",[273,300,302],{"class":275,"line":301},3,[273,303,305],{"emptyLinePlaceholder":304},true,"\n",[273,307,309,312,316,319],{"class":275,"line":308},4,[273,310,311],{"class":290},"func",[273,313,315],{"class":314},"s2Zo4"," init",[273,317,318],{"class":290},"()",[273,320,321],{"class":290}," {\n",[273,323,325,328,332,335,338,341,344,347,350,352,355,357,360,364,366,369,371,374,377],{"class":275,"line":324},5,[273,326,327],{"class":286},"    if",[273,329,331],{"class":330},"sTEyZ"," err ",[273,333,334],{"class":290},":=",[273,336,337],{"class":330}," license",[273,339,340],{"class":290},".",[273,342,343],{"class":314},"SetMeteredKey",[273,345,346],{"class":290},"(",[273,348,349],{"class":330},"os",[273,351,340],{"class":290},[273,353,354],{"class":314},"Getenv",[273,356,346],{"class":290},[273,358,359],{"class":290},"\"",[273,361,363],{"class":362},"sfazB","UNIDOC_API_KEY",[273,365,359],{"class":290},[273,367,368],{"class":290},"));",[273,370,331],{"class":330},[273,372,373],{"class":290},"!=",[273,375,376],{"class":290}," nil",[273,378,321],{"class":290},[273,380,382,385,387,390,392,395],{"class":275,"line":381},6,[273,383,384],{"class":330},"        log",[273,386,340],{"class":290},[273,388,389],{"class":314},"Fatal",[273,391,346],{"class":290},[273,393,394],{"class":330},"err",[273,396,397],{"class":290},")\n",[273,399,401],{"class":275,"line":400},7,[273,402,403],{"class":290},"    }\n",[273,405,407],{"class":275,"line":406},8,[273,408,409],{"class":290},"}\n",[264,411,413],{"className":266,"code":412,"language":268,"meta":269,"style":269},"// オフラインライセンスファイル\nfunc init() {\n    licenseKey, _ := os.ReadFile(\"/etc/unidoc/license.txt\")\n    if err := license.SetLicenseKey(string(licenseKey), \"Acme Corp\"); err != nil {\n        log.Fatal(err)\n    }\n}\n",[38,414,415,420,430,462,509,523,527],{"__ignoreMap":269},[273,416,417],{"class":275,"line":276},[273,418,419],{"class":279},"// オフラインライセンスファイル\n",[273,421,422,424,426,428],{"class":275,"line":283},[273,423,311],{"class":290},[273,425,315],{"class":314},[273,427,318],{"class":290},[273,429,321],{"class":290},[273,431,432,435,438,441,443,446,448,451,453,455,458,460],{"class":275,"line":301},[273,433,434],{"class":330},"    licenseKey",[273,436,437],{"class":290},",",[273,439,440],{"class":330}," _ ",[273,442,334],{"class":290},[273,444,445],{"class":330}," os",[273,447,340],{"class":290},[273,449,450],{"class":314},"ReadFile",[273,452,346],{"class":290},[273,454,359],{"class":290},[273,456,457],{"class":362},"/etc/unidoc/license.txt",[273,459,359],{"class":290},[273,461,397],{"class":290},[273,463,464,466,468,470,472,474,477,479,483,485,488,491,493,496,498,501,503,505,507],{"class":275,"line":308},[273,465,327],{"class":286},[273,467,331],{"class":330},[273,469,334],{"class":290},[273,471,337],{"class":330},[273,473,340],{"class":290},[273,475,476],{"class":314},"SetLicenseKey",[273,478,346],{"class":290},[273,480,482],{"class":481},"spNyl","string",[273,484,346],{"class":290},[273,486,487],{"class":330},"licenseKey",[273,489,490],{"class":290},"),",[273,492,291],{"class":290},[273,494,495],{"class":362},"Acme Corp",[273,497,359],{"class":290},[273,499,500],{"class":290},");",[273,502,331],{"class":330},[273,504,373],{"class":290},[273,506,376],{"class":290},[273,508,321],{"class":290},[273,510,511,513,515,517,519,521],{"class":275,"line":324},[273,512,384],{"class":330},[273,514,340],{"class":290},[273,516,389],{"class":314},[273,518,346],{"class":290},[273,520,394],{"class":330},[273,522,397],{"class":290},[273,524,525],{"class":275,"line":381},[273,526,403],{"class":290},[273,528,529],{"class":275,"line":400},[273,530,409],{"class":290},[19,532,533,534,537,538,540,541,544,545,548],{},"gpdf には対応物が存在しない。",[38,535,536],{},"init()"," ブロックは丸ごと削除。",[38,539,363],{}," をシークレットマネージャ・CI 変数・コンテナマニフェストから抜く。イメージからライセンスファイルを除く。import するのは ",[38,542,543],{},"github.com/gpdf-dev/gpdf"," だけで、要件は「どこかで ",[38,546,547],{},"gpdf.NewDocument"," を呼ぶ」だけ。",[19,550,551,552,555],{},"これだけ。完了の判定基準もシンプル: ",[38,553,554],{},"grep -r unidoc ."," がヒット 0 件になればよい。",[14,557,559],{"id":558},"api-マッピング表","API マッピング表",[19,561,562,563,566,567,570],{},"これがチートシート。続くセクションで 5 ペアの具体例。unipdf では高レベルビルダーを ",[38,564,565],{},"Creator"," と呼ぶ。gpdf では ",[38,568,569],{},"Document","。形が似ていて、たいていは見た目で対応が取れる。",[121,572,573,588],{},[124,574,575],{},[127,576,577,580,586],{},[130,578,579],{},"やりたいこと",[130,581,582,583,585],{},"unipdf (",[38,584,44],{},")",[130,587,24],{},[139,589,590,605,620,635,655,673,691,707,722,737,752,774,796,816,831,850,865],{},[127,591,592,595,600],{},[144,593,594],{},"ビルダーを作る",[144,596,597],{},[38,598,599],{},"c := creator.New(); c.SetPageSize(creator.PageSizeA4)",[144,601,602],{},[38,603,604],{},"doc := gpdf.NewDocument(gpdf.WithPageSize(document.A4))",[127,606,607,610,615],{},[144,608,609],{},"マージン設定",[144,611,612],{},[38,613,614],{},"c.SetPageMargins(L, R, T, B)",[144,616,617],{},[38,618,619],{},"gpdf.WithMargins(document.UniformEdges(document.Mm(20)))",[127,621,622,625,630],{},[144,623,624],{},"新規ページ",[144,626,627],{},[38,628,629],{},"c.NewPage()",[144,631,632],{},[38,633,634],{},"page := doc.AddPage()",[127,636,637,640,645],{},[144,638,639],{},"1 行のテキスト",[144,641,642],{},[38,643,644],{},"p := c.NewParagraph(\"hi\"); c.Draw(p)",[144,646,647,650,651],{},[38,648,649],{},"c.Text(\"hi\")"," ",[652,653,654],"em",{},"(カラム内)",[127,656,657,660,665],{},[144,658,659],{},"折り返しテキスト",[144,661,662],{},[38,663,664],{},"p := c.NewStyledParagraph(); p.SetText(...); c.Draw(p)",[144,666,667,650,670],{},[38,668,669],{},"c.Text(body)",[652,671,672],{},"(自動折り返し)",[127,674,675,678,683],{},[144,676,677],{},"フォント登録",[144,679,680],{},[38,681,682],{},"model.NewCompositePdfFontFromTTFFile(path)",[144,684,685,650,688],{},[38,686,687],{},"gpdf.WithFont(\"Name\", ttfBytes)",[652,689,690],{},"(構築時)",[127,692,693,696,701],{},[144,694,695],{},"テキストにフォント適用",[144,697,698],{},[38,699,700],{},"style.Font = font; style.FontSize = 12",[144,702,703,706],{},[38,704,705],{},"template.FontFamily(\"Name\"), template.FontSize(12)"," per-text",[127,708,709,712,717],{},[144,710,711],{},"色",[144,713,714],{},[38,715,716],{},"style.Color = creator.ColorRGBFromHex(\"#1A237E\")",[144,718,719],{},[38,720,721],{},"template.TextColor(pdf.RGBHex(0x1A237E))",[127,723,724,727,732],{},[144,725,726],{},"テーブル",[144,728,729],{},[38,730,731],{},"t := c.NewTable(4); t.SetColumnWidths(...); c.Draw(t)",[144,733,734],{},[38,735,736],{},"c.Table(headers, rows, template.ColumnWidths(...))",[127,738,739,742,747],{},[144,740,741],{},"画像",[144,743,744],{},[38,745,746],{},"img, _ := c.NewImageFromFile(path); img.ScaleToWidth(w); c.Draw(img)",[144,748,749],{},[38,750,751],{},"c.Image(imgBytes, template.FitWidth(document.Mm(50)))",[127,753,754,757,766],{},[144,755,756],{},"ヘッダ / フッタ",[144,758,759,762,763],{},[38,760,761],{},"c.DrawHeader(fn)"," / ",[38,764,765],{},"c.DrawFooter(fn)",[144,767,768,762,771],{},[38,769,770],{},"doc.Header(fn)",[38,772,773],{},"doc.Footer(fn)",[127,775,776,779,785],{},[144,777,778],{},"ページ番号",[144,780,781,784],{},[38,782,783],{},"DrawFooter"," 引数からページ数を手動取得",[144,786,787,762,790,650,793],{},[38,788,789],{},"c.PageNumber()",[38,791,792],{},"c.TotalPages()",[652,794,795],{},"(プレースホルダ)",[127,797,798,801,811],{},[144,799,800],{},"暗号化",[144,802,803,806,807,810],{},[38,804,805],{},"model.PdfWriter"," + ",[38,808,809],{},"Encrypt"," で再エンコード",[144,812,813],{},[38,814,815],{},"gpdf.WithEncryption(gpdf.AES256, \"user\", \"owner\", perms)",[127,817,818,821,826],{},[144,819,820],{},"署名",[144,822,823],{},[38,824,825],{},"model.NewPdfAppender(...).Sign(...)",[144,827,828],{},[38,829,830],{},"gpdf.SignDocument(pdfBytes, signer, opts)",[127,832,833,836,845],{},[144,834,835],{},"ライセンス登録",[144,837,838,841,842,844],{},[38,839,840],{},"license.SetMeteredKey(...)"," を ",[38,843,536],{}," に",[144,846,847],{},[652,848,849],{},"(なし — 削除する)",[127,851,852,855,860],{},[144,853,854],{},"ファイル出力",[144,856,857],{},[38,858,859],{},"c.WriteToFile(\"out.pdf\")",[144,861,862],{},[38,863,864],{},"data, _ := doc.Generate(); os.WriteFile(\"out.pdf\", data, 0o644)",[127,866,867,870,875],{},[144,868,869],{},"Writer 出力",[144,871,872],{},[38,873,874],{},"c.Write(w)",[144,876,877],{},[38,878,879],{},"doc.Render(w)",[19,881,882,883,886,887,890,891,894,895,898,899,902,903,906,907,910],{},"構造的なシフトは 2 つ。unipdf の creator は ",[22,884,885],{},"状態を持つ"," — ",[38,888,889],{},"Paragraph"," や ",[38,892,893],{},"Table"," を組み立て、",[38,896,897],{},"c.Draw(thing)"," で確定する。gpdf は ",[22,900,901],{},"宣言的"," — 行とカラムのツリーを描き、配置はレイアウトエンジンに任せる。もう 1 つは gpdf が Bootstrap と同じ ",[22,904,905],{},"12 カラムグリッド"," を持つ点。各行は暗黙的に 12 単位幅で、",[38,908,909],{},"r.Col(n, fn)"," で消費する。ミリ単位で幅を追わなくなり、たいていのレイアウトは 2〜3 行に縮む。",[14,912,914],{"id":913},"before-after-1-最小の-pdf","Before / After 1: 最小の PDF",[19,916,917],{},"「Hello world」のペア。unipdf 側が長いのは license 呼び出しのセレモニーがあるから。",[19,919,920],{},[22,921,922],{},"Before — unipdf:",[264,924,926],{"className":266,"code":925,"language":268,"meta":269,"style":269},"package main\n\nimport (\n    \"log\"\n    \"os\"\n\n    \"github.com/unidoc/unipdf/v3/common/license\"\n    \"github.com/unidoc/unipdf/v3/creator\"\n)\n\nfunc init() {\n    if err := license.SetMeteredKey(os.Getenv(\"UNIDOC_API_KEY\")); err != nil {\n        log.Fatal(err)\n    }\n}\n\nfunc main() {\n    c := creator.New()\n    c.SetPageSize(creator.PageSizeA4)\n\n    p := c.NewParagraph(\"Hello, World!\")\n    p.SetFontSize(24)\n    if err := c.Draw(p); err != nil {\n        log.Fatal(err)\n    }\n\n    if err := c.WriteToFile(\"hello.pdf\"); err != nil {\n        log.Fatal(err)\n    }\n}\n",[38,927,928,936,940,947,957,965,969,977,986,991,996,1007,1048,1063,1068,1073,1078,1090,1109,1131,1136,1163,1182,1212,1227,1232,1237,1272,1287,1292],{"__ignoreMap":269},[273,929,930,933],{"class":275,"line":276},[273,931,932],{"class":290},"package",[273,934,935],{"class":294}," main\n",[273,937,938],{"class":275,"line":283},[273,939,305],{"emptyLinePlaceholder":304},[273,941,942,944],{"class":275,"line":301},[273,943,287],{"class":286},[273,945,946],{"class":290}," (\n",[273,948,949,952,955],{"class":275,"line":308},[273,950,951],{"class":290},"    \"",[273,953,954],{"class":294},"log",[273,956,298],{"class":290},[273,958,959,961,963],{"class":275,"line":324},[273,960,951],{"class":290},[273,962,349],{"class":294},[273,964,298],{"class":290},[273,966,967],{"class":275,"line":381},[273,968,305],{"emptyLinePlaceholder":304},[273,970,971,973,975],{"class":275,"line":400},[273,972,951],{"class":290},[273,974,295],{"class":294},[273,976,298],{"class":290},[273,978,979,981,984],{"class":275,"line":406},[273,980,951],{"class":290},[273,982,983],{"class":294},"github.com/unidoc/unipdf/v3/creator",[273,985,298],{"class":290},[273,987,989],{"class":275,"line":988},9,[273,990,397],{"class":290},[273,992,994],{"class":275,"line":993},10,[273,995,305],{"emptyLinePlaceholder":304},[273,997,999,1001,1003,1005],{"class":275,"line":998},11,[273,1000,311],{"class":290},[273,1002,315],{"class":314},[273,1004,318],{"class":290},[273,1006,321],{"class":290},[273,1008,1010,1012,1014,1016,1018,1020,1022,1024,1026,1028,1030,1032,1034,1036,1038,1040,1042,1044,1046],{"class":275,"line":1009},12,[273,1011,327],{"class":286},[273,1013,331],{"class":330},[273,1015,334],{"class":290},[273,1017,337],{"class":330},[273,1019,340],{"class":290},[273,1021,343],{"class":314},[273,1023,346],{"class":290},[273,1025,349],{"class":330},[273,1027,340],{"class":290},[273,1029,354],{"class":314},[273,1031,346],{"class":290},[273,1033,359],{"class":290},[273,1035,363],{"class":362},[273,1037,359],{"class":290},[273,1039,368],{"class":290},[273,1041,331],{"class":330},[273,1043,373],{"class":290},[273,1045,376],{"class":290},[273,1047,321],{"class":290},[273,1049,1051,1053,1055,1057,1059,1061],{"class":275,"line":1050},13,[273,1052,384],{"class":330},[273,1054,340],{"class":290},[273,1056,389],{"class":314},[273,1058,346],{"class":290},[273,1060,394],{"class":330},[273,1062,397],{"class":290},[273,1064,1066],{"class":275,"line":1065},14,[273,1067,403],{"class":290},[273,1069,1071],{"class":275,"line":1070},15,[273,1072,409],{"class":290},[273,1074,1076],{"class":275,"line":1075},16,[273,1077,305],{"emptyLinePlaceholder":304},[273,1079,1081,1083,1086,1088],{"class":275,"line":1080},17,[273,1082,311],{"class":290},[273,1084,1085],{"class":314}," main",[273,1087,318],{"class":290},[273,1089,321],{"class":290},[273,1091,1093,1096,1098,1101,1103,1106],{"class":275,"line":1092},18,[273,1094,1095],{"class":330},"    c ",[273,1097,334],{"class":290},[273,1099,1100],{"class":330}," creator",[273,1102,340],{"class":290},[273,1104,1105],{"class":314},"New",[273,1107,1108],{"class":290},"()\n",[273,1110,1112,1115,1117,1120,1122,1124,1126,1129],{"class":275,"line":1111},19,[273,1113,1114],{"class":330},"    c",[273,1116,340],{"class":290},[273,1118,1119],{"class":314},"SetPageSize",[273,1121,346],{"class":290},[273,1123,44],{"class":330},[273,1125,340],{"class":290},[273,1127,1128],{"class":330},"PageSizeA4",[273,1130,397],{"class":290},[273,1132,1134],{"class":275,"line":1133},20,[273,1135,305],{"emptyLinePlaceholder":304},[273,1137,1139,1142,1144,1147,1149,1152,1154,1156,1159,1161],{"class":275,"line":1138},21,[273,1140,1141],{"class":330},"    p ",[273,1143,334],{"class":290},[273,1145,1146],{"class":330}," c",[273,1148,340],{"class":290},[273,1150,1151],{"class":314},"NewParagraph",[273,1153,346],{"class":290},[273,1155,359],{"class":290},[273,1157,1158],{"class":362},"Hello, World!",[273,1160,359],{"class":290},[273,1162,397],{"class":290},[273,1164,1166,1169,1171,1174,1176,1180],{"class":275,"line":1165},22,[273,1167,1168],{"class":330},"    p",[273,1170,340],{"class":290},[273,1172,1173],{"class":314},"SetFontSize",[273,1175,346],{"class":290},[273,1177,1179],{"class":1178},"sbssI","24",[273,1181,397],{"class":290},[273,1183,1185,1187,1189,1191,1193,1195,1198,1200,1202,1204,1206,1208,1210],{"class":275,"line":1184},23,[273,1186,327],{"class":286},[273,1188,331],{"class":330},[273,1190,334],{"class":290},[273,1192,1146],{"class":330},[273,1194,340],{"class":290},[273,1196,1197],{"class":314},"Draw",[273,1199,346],{"class":290},[273,1201,19],{"class":330},[273,1203,500],{"class":290},[273,1205,331],{"class":330},[273,1207,373],{"class":290},[273,1209,376],{"class":290},[273,1211,321],{"class":290},[273,1213,1215,1217,1219,1221,1223,1225],{"class":275,"line":1214},24,[273,1216,384],{"class":330},[273,1218,340],{"class":290},[273,1220,389],{"class":314},[273,1222,346],{"class":290},[273,1224,394],{"class":330},[273,1226,397],{"class":290},[273,1228,1230],{"class":275,"line":1229},25,[273,1231,403],{"class":290},[273,1233,1235],{"class":275,"line":1234},26,[273,1236,305],{"emptyLinePlaceholder":304},[273,1238,1240,1242,1244,1246,1248,1250,1253,1255,1257,1260,1262,1264,1266,1268,1270],{"class":275,"line":1239},27,[273,1241,327],{"class":286},[273,1243,331],{"class":330},[273,1245,334],{"class":290},[273,1247,1146],{"class":330},[273,1249,340],{"class":290},[273,1251,1252],{"class":314},"WriteToFile",[273,1254,346],{"class":290},[273,1256,359],{"class":290},[273,1258,1259],{"class":362},"hello.pdf",[273,1261,359],{"class":290},[273,1263,500],{"class":290},[273,1265,331],{"class":330},[273,1267,373],{"class":290},[273,1269,376],{"class":290},[273,1271,321],{"class":290},[273,1273,1275,1277,1279,1281,1283,1285],{"class":275,"line":1274},28,[273,1276,384],{"class":330},[273,1278,340],{"class":290},[273,1280,389],{"class":314},[273,1282,346],{"class":290},[273,1284,394],{"class":330},[273,1286,397],{"class":290},[273,1288,1290],{"class":275,"line":1289},29,[273,1291,403],{"class":290},[273,1293,1295],{"class":275,"line":1294},30,[273,1296,409],{"class":290},[19,1298,1299],{},[22,1300,1301],{},"After — gpdf:",[264,1303,1305],{"className":266,"code":1304,"language":268,"meta":269,"style":269},"package main\n\nimport (\n    \"log\"\n    \"os\"\n\n    \"github.com/gpdf-dev/gpdf\"\n    \"github.com/gpdf-dev/gpdf/document\"\n    \"github.com/gpdf-dev/gpdf/template\"\n)\n\nfunc main() {\n    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(document.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n    )\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"Hello, World!\", template.FontSize(24), template.Bold())\n        })\n    })\n\n    data, err := doc.Generate()\n    if err != nil {\n        log.Fatal(err)\n    }\n    if err := os.WriteFile(\"hello.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n",[38,1306,1307,1313,1317,1323,1331,1339,1343,1351,1360,1369,1373,1377,1387,1405,1428,1463,1468,1472,1489,1521,1557,1601,1606,1611,1615,1635,1647,1661,1665,1708,1722,1727],{"__ignoreMap":269},[273,1308,1309,1311],{"class":275,"line":276},[273,1310,932],{"class":290},[273,1312,935],{"class":294},[273,1314,1315],{"class":275,"line":283},[273,1316,305],{"emptyLinePlaceholder":304},[273,1318,1319,1321],{"class":275,"line":301},[273,1320,287],{"class":286},[273,1322,946],{"class":290},[273,1324,1325,1327,1329],{"class":275,"line":308},[273,1326,951],{"class":290},[273,1328,954],{"class":294},[273,1330,298],{"class":290},[273,1332,1333,1335,1337],{"class":275,"line":324},[273,1334,951],{"class":290},[273,1336,349],{"class":294},[273,1338,298],{"class":290},[273,1340,1341],{"class":275,"line":381},[273,1342,305],{"emptyLinePlaceholder":304},[273,1344,1345,1347,1349],{"class":275,"line":400},[273,1346,951],{"class":290},[273,1348,543],{"class":294},[273,1350,298],{"class":290},[273,1352,1353,1355,1358],{"class":275,"line":406},[273,1354,951],{"class":290},[273,1356,1357],{"class":294},"github.com/gpdf-dev/gpdf/document",[273,1359,298],{"class":290},[273,1361,1362,1364,1367],{"class":275,"line":988},[273,1363,951],{"class":290},[273,1365,1366],{"class":294},"github.com/gpdf-dev/gpdf/template",[273,1368,298],{"class":290},[273,1370,1371],{"class":275,"line":993},[273,1372,397],{"class":290},[273,1374,1375],{"class":275,"line":998},[273,1376,305],{"emptyLinePlaceholder":304},[273,1378,1379,1381,1383,1385],{"class":275,"line":1009},[273,1380,311],{"class":290},[273,1382,1085],{"class":314},[273,1384,318],{"class":290},[273,1386,321],{"class":290},[273,1388,1389,1392,1394,1397,1399,1402],{"class":275,"line":1050},[273,1390,1391],{"class":330},"    doc ",[273,1393,334],{"class":290},[273,1395,1396],{"class":330}," gpdf",[273,1398,340],{"class":290},[273,1400,1401],{"class":314},"NewDocument",[273,1403,1404],{"class":290},"(\n",[273,1406,1407,1410,1412,1415,1417,1420,1422,1425],{"class":275,"line":1065},[273,1408,1409],{"class":330},"        gpdf",[273,1411,340],{"class":290},[273,1413,1414],{"class":314},"WithPageSize",[273,1416,346],{"class":290},[273,1418,1419],{"class":330},"document",[273,1421,340],{"class":290},[273,1423,1424],{"class":330},"A4",[273,1426,1427],{"class":290},"),\n",[273,1429,1430,1432,1434,1437,1439,1441,1443,1446,1448,1450,1452,1455,1457,1460],{"class":275,"line":1070},[273,1431,1409],{"class":330},[273,1433,340],{"class":290},[273,1435,1436],{"class":314},"WithMargins",[273,1438,346],{"class":290},[273,1440,1419],{"class":330},[273,1442,340],{"class":290},[273,1444,1445],{"class":314},"UniformEdges",[273,1447,346],{"class":290},[273,1449,1419],{"class":330},[273,1451,340],{"class":290},[273,1453,1454],{"class":314},"Mm",[273,1456,346],{"class":290},[273,1458,1459],{"class":1178},"20",[273,1461,1462],{"class":290},"))),\n",[273,1464,1465],{"class":275,"line":1075},[273,1466,1467],{"class":290},"    )\n",[273,1469,1470],{"class":275,"line":1080},[273,1471,305],{"emptyLinePlaceholder":304},[273,1473,1474,1477,1479,1482,1484,1487],{"class":275,"line":1092},[273,1475,1476],{"class":330},"    page ",[273,1478,334],{"class":290},[273,1480,1481],{"class":330}," doc",[273,1483,340],{"class":290},[273,1485,1486],{"class":314},"AddPage",[273,1488,1108],{"class":290},[273,1490,1491,1494,1496,1499,1502,1506,1509,1512,1514,1517,1519],{"class":275,"line":1111},[273,1492,1493],{"class":330},"    page",[273,1495,340],{"class":290},[273,1497,1498],{"class":314},"AutoRow",[273,1500,1501],{"class":290},"(func(",[273,1503,1505],{"class":1504},"sHdIc","r",[273,1507,1508],{"class":290}," *",[273,1510,1511],{"class":294},"template",[273,1513,340],{"class":290},[273,1515,1516],{"class":294},"RowBuilder",[273,1518,585],{"class":290},[273,1520,321],{"class":290},[273,1522,1523,1526,1528,1531,1533,1536,1538,1541,1544,1546,1548,1550,1553,1555],{"class":275,"line":1133},[273,1524,1525],{"class":330},"        r",[273,1527,340],{"class":290},[273,1529,1530],{"class":314},"Col",[273,1532,346],{"class":290},[273,1534,1535],{"class":1178},"12",[273,1537,437],{"class":290},[273,1539,1540],{"class":290}," func(",[273,1542,1543],{"class":1504},"c",[273,1545,1508],{"class":290},[273,1547,1511],{"class":294},[273,1549,340],{"class":290},[273,1551,1552],{"class":294},"ColBuilder",[273,1554,585],{"class":290},[273,1556,321],{"class":290},[273,1558,1559,1562,1564,1567,1569,1571,1573,1575,1577,1580,1582,1585,1587,1589,1591,1593,1595,1598],{"class":275,"line":1138},[273,1560,1561],{"class":330},"            c",[273,1563,340],{"class":290},[273,1565,1566],{"class":314},"Text",[273,1568,346],{"class":290},[273,1570,359],{"class":290},[273,1572,1158],{"class":362},[273,1574,359],{"class":290},[273,1576,437],{"class":290},[273,1578,1579],{"class":330}," template",[273,1581,340],{"class":290},[273,1583,1584],{"class":314},"FontSize",[273,1586,346],{"class":290},[273,1588,1179],{"class":1178},[273,1590,490],{"class":290},[273,1592,1579],{"class":330},[273,1594,340],{"class":290},[273,1596,1597],{"class":314},"Bold",[273,1599,1600],{"class":290},"())\n",[273,1602,1603],{"class":275,"line":1165},[273,1604,1605],{"class":290},"        })\n",[273,1607,1608],{"class":275,"line":1184},[273,1609,1610],{"class":290},"    })\n",[273,1612,1613],{"class":275,"line":1214},[273,1614,305],{"emptyLinePlaceholder":304},[273,1616,1617,1620,1622,1624,1626,1628,1630,1633],{"class":275,"line":1229},[273,1618,1619],{"class":330},"    data",[273,1621,437],{"class":290},[273,1623,331],{"class":330},[273,1625,334],{"class":290},[273,1627,1481],{"class":330},[273,1629,340],{"class":290},[273,1631,1632],{"class":314},"Generate",[273,1634,1108],{"class":290},[273,1636,1637,1639,1641,1643,1645],{"class":275,"line":1234},[273,1638,327],{"class":286},[273,1640,331],{"class":330},[273,1642,373],{"class":290},[273,1644,376],{"class":290},[273,1646,321],{"class":290},[273,1648,1649,1651,1653,1655,1657,1659],{"class":275,"line":1239},[273,1650,384],{"class":330},[273,1652,340],{"class":290},[273,1654,389],{"class":314},[273,1656,346],{"class":290},[273,1658,394],{"class":330},[273,1660,397],{"class":290},[273,1662,1663],{"class":275,"line":1274},[273,1664,403],{"class":290},[273,1666,1667,1669,1671,1673,1675,1677,1680,1682,1684,1686,1688,1690,1693,1695,1698,1700,1702,1704,1706],{"class":275,"line":1289},[273,1668,327],{"class":286},[273,1670,331],{"class":330},[273,1672,334],{"class":290},[273,1674,445],{"class":330},[273,1676,340],{"class":290},[273,1678,1679],{"class":314},"WriteFile",[273,1681,346],{"class":290},[273,1683,359],{"class":290},[273,1685,1259],{"class":362},[273,1687,359],{"class":290},[273,1689,437],{"class":290},[273,1691,1692],{"class":330}," data",[273,1694,437],{"class":290},[273,1696,1697],{"class":1178}," 0o644",[273,1699,500],{"class":290},[273,1701,331],{"class":330},[273,1703,373],{"class":290},[273,1705,376],{"class":290},[273,1707,321],{"class":290},[273,1709,1710,1712,1714,1716,1718,1720],{"class":275,"line":1294},[273,1711,384],{"class":330},[273,1713,340],{"class":290},[273,1715,389],{"class":314},[273,1717,346],{"class":290},[273,1719,394],{"class":330},[273,1721,397],{"class":290},[273,1723,1725],{"class":275,"line":1724},31,[273,1726,403],{"class":290},[273,1728,1730],{"class":275,"line":1729},32,[273,1731,409],{"class":290},[19,1733,1734,1735,1737,1738,1740],{},"3 つ違う。",[38,1736,536],{}," ブロックが消えた — キーも環境変数もない。構築は mutating ではなく options 渡し。テキストは独立した ",[38,1739,889],{}," ではなく行とカラムの中に座る。配置はグリッドが行うので座標を選ぶ必要がない。",[14,1742,1744],{"id":1743},"before-after-2-請求書の明細テーブル","Before / After 2: 請求書の明細テーブル",[19,1746,1747,1748,1750,1751,1754,1755,762,1758,1761],{},"unipdf の creator API でテーブルを書くと長くなる。",[38,1749,893],{}," を作り、絶対比率で ",[38,1752,1753],{},"SetColumnWidths"," し、",[38,1756,1757],{},"NewCell",[38,1759,1760],{},"SetContent"," で 1 セルずつ組み立て、罫線・整列を手で設定する。",[19,1763,1764],{},[22,1765,922],{},[264,1767,1769],{"className":266,"code":1768,"language":268,"meta":269,"style":269},"table := c.NewTable(4)\ntable.SetColumnWidths(0.5, 0.15, 0.15, 0.2)\n\nheaderStyle := c.NewTextStyle()\nheaderStyle.Font, _ = model.NewStandard14Font(\"Helvetica-Bold\")\nheaderStyle.FontSize = 11\nheaderStyle.Color = creator.ColorWhite\n\ndrawHeaderCell := func(text string) {\n    cell := table.NewCell()\n    cell.SetBackgroundColor(creator.ColorRGBFromHex(\"#1A237E\"))\n    cell.SetBorder(creator.CellBorderSideAll, creator.CellBorderStyleSingle, 0.5)\n\n    p := c.NewStyledParagraph()\n    chunk := p.Append(text)\n    chunk.Style = headerStyle\n    cell.SetContent(p)\n}\n\nfor _, h := range []string{\"品目\", \"数量\", \"単価\", \"金額\"} {\n    drawHeaderCell(h)\n}\n\nfor _, row := range items {\n    for _, cellText := range row {\n        cell := table.NewCell()\n        cell.SetBorder(creator.CellBorderSideAll, creator.CellBorderStyleSingle, 0.3)\n\n        p := c.NewParagraph(cellText)\n        p.SetFontSize(11)\n        cell.SetContent(p)\n    }\n}\n\nif err := c.Draw(table); err != nil {\n    log.Fatal(err)\n}\n",[38,1770,1771,1792,1821,1825,1841,1877,1891,1909,1913,1932,1948,1979,2013,2017,2032,2053,2068,2082,2086,2090,2155,2167,2171,2175,2196,2216,2231,2263,2267,2287,2303,2317,2321,2326,2331,2361,2377],{"__ignoreMap":269},[273,1772,1773,1776,1778,1780,1782,1785,1787,1790],{"class":275,"line":276},[273,1774,1775],{"class":330},"table ",[273,1777,334],{"class":290},[273,1779,1146],{"class":330},[273,1781,340],{"class":290},[273,1783,1784],{"class":314},"NewTable",[273,1786,346],{"class":290},[273,1788,1789],{"class":1178},"4",[273,1791,397],{"class":290},[273,1793,1794,1796,1798,1800,1802,1805,1807,1810,1812,1814,1816,1819],{"class":275,"line":283},[273,1795,121],{"class":330},[273,1797,340],{"class":290},[273,1799,1753],{"class":314},[273,1801,346],{"class":290},[273,1803,1804],{"class":1178},"0.5",[273,1806,437],{"class":290},[273,1808,1809],{"class":1178}," 0.15",[273,1811,437],{"class":290},[273,1813,1809],{"class":1178},[273,1815,437],{"class":290},[273,1817,1818],{"class":1178}," 0.2",[273,1820,397],{"class":290},[273,1822,1823],{"class":275,"line":301},[273,1824,305],{"emptyLinePlaceholder":304},[273,1826,1827,1830,1832,1834,1836,1839],{"class":275,"line":308},[273,1828,1829],{"class":330},"headerStyle ",[273,1831,334],{"class":290},[273,1833,1146],{"class":330},[273,1835,340],{"class":290},[273,1837,1838],{"class":314},"NewTextStyle",[273,1840,1108],{"class":290},[273,1842,1843,1846,1848,1851,1853,1855,1858,1861,1863,1866,1868,1870,1873,1875],{"class":275,"line":324},[273,1844,1845],{"class":330},"headerStyle",[273,1847,340],{"class":290},[273,1849,1850],{"class":330},"Font",[273,1852,437],{"class":290},[273,1854,440],{"class":330},[273,1856,1857],{"class":290},"=",[273,1859,1860],{"class":330}," model",[273,1862,340],{"class":290},[273,1864,1865],{"class":314},"NewStandard14Font",[273,1867,346],{"class":290},[273,1869,359],{"class":290},[273,1871,1872],{"class":362},"Helvetica-Bold",[273,1874,359],{"class":290},[273,1876,397],{"class":290},[273,1878,1879,1881,1883,1886,1888],{"class":275,"line":381},[273,1880,1845],{"class":330},[273,1882,340],{"class":290},[273,1884,1885],{"class":330},"FontSize ",[273,1887,1857],{"class":290},[273,1889,1890],{"class":1178}," 11\n",[273,1892,1893,1895,1897,1900,1902,1904,1906],{"class":275,"line":400},[273,1894,1845],{"class":330},[273,1896,340],{"class":290},[273,1898,1899],{"class":330},"Color ",[273,1901,1857],{"class":290},[273,1903,1100],{"class":330},[273,1905,340],{"class":290},[273,1907,1908],{"class":330},"ColorWhite\n",[273,1910,1911],{"class":275,"line":406},[273,1912,305],{"emptyLinePlaceholder":304},[273,1914,1915,1918,1920,1922,1925,1928,1930],{"class":275,"line":988},[273,1916,1917],{"class":330},"drawHeaderCell ",[273,1919,334],{"class":290},[273,1921,1540],{"class":290},[273,1923,1924],{"class":1504},"text",[273,1926,1927],{"class":481}," string",[273,1929,585],{"class":290},[273,1931,321],{"class":290},[273,1933,1934,1937,1939,1942,1944,1946],{"class":275,"line":993},[273,1935,1936],{"class":330},"    cell ",[273,1938,334],{"class":290},[273,1940,1941],{"class":330}," table",[273,1943,340],{"class":290},[273,1945,1757],{"class":314},[273,1947,1108],{"class":290},[273,1949,1950,1953,1955,1958,1960,1962,1964,1967,1969,1971,1974,1976],{"class":275,"line":998},[273,1951,1952],{"class":330},"    cell",[273,1954,340],{"class":290},[273,1956,1957],{"class":314},"SetBackgroundColor",[273,1959,346],{"class":290},[273,1961,44],{"class":330},[273,1963,340],{"class":290},[273,1965,1966],{"class":314},"ColorRGBFromHex",[273,1968,346],{"class":290},[273,1970,359],{"class":290},[273,1972,1973],{"class":362},"#1A237E",[273,1975,359],{"class":290},[273,1977,1978],{"class":290},"))\n",[273,1980,1981,1983,1985,1988,1990,1992,1994,1997,1999,2001,2003,2006,2008,2011],{"class":275,"line":1009},[273,1982,1952],{"class":330},[273,1984,340],{"class":290},[273,1986,1987],{"class":314},"SetBorder",[273,1989,346],{"class":290},[273,1991,44],{"class":330},[273,1993,340],{"class":290},[273,1995,1996],{"class":330},"CellBorderSideAll",[273,1998,437],{"class":290},[273,2000,1100],{"class":330},[273,2002,340],{"class":290},[273,2004,2005],{"class":330},"CellBorderStyleSingle",[273,2007,437],{"class":290},[273,2009,2010],{"class":1178}," 0.5",[273,2012,397],{"class":290},[273,2014,2015],{"class":275,"line":1050},[273,2016,305],{"emptyLinePlaceholder":304},[273,2018,2019,2021,2023,2025,2027,2030],{"class":275,"line":1065},[273,2020,1141],{"class":330},[273,2022,334],{"class":290},[273,2024,1146],{"class":330},[273,2026,340],{"class":290},[273,2028,2029],{"class":314},"NewStyledParagraph",[273,2031,1108],{"class":290},[273,2033,2034,2037,2039,2042,2044,2047,2049,2051],{"class":275,"line":1070},[273,2035,2036],{"class":330},"    chunk ",[273,2038,334],{"class":290},[273,2040,2041],{"class":330}," p",[273,2043,340],{"class":290},[273,2045,2046],{"class":314},"Append",[273,2048,346],{"class":290},[273,2050,1924],{"class":330},[273,2052,397],{"class":290},[273,2054,2055,2058,2060,2063,2065],{"class":275,"line":1075},[273,2056,2057],{"class":330},"    chunk",[273,2059,340],{"class":290},[273,2061,2062],{"class":330},"Style ",[273,2064,1857],{"class":290},[273,2066,2067],{"class":330}," headerStyle\n",[273,2069,2070,2072,2074,2076,2078,2080],{"class":275,"line":1080},[273,2071,1952],{"class":330},[273,2073,340],{"class":290},[273,2075,1760],{"class":314},[273,2077,346],{"class":290},[273,2079,19],{"class":330},[273,2081,397],{"class":290},[273,2083,2084],{"class":275,"line":1092},[273,2085,409],{"class":290},[273,2087,2088],{"class":275,"line":1111},[273,2089,305],{"emptyLinePlaceholder":304},[273,2091,2092,2095,2098,2100,2103,2105,2108,2111,2113,2116,2118,2121,2123,2125,2127,2130,2132,2134,2136,2139,2141,2143,2145,2148,2150,2153],{"class":275,"line":1133},[273,2093,2094],{"class":286},"for",[273,2096,2097],{"class":330}," _",[273,2099,437],{"class":290},[273,2101,2102],{"class":330}," h ",[273,2104,334],{"class":290},[273,2106,2107],{"class":286}," range",[273,2109,2110],{"class":290}," []",[273,2112,482],{"class":481},[273,2114,2115],{"class":290},"{",[273,2117,359],{"class":290},[273,2119,2120],{"class":362},"品目",[273,2122,359],{"class":290},[273,2124,437],{"class":290},[273,2126,291],{"class":290},[273,2128,2129],{"class":362},"数量",[273,2131,359],{"class":290},[273,2133,437],{"class":290},[273,2135,291],{"class":290},[273,2137,2138],{"class":362},"単価",[273,2140,359],{"class":290},[273,2142,437],{"class":290},[273,2144,291],{"class":290},[273,2146,2147],{"class":362},"金額",[273,2149,359],{"class":290},[273,2151,2152],{"class":290},"}",[273,2154,321],{"class":290},[273,2156,2157,2160,2162,2165],{"class":275,"line":1138},[273,2158,2159],{"class":314},"    drawHeaderCell",[273,2161,346],{"class":290},[273,2163,2164],{"class":330},"h",[273,2166,397],{"class":290},[273,2168,2169],{"class":275,"line":1165},[273,2170,409],{"class":290},[273,2172,2173],{"class":275,"line":1184},[273,2174,305],{"emptyLinePlaceholder":304},[273,2176,2177,2179,2181,2183,2186,2188,2190,2193],{"class":275,"line":1214},[273,2178,2094],{"class":286},[273,2180,2097],{"class":330},[273,2182,437],{"class":290},[273,2184,2185],{"class":330}," row ",[273,2187,334],{"class":290},[273,2189,2107],{"class":286},[273,2191,2192],{"class":330}," items ",[273,2194,2195],{"class":290},"{\n",[273,2197,2198,2201,2203,2205,2208,2210,2212,2214],{"class":275,"line":1229},[273,2199,2200],{"class":286},"    for",[273,2202,2097],{"class":330},[273,2204,437],{"class":290},[273,2206,2207],{"class":330}," cellText ",[273,2209,334],{"class":290},[273,2211,2107],{"class":286},[273,2213,2185],{"class":330},[273,2215,2195],{"class":290},[273,2217,2218,2221,2223,2225,2227,2229],{"class":275,"line":1234},[273,2219,2220],{"class":330},"        cell ",[273,2222,334],{"class":290},[273,2224,1941],{"class":330},[273,2226,340],{"class":290},[273,2228,1757],{"class":314},[273,2230,1108],{"class":290},[273,2232,2233,2236,2238,2240,2242,2244,2246,2248,2250,2252,2254,2256,2258,2261],{"class":275,"line":1239},[273,2234,2235],{"class":330},"        cell",[273,2237,340],{"class":290},[273,2239,1987],{"class":314},[273,2241,346],{"class":290},[273,2243,44],{"class":330},[273,2245,340],{"class":290},[273,2247,1996],{"class":330},[273,2249,437],{"class":290},[273,2251,1100],{"class":330},[273,2253,340],{"class":290},[273,2255,2005],{"class":330},[273,2257,437],{"class":290},[273,2259,2260],{"class":1178}," 0.3",[273,2262,397],{"class":290},[273,2264,2265],{"class":275,"line":1274},[273,2266,305],{"emptyLinePlaceholder":304},[273,2268,2269,2272,2274,2276,2278,2280,2282,2285],{"class":275,"line":1289},[273,2270,2271],{"class":330},"        p ",[273,2273,334],{"class":290},[273,2275,1146],{"class":330},[273,2277,340],{"class":290},[273,2279,1151],{"class":314},[273,2281,346],{"class":290},[273,2283,2284],{"class":330},"cellText",[273,2286,397],{"class":290},[273,2288,2289,2292,2294,2296,2298,2301],{"class":275,"line":1294},[273,2290,2291],{"class":330},"        p",[273,2293,340],{"class":290},[273,2295,1173],{"class":314},[273,2297,346],{"class":290},[273,2299,2300],{"class":1178},"11",[273,2302,397],{"class":290},[273,2304,2305,2307,2309,2311,2313,2315],{"class":275,"line":1724},[273,2306,2235],{"class":330},[273,2308,340],{"class":290},[273,2310,1760],{"class":314},[273,2312,346],{"class":290},[273,2314,19],{"class":330},[273,2316,397],{"class":290},[273,2318,2319],{"class":275,"line":1729},[273,2320,403],{"class":290},[273,2322,2324],{"class":275,"line":2323},33,[273,2325,409],{"class":290},[273,2327,2329],{"class":275,"line":2328},34,[273,2330,305],{"emptyLinePlaceholder":304},[273,2332,2334,2337,2339,2341,2343,2345,2347,2349,2351,2353,2355,2357,2359],{"class":275,"line":2333},35,[273,2335,2336],{"class":286},"if",[273,2338,331],{"class":330},[273,2340,334],{"class":290},[273,2342,1146],{"class":330},[273,2344,340],{"class":290},[273,2346,1197],{"class":314},[273,2348,346],{"class":290},[273,2350,121],{"class":330},[273,2352,500],{"class":290},[273,2354,331],{"class":330},[273,2356,373],{"class":290},[273,2358,376],{"class":290},[273,2360,321],{"class":290},[273,2362,2364,2367,2369,2371,2373,2375],{"class":275,"line":2363},36,[273,2365,2366],{"class":330},"    log",[273,2368,340],{"class":290},[273,2370,389],{"class":314},[273,2372,346],{"class":290},[273,2374,394],{"class":330},[273,2376,397],{"class":290},[273,2378,2380],{"class":275,"line":2379},37,[273,2381,409],{"class":290},[19,2383,2384],{},"罫線、セルごとの content、ヘッダ描画ループ — どれも機械的な作業。",[19,2386,2387],{},[22,2388,1301],{},[264,2390,2392],{"className":266,"code":2391,"language":268,"meta":269,"style":269},"page.AutoRow(func(r *template.RowBuilder) {\n    r.Col(12, func(c *template.ColBuilder) {\n        c.Table(\n            []string{\"品目\", \"数量\", \"単価\", \"金額\"},\n            [][]string{\n                {\"フロントエンド開発\", \"40 時間\", \"¥15,000\", \"¥600,000\"},\n                {\"バックエンド開発\",   \"60 時間\", \"¥15,000\", \"¥900,000\"},\n                {\"UI デザイン\",        \"20 時間\", \"¥12,000\", \"¥240,000\"},\n            },\n            template.ColumnWidths(50, 15, 15, 20),\n            template.TableHeaderStyle(\n                template.Bold(),\n                template.TextColor(pdf.White),\n                template.BgColor(pdf.RGBHex(0x1A237E)),\n            ),\n            template.TableStripe(pdf.RGBHex(0xF5F5F5)),\n        )\n    })\n})\n",[38,2393,2394,2419,2450,2461,2503,2512,2553,2593,2634,2639,2670,2681,2693,2714,2740,2745,2769,2774,2778],{"__ignoreMap":269},[273,2395,2396,2399,2401,2403,2405,2407,2409,2411,2413,2415,2417],{"class":275,"line":276},[273,2397,2398],{"class":330},"page",[273,2400,340],{"class":290},[273,2402,1498],{"class":314},[273,2404,1501],{"class":290},[273,2406,1505],{"class":1504},[273,2408,1508],{"class":290},[273,2410,1511],{"class":294},[273,2412,340],{"class":290},[273,2414,1516],{"class":294},[273,2416,585],{"class":290},[273,2418,321],{"class":290},[273,2420,2421,2424,2426,2428,2430,2432,2434,2436,2438,2440,2442,2444,2446,2448],{"class":275,"line":283},[273,2422,2423],{"class":330},"    r",[273,2425,340],{"class":290},[273,2427,1530],{"class":314},[273,2429,346],{"class":290},[273,2431,1535],{"class":1178},[273,2433,437],{"class":290},[273,2435,1540],{"class":290},[273,2437,1543],{"class":1504},[273,2439,1508],{"class":290},[273,2441,1511],{"class":294},[273,2443,340],{"class":290},[273,2445,1552],{"class":294},[273,2447,585],{"class":290},[273,2449,321],{"class":290},[273,2451,2452,2455,2457,2459],{"class":275,"line":301},[273,2453,2454],{"class":330},"        c",[273,2456,340],{"class":290},[273,2458,893],{"class":314},[273,2460,1404],{"class":290},[273,2462,2463,2466,2468,2470,2472,2474,2476,2478,2480,2482,2484,2486,2488,2490,2492,2494,2496,2498,2500],{"class":275,"line":308},[273,2464,2465],{"class":290},"            []",[273,2467,482],{"class":481},[273,2469,2115],{"class":290},[273,2471,359],{"class":290},[273,2473,2120],{"class":362},[273,2475,359],{"class":290},[273,2477,437],{"class":290},[273,2479,291],{"class":290},[273,2481,2129],{"class":362},[273,2483,359],{"class":290},[273,2485,437],{"class":290},[273,2487,291],{"class":290},[273,2489,2138],{"class":362},[273,2491,359],{"class":290},[273,2493,437],{"class":290},[273,2495,291],{"class":290},[273,2497,2147],{"class":362},[273,2499,359],{"class":290},[273,2501,2502],{"class":290},"},\n",[273,2504,2505,2508,2510],{"class":275,"line":324},[273,2506,2507],{"class":290},"            [][]",[273,2509,482],{"class":481},[273,2511,2195],{"class":290},[273,2513,2514,2517,2519,2522,2524,2526,2528,2531,2533,2535,2537,2540,2542,2544,2546,2549,2551],{"class":275,"line":381},[273,2515,2516],{"class":290},"                {",[273,2518,359],{"class":290},[273,2520,2521],{"class":362},"フロントエンド開発",[273,2523,359],{"class":290},[273,2525,437],{"class":290},[273,2527,291],{"class":290},[273,2529,2530],{"class":362},"40 時間",[273,2532,359],{"class":290},[273,2534,437],{"class":290},[273,2536,291],{"class":290},[273,2538,2539],{"class":362},"¥15,000",[273,2541,359],{"class":290},[273,2543,437],{"class":290},[273,2545,291],{"class":290},[273,2547,2548],{"class":362},"¥600,000",[273,2550,359],{"class":290},[273,2552,2502],{"class":290},[273,2554,2555,2557,2559,2562,2564,2566,2569,2572,2574,2576,2578,2580,2582,2584,2586,2589,2591],{"class":275,"line":400},[273,2556,2516],{"class":290},[273,2558,359],{"class":290},[273,2560,2561],{"class":362},"バックエンド開発",[273,2563,359],{"class":290},[273,2565,437],{"class":290},[273,2567,2568],{"class":290},"   \"",[273,2570,2571],{"class":362},"60 時間",[273,2573,359],{"class":290},[273,2575,437],{"class":290},[273,2577,291],{"class":290},[273,2579,2539],{"class":362},[273,2581,359],{"class":290},[273,2583,437],{"class":290},[273,2585,291],{"class":290},[273,2587,2588],{"class":362},"¥900,000",[273,2590,359],{"class":290},[273,2592,2502],{"class":290},[273,2594,2595,2597,2599,2602,2604,2606,2609,2612,2614,2616,2618,2621,2623,2625,2627,2630,2632],{"class":275,"line":406},[273,2596,2516],{"class":290},[273,2598,359],{"class":290},[273,2600,2601],{"class":362},"UI デザイン",[273,2603,359],{"class":290},[273,2605,437],{"class":290},[273,2607,2608],{"class":290},"        \"",[273,2610,2611],{"class":362},"20 時間",[273,2613,359],{"class":290},[273,2615,437],{"class":290},[273,2617,291],{"class":290},[273,2619,2620],{"class":362},"¥12,000",[273,2622,359],{"class":290},[273,2624,437],{"class":290},[273,2626,291],{"class":290},[273,2628,2629],{"class":362},"¥240,000",[273,2631,359],{"class":290},[273,2633,2502],{"class":290},[273,2635,2636],{"class":275,"line":988},[273,2637,2638],{"class":290},"            },\n",[273,2640,2641,2644,2646,2649,2651,2654,2656,2659,2661,2663,2665,2668],{"class":275,"line":993},[273,2642,2643],{"class":330},"            template",[273,2645,340],{"class":290},[273,2647,2648],{"class":314},"ColumnWidths",[273,2650,346],{"class":290},[273,2652,2653],{"class":1178},"50",[273,2655,437],{"class":290},[273,2657,2658],{"class":1178}," 15",[273,2660,437],{"class":290},[273,2662,2658],{"class":1178},[273,2664,437],{"class":290},[273,2666,2667],{"class":1178}," 20",[273,2669,1427],{"class":290},[273,2671,2672,2674,2676,2679],{"class":275,"line":998},[273,2673,2643],{"class":330},[273,2675,340],{"class":290},[273,2677,2678],{"class":314},"TableHeaderStyle",[273,2680,1404],{"class":290},[273,2682,2683,2686,2688,2690],{"class":275,"line":1009},[273,2684,2685],{"class":330},"                template",[273,2687,340],{"class":290},[273,2689,1597],{"class":314},[273,2691,2692],{"class":290},"(),\n",[273,2694,2695,2697,2699,2702,2704,2707,2709,2712],{"class":275,"line":1050},[273,2696,2685],{"class":330},[273,2698,340],{"class":290},[273,2700,2701],{"class":314},"TextColor",[273,2703,346],{"class":290},[273,2705,2706],{"class":330},"pdf",[273,2708,340],{"class":290},[273,2710,2711],{"class":330},"White",[273,2713,1427],{"class":290},[273,2715,2716,2718,2720,2723,2725,2727,2729,2732,2734,2737],{"class":275,"line":1065},[273,2717,2685],{"class":330},[273,2719,340],{"class":290},[273,2721,2722],{"class":314},"BgColor",[273,2724,346],{"class":290},[273,2726,2706],{"class":330},[273,2728,340],{"class":290},[273,2730,2731],{"class":314},"RGBHex",[273,2733,346],{"class":290},[273,2735,2736],{"class":1178},"0x1A237E",[273,2738,2739],{"class":290},")),\n",[273,2741,2742],{"class":275,"line":1070},[273,2743,2744],{"class":290},"            ),\n",[273,2746,2747,2749,2751,2754,2756,2758,2760,2762,2764,2767],{"class":275,"line":1075},[273,2748,2643],{"class":330},[273,2750,340],{"class":290},[273,2752,2753],{"class":314},"TableStripe",[273,2755,346],{"class":290},[273,2757,2706],{"class":330},[273,2759,340],{"class":290},[273,2761,2731],{"class":314},[273,2763,346],{"class":290},[273,2765,2766],{"class":1178},"0xF5F5F5",[273,2768,2739],{"class":290},[273,2770,2771],{"class":275,"line":1080},[273,2772,2773],{"class":290},"        )\n",[273,2775,2776],{"class":275,"line":1092},[273,2777,1610],{"class":290},[273,2779,2780],{"class":275,"line":1111},[273,2781,2782],{"class":290},"})\n",[19,2784,2785,25,2787,2790,2791,2794],{},[38,2786,2648],{},[22,2788,2789],{},"そのテーブルが入っているカラムの幅に対するパーセンテージ","。ページ全体の絶対比率ではない。同じテーブルを ",[38,2792,2793],{},"r.Col(6, ...)"," に入れれば、テーブルが行の半分を占め、列幅は同じ比率で再分配される。ページ分割は自動で、本文がボトムマージンを越えれば次ページにヘッダが繰り返される — 何も配線しなくていい。",[19,2796,2797,2798,2801,2802,2805],{},"具体的な数字も挙げておくと、unipdf の Table を 100 行の請求書ベンチで回すとレンダリング 1 回あたりおおむね ",[22,2799,2800],{},"8.6 ms","。gpdf の同じワークロードは ",[22,2803,2804],{},"108 µs"," (約 80 倍速い)。これはレイアウトエンジンが各行を 1 回計測してシングルパスでページを書き出すため。1 通の請求書なら差は見えないが、cron で大量にバッチ処理する場合「キューが要るかどうか」の境界が変わる。",[19,2807,2808,2809,2812],{},"なお適格請求書 (インボイス制度) や電子帳簿保存法対応の項目 (登録番号・税率内訳・改ざん防止) は、レイアウトとしては gpdf でそのまま表現できる。タイムスタンプは ",[38,2810,2811],{},"gpdf.SignDocument"," の RFC 3161 TSA オプション側で扱う。",[14,2814,2816],{"id":2815},"before-after-3-composite-font-の作法なしで日本語","Before / After 3: composite font の作法なしで日本語",[19,2818,2819],{},"unipdf も CJK は対応している。ただし手数が多い。ディスク上の TTF から composite font を構築し、style font に設定し、すべての paragraph に通す。フォールバックを入れたければ自分で配線する。",[19,2821,2822],{},[22,2823,922],{},[264,2825,2827],{"className":266,"code":2826,"language":268,"meta":269,"style":269},"font, err := model.NewCompositePdfFontFromTTFFile(\"NotoSansJP-Regular.ttf\")\nif err != nil {\n    log.Fatal(err)\n}\n\nc := creator.New()\nc.SetPageSize(creator.PageSizeA4)\n\nstyle := c.NewTextStyle()\nstyle.Font = font\nstyle.FontSize = 14\n\np := c.NewStyledParagraph()\np.Append(\"こんにちは、世界。\").Style = style\nif err := c.Draw(p); err != nil {\n    log.Fatal(err)\n}\n\nc.WriteToFile(\"ja.pdf\")\n",[38,2828,2829,2858,2870,2884,2888,2892,2907,2925,2929,2944,2959,2972,2976,2991,3018,3046,3060,3064,3068],{"__ignoreMap":269},[273,2830,2831,2834,2836,2838,2840,2842,2844,2847,2849,2851,2854,2856],{"class":275,"line":276},[273,2832,2833],{"class":330},"font",[273,2835,437],{"class":290},[273,2837,331],{"class":330},[273,2839,334],{"class":290},[273,2841,1860],{"class":330},[273,2843,340],{"class":290},[273,2845,2846],{"class":314},"NewCompositePdfFontFromTTFFile",[273,2848,346],{"class":290},[273,2850,359],{"class":290},[273,2852,2853],{"class":362},"NotoSansJP-Regular.ttf",[273,2855,359],{"class":290},[273,2857,397],{"class":290},[273,2859,2860,2862,2864,2866,2868],{"class":275,"line":283},[273,2861,2336],{"class":286},[273,2863,331],{"class":330},[273,2865,373],{"class":290},[273,2867,376],{"class":290},[273,2869,321],{"class":290},[273,2871,2872,2874,2876,2878,2880,2882],{"class":275,"line":301},[273,2873,2366],{"class":330},[273,2875,340],{"class":290},[273,2877,389],{"class":314},[273,2879,346],{"class":290},[273,2881,394],{"class":330},[273,2883,397],{"class":290},[273,2885,2886],{"class":275,"line":308},[273,2887,409],{"class":290},[273,2889,2890],{"class":275,"line":324},[273,2891,305],{"emptyLinePlaceholder":304},[273,2893,2894,2897,2899,2901,2903,2905],{"class":275,"line":381},[273,2895,2896],{"class":330},"c ",[273,2898,334],{"class":290},[273,2900,1100],{"class":330},[273,2902,340],{"class":290},[273,2904,1105],{"class":314},[273,2906,1108],{"class":290},[273,2908,2909,2911,2913,2915,2917,2919,2921,2923],{"class":275,"line":400},[273,2910,1543],{"class":330},[273,2912,340],{"class":290},[273,2914,1119],{"class":314},[273,2916,346],{"class":290},[273,2918,44],{"class":330},[273,2920,340],{"class":290},[273,2922,1128],{"class":330},[273,2924,397],{"class":290},[273,2926,2927],{"class":275,"line":406},[273,2928,305],{"emptyLinePlaceholder":304},[273,2930,2931,2934,2936,2938,2940,2942],{"class":275,"line":988},[273,2932,2933],{"class":330},"style ",[273,2935,334],{"class":290},[273,2937,1146],{"class":330},[273,2939,340],{"class":290},[273,2941,1838],{"class":314},[273,2943,1108],{"class":290},[273,2945,2946,2949,2951,2954,2956],{"class":275,"line":993},[273,2947,2948],{"class":330},"style",[273,2950,340],{"class":290},[273,2952,2953],{"class":330},"Font ",[273,2955,1857],{"class":290},[273,2957,2958],{"class":330}," font\n",[273,2960,2961,2963,2965,2967,2969],{"class":275,"line":998},[273,2962,2948],{"class":330},[273,2964,340],{"class":290},[273,2966,1885],{"class":330},[273,2968,1857],{"class":290},[273,2970,2971],{"class":1178}," 14\n",[273,2973,2974],{"class":275,"line":1009},[273,2975,305],{"emptyLinePlaceholder":304},[273,2977,2978,2981,2983,2985,2987,2989],{"class":275,"line":1050},[273,2979,2980],{"class":330},"p ",[273,2982,334],{"class":290},[273,2984,1146],{"class":330},[273,2986,340],{"class":290},[273,2988,2029],{"class":314},[273,2990,1108],{"class":290},[273,2992,2993,2995,2997,2999,3001,3003,3006,3008,3011,3013,3015],{"class":275,"line":1065},[273,2994,19],{"class":330},[273,2996,340],{"class":290},[273,2998,2046],{"class":314},[273,3000,346],{"class":290},[273,3002,359],{"class":290},[273,3004,3005],{"class":362},"こんにちは、世界。",[273,3007,359],{"class":290},[273,3009,3010],{"class":290},").",[273,3012,2062],{"class":330},[273,3014,1857],{"class":290},[273,3016,3017],{"class":330}," style\n",[273,3019,3020,3022,3024,3026,3028,3030,3032,3034,3036,3038,3040,3042,3044],{"class":275,"line":1070},[273,3021,2336],{"class":286},[273,3023,331],{"class":330},[273,3025,334],{"class":290},[273,3027,1146],{"class":330},[273,3029,340],{"class":290},[273,3031,1197],{"class":314},[273,3033,346],{"class":290},[273,3035,19],{"class":330},[273,3037,500],{"class":290},[273,3039,331],{"class":330},[273,3041,373],{"class":290},[273,3043,376],{"class":290},[273,3045,321],{"class":290},[273,3047,3048,3050,3052,3054,3056,3058],{"class":275,"line":1075},[273,3049,2366],{"class":330},[273,3051,340],{"class":290},[273,3053,389],{"class":314},[273,3055,346],{"class":290},[273,3057,394],{"class":330},[273,3059,397],{"class":290},[273,3061,3062],{"class":275,"line":1080},[273,3063,409],{"class":290},[273,3065,3066],{"class":275,"line":1092},[273,3067,305],{"emptyLinePlaceholder":304},[273,3069,3070,3072,3074,3076,3078,3080,3083,3085],{"class":275,"line":1111},[273,3071,1543],{"class":330},[273,3073,340],{"class":290},[273,3075,1252],{"class":314},[273,3077,346],{"class":290},[273,3079,359],{"class":290},[273,3081,3082],{"class":362},"ja.pdf",[273,3084,359],{"class":290},[273,3086,397],{"class":290},[19,3088,3089,3090,3092],{},"TTF は実行時に指定したパスに存在している必要がある (バイナリを動かすホスト上に)。コンテナイメージにフォントを同梱しなければならない。",[38,3091,2846],{}," は使う前に呼ばれる必要があり、グローバルに置くか依存として持ち回るかの選択を迫られる。",[19,3094,3095],{},[22,3096,1301],{},[264,3098,3100],{"className":266,"code":3099,"language":268,"meta":269,"style":269},"package main\n\nimport (\n    _ \"embed\"\n    \"log\"\n    \"os\"\n\n    \"github.com/gpdf-dev/gpdf\"\n    \"github.com/gpdf-dev/gpdf/document\"\n    \"github.com/gpdf-dev/gpdf/template\"\n)\n\n//go:embed NotoSansJP-Regular.ttf\nvar notoJP []byte\n\nfunc main() {\n    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(document.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n        gpdf.WithFont(\"NotoSansJP\", notoJP),\n        gpdf.WithDefaultFont(\"NotoSansJP\", 14),\n    )\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"こんにちは、世界。\")\n            c.Text(\"吾輩は猫である。名前はまだ無い。\")\n            c.Text(\"東京都渋谷区神宮前1-2-3\")\n        })\n    })\n\n    data, _ := doc.Generate()\n    if err := os.WriteFile(\"ja.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n",[38,3101,3102,3108,3112,3118,3130,3138,3146,3150,3158,3166,3174,3178,3182,3187,3201,3205,3215,3229,3247,3277,3302,3326,3330,3334,3348,3372,3402,3420,3439,3458,3462,3466,3470,3488,3528,3542,3546],{"__ignoreMap":269},[273,3103,3104,3106],{"class":275,"line":276},[273,3105,932],{"class":290},[273,3107,935],{"class":294},[273,3109,3110],{"class":275,"line":283},[273,3111,305],{"emptyLinePlaceholder":304},[273,3113,3114,3116],{"class":275,"line":301},[273,3115,287],{"class":286},[273,3117,946],{"class":290},[273,3119,3120,3123,3125,3128],{"class":275,"line":308},[273,3121,3122],{"class":330},"    _ ",[273,3124,359],{"class":290},[273,3126,3127],{"class":294},"embed",[273,3129,298],{"class":290},[273,3131,3132,3134,3136],{"class":275,"line":324},[273,3133,951],{"class":290},[273,3135,954],{"class":294},[273,3137,298],{"class":290},[273,3139,3140,3142,3144],{"class":275,"line":381},[273,3141,951],{"class":290},[273,3143,349],{"class":294},[273,3145,298],{"class":290},[273,3147,3148],{"class":275,"line":400},[273,3149,305],{"emptyLinePlaceholder":304},[273,3151,3152,3154,3156],{"class":275,"line":406},[273,3153,951],{"class":290},[273,3155,543],{"class":294},[273,3157,298],{"class":290},[273,3159,3160,3162,3164],{"class":275,"line":988},[273,3161,951],{"class":290},[273,3163,1357],{"class":294},[273,3165,298],{"class":290},[273,3167,3168,3170,3172],{"class":275,"line":993},[273,3169,951],{"class":290},[273,3171,1366],{"class":294},[273,3173,298],{"class":290},[273,3175,3176],{"class":275,"line":998},[273,3177,397],{"class":290},[273,3179,3180],{"class":275,"line":1009},[273,3181,305],{"emptyLinePlaceholder":304},[273,3183,3184],{"class":275,"line":1050},[273,3185,3186],{"class":279},"//go:embed NotoSansJP-Regular.ttf\n",[273,3188,3189,3192,3195,3198],{"class":275,"line":1065},[273,3190,3191],{"class":290},"var",[273,3193,3194],{"class":330}," notoJP ",[273,3196,3197],{"class":290},"[]",[273,3199,3200],{"class":481},"byte\n",[273,3202,3203],{"class":275,"line":1070},[273,3204,305],{"emptyLinePlaceholder":304},[273,3206,3207,3209,3211,3213],{"class":275,"line":1075},[273,3208,311],{"class":290},[273,3210,1085],{"class":314},[273,3212,318],{"class":290},[273,3214,321],{"class":290},[273,3216,3217,3219,3221,3223,3225,3227],{"class":275,"line":1080},[273,3218,1391],{"class":330},[273,3220,334],{"class":290},[273,3222,1396],{"class":330},[273,3224,340],{"class":290},[273,3226,1401],{"class":314},[273,3228,1404],{"class":290},[273,3230,3231,3233,3235,3237,3239,3241,3243,3245],{"class":275,"line":1092},[273,3232,1409],{"class":330},[273,3234,340],{"class":290},[273,3236,1414],{"class":314},[273,3238,346],{"class":290},[273,3240,1419],{"class":330},[273,3242,340],{"class":290},[273,3244,1424],{"class":330},[273,3246,1427],{"class":290},[273,3248,3249,3251,3253,3255,3257,3259,3261,3263,3265,3267,3269,3271,3273,3275],{"class":275,"line":1111},[273,3250,1409],{"class":330},[273,3252,340],{"class":290},[273,3254,1436],{"class":314},[273,3256,346],{"class":290},[273,3258,1419],{"class":330},[273,3260,340],{"class":290},[273,3262,1445],{"class":314},[273,3264,346],{"class":290},[273,3266,1419],{"class":330},[273,3268,340],{"class":290},[273,3270,1454],{"class":314},[273,3272,346],{"class":290},[273,3274,1459],{"class":1178},[273,3276,1462],{"class":290},[273,3278,3279,3281,3283,3286,3288,3290,3293,3295,3297,3300],{"class":275,"line":1133},[273,3280,1409],{"class":330},[273,3282,340],{"class":290},[273,3284,3285],{"class":314},"WithFont",[273,3287,346],{"class":290},[273,3289,359],{"class":290},[273,3291,3292],{"class":362},"NotoSansJP",[273,3294,359],{"class":290},[273,3296,437],{"class":290},[273,3298,3299],{"class":330}," notoJP",[273,3301,1427],{"class":290},[273,3303,3304,3306,3308,3311,3313,3315,3317,3319,3321,3324],{"class":275,"line":1138},[273,3305,1409],{"class":330},[273,3307,340],{"class":290},[273,3309,3310],{"class":314},"WithDefaultFont",[273,3312,346],{"class":290},[273,3314,359],{"class":290},[273,3316,3292],{"class":362},[273,3318,359],{"class":290},[273,3320,437],{"class":290},[273,3322,3323],{"class":1178}," 14",[273,3325,1427],{"class":290},[273,3327,3328],{"class":275,"line":1165},[273,3329,1467],{"class":290},[273,3331,3332],{"class":275,"line":1184},[273,3333,305],{"emptyLinePlaceholder":304},[273,3335,3336,3338,3340,3342,3344,3346],{"class":275,"line":1214},[273,3337,1476],{"class":330},[273,3339,334],{"class":290},[273,3341,1481],{"class":330},[273,3343,340],{"class":290},[273,3345,1486],{"class":314},[273,3347,1108],{"class":290},[273,3349,3350,3352,3354,3356,3358,3360,3362,3364,3366,3368,3370],{"class":275,"line":1229},[273,3351,1493],{"class":330},[273,3353,340],{"class":290},[273,3355,1498],{"class":314},[273,3357,1501],{"class":290},[273,3359,1505],{"class":1504},[273,3361,1508],{"class":290},[273,3363,1511],{"class":294},[273,3365,340],{"class":290},[273,3367,1516],{"class":294},[273,3369,585],{"class":290},[273,3371,321],{"class":290},[273,3373,3374,3376,3378,3380,3382,3384,3386,3388,3390,3392,3394,3396,3398,3400],{"class":275,"line":1234},[273,3375,1525],{"class":330},[273,3377,340],{"class":290},[273,3379,1530],{"class":314},[273,3381,346],{"class":290},[273,3383,1535],{"class":1178},[273,3385,437],{"class":290},[273,3387,1540],{"class":290},[273,3389,1543],{"class":1504},[273,3391,1508],{"class":290},[273,3393,1511],{"class":294},[273,3395,340],{"class":290},[273,3397,1552],{"class":294},[273,3399,585],{"class":290},[273,3401,321],{"class":290},[273,3403,3404,3406,3408,3410,3412,3414,3416,3418],{"class":275,"line":1239},[273,3405,1561],{"class":330},[273,3407,340],{"class":290},[273,3409,1566],{"class":314},[273,3411,346],{"class":290},[273,3413,359],{"class":290},[273,3415,3005],{"class":362},[273,3417,359],{"class":290},[273,3419,397],{"class":290},[273,3421,3422,3424,3426,3428,3430,3432,3435,3437],{"class":275,"line":1274},[273,3423,1561],{"class":330},[273,3425,340],{"class":290},[273,3427,1566],{"class":314},[273,3429,346],{"class":290},[273,3431,359],{"class":290},[273,3433,3434],{"class":362},"吾輩は猫である。名前はまだ無い。",[273,3436,359],{"class":290},[273,3438,397],{"class":290},[273,3440,3441,3443,3445,3447,3449,3451,3454,3456],{"class":275,"line":1289},[273,3442,1561],{"class":330},[273,3444,340],{"class":290},[273,3446,1566],{"class":314},[273,3448,346],{"class":290},[273,3450,359],{"class":290},[273,3452,3453],{"class":362},"東京都渋谷区神宮前1-2-3",[273,3455,359],{"class":290},[273,3457,397],{"class":290},[273,3459,3460],{"class":275,"line":1294},[273,3461,1605],{"class":290},[273,3463,3464],{"class":275,"line":1724},[273,3465,1610],{"class":290},[273,3467,3468],{"class":275,"line":1729},[273,3469,305],{"emptyLinePlaceholder":304},[273,3471,3472,3474,3476,3478,3480,3482,3484,3486],{"class":275,"line":2323},[273,3473,1619],{"class":330},[273,3475,437],{"class":290},[273,3477,440],{"class":330},[273,3479,334],{"class":290},[273,3481,1481],{"class":330},[273,3483,340],{"class":290},[273,3485,1632],{"class":314},[273,3487,1108],{"class":290},[273,3489,3490,3492,3494,3496,3498,3500,3502,3504,3506,3508,3510,3512,3514,3516,3518,3520,3522,3524,3526],{"class":275,"line":2328},[273,3491,327],{"class":286},[273,3493,331],{"class":330},[273,3495,334],{"class":290},[273,3497,445],{"class":330},[273,3499,340],{"class":290},[273,3501,1679],{"class":314},[273,3503,346],{"class":290},[273,3505,359],{"class":290},[273,3507,3082],{"class":362},[273,3509,359],{"class":290},[273,3511,437],{"class":290},[273,3513,1692],{"class":330},[273,3515,437],{"class":290},[273,3517,1697],{"class":1178},[273,3519,500],{"class":290},[273,3521,331],{"class":330},[273,3523,373],{"class":290},[273,3525,376],{"class":290},[273,3527,321],{"class":290},[273,3529,3530,3532,3534,3536,3538,3540],{"class":275,"line":2333},[273,3531,384],{"class":330},[273,3533,340],{"class":290},[273,3535,389],{"class":314},[273,3537,346],{"class":290},[273,3539,394],{"class":330},[273,3541,397],{"class":290},[273,3543,3544],{"class":275,"line":2363},[273,3545,403],{"class":290},[273,3547,3548],{"class":275,"line":2379},[273,3549,409],{"class":290},[19,3551,3552,3553,3556,3557,3560,3561,3564],{},"3 点が違う。フォントは ",[22,3554,3555],{},"バイト列","、パスではない。",[38,3558,3559],{},"//go:embed"," でバイナリに同梱できるので、実行時イメージにフォントディレクトリを用意しなくていい。フォント登録は ",[22,3562,3563],{},"構築時に 1 回","。paragraph ごとに style を引き回さない。そして gpdf の TrueType サブセッタは CJK の cmap (4, 6, 12) と Identity-H エンコーディングを理解しているため、出力 PDF には実際に使ったグリフだけが埋め込まれる。日本語 200 文字の請求書なら埋め込みフォントは ~30 KB。4 MB のフルエンベッドにはならない。",[19,3566,3567],{},"IPAex Gothic / Source Han Sans / フォールバックチェーンの詳細は日本語フォントの記事で別に扱う。",[14,3569,3571],{"id":3570},"before-after-4-全ページ共通のヘッダとフッタのページ番号","Before / After 4: 全ページ共通のヘッダとフッタのページ番号",[19,3573,3574,3575,762,3577,3579,3580,762,3583,3586],{},"unipdf のパターンは ",[38,3576,761],{},[38,3578,765],{},"。どちらも block と現ページ番号を含む引数を受ける。ページ番号は引数の ",[38,3581,3582],{},"PageNum",[38,3584,3585],{},"TotalPages"," から取り出す。",[19,3588,3589],{},[22,3590,922],{},[264,3592,3594],{"className":266,"code":3593,"language":268,"meta":269,"style":269},"c.DrawHeader(func(block *creator.Block, args creator.HeaderFunctionArgs) {\n    p := c.NewParagraph(\"ACME 株式会社\")\n    p.SetFontSize(12)\n    p.SetPos(40, 30)\n    block.Draw(p)\n})\n\nc.DrawFooter(func(block *creator.Block, args creator.FooterFunctionArgs) {\n    p := c.NewParagraph(fmt.Sprintf(\"%d / %d ページ\", args.PageNum, args.TotalPages))\n    p.SetFontSize(8)\n    p.SetPos(0, 20)\n    p.SetTextAlignment(creator.TextAlignmentCenter)\n    block.Draw(p)\n})\n",[38,3595,3596,3635,3658,3672,3693,3708,3712,3716,3751,3808,3823,3842,3862,3876],{"__ignoreMap":269},[273,3597,3598,3600,3602,3605,3607,3610,3612,3614,3616,3619,3621,3624,3626,3628,3631,3633],{"class":275,"line":276},[273,3599,1543],{"class":330},[273,3601,340],{"class":290},[273,3603,3604],{"class":314},"DrawHeader",[273,3606,1501],{"class":290},[273,3608,3609],{"class":1504},"block",[273,3611,1508],{"class":290},[273,3613,44],{"class":294},[273,3615,340],{"class":290},[273,3617,3618],{"class":294},"Block",[273,3620,437],{"class":290},[273,3622,3623],{"class":1504}," args",[273,3625,1100],{"class":294},[273,3627,340],{"class":290},[273,3629,3630],{"class":294},"HeaderFunctionArgs",[273,3632,585],{"class":290},[273,3634,321],{"class":290},[273,3636,3637,3639,3641,3643,3645,3647,3649,3651,3654,3656],{"class":275,"line":283},[273,3638,1141],{"class":330},[273,3640,334],{"class":290},[273,3642,1146],{"class":330},[273,3644,340],{"class":290},[273,3646,1151],{"class":314},[273,3648,346],{"class":290},[273,3650,359],{"class":290},[273,3652,3653],{"class":362},"ACME 株式会社",[273,3655,359],{"class":290},[273,3657,397],{"class":290},[273,3659,3660,3662,3664,3666,3668,3670],{"class":275,"line":301},[273,3661,1168],{"class":330},[273,3663,340],{"class":290},[273,3665,1173],{"class":314},[273,3667,346],{"class":290},[273,3669,1535],{"class":1178},[273,3671,397],{"class":290},[273,3673,3674,3676,3678,3681,3683,3686,3688,3691],{"class":275,"line":308},[273,3675,1168],{"class":330},[273,3677,340],{"class":290},[273,3679,3680],{"class":314},"SetPos",[273,3682,346],{"class":290},[273,3684,3685],{"class":1178},"40",[273,3687,437],{"class":290},[273,3689,3690],{"class":1178}," 30",[273,3692,397],{"class":290},[273,3694,3695,3698,3700,3702,3704,3706],{"class":275,"line":324},[273,3696,3697],{"class":330},"    block",[273,3699,340],{"class":290},[273,3701,1197],{"class":314},[273,3703,346],{"class":290},[273,3705,19],{"class":330},[273,3707,397],{"class":290},[273,3709,3710],{"class":275,"line":381},[273,3711,2782],{"class":290},[273,3713,3714],{"class":275,"line":400},[273,3715,305],{"emptyLinePlaceholder":304},[273,3717,3718,3720,3722,3724,3726,3728,3730,3732,3734,3736,3738,3740,3742,3744,3747,3749],{"class":275,"line":406},[273,3719,1543],{"class":330},[273,3721,340],{"class":290},[273,3723,783],{"class":314},[273,3725,1501],{"class":290},[273,3727,3609],{"class":1504},[273,3729,1508],{"class":290},[273,3731,44],{"class":294},[273,3733,340],{"class":290},[273,3735,3618],{"class":294},[273,3737,437],{"class":290},[273,3739,3623],{"class":1504},[273,3741,1100],{"class":294},[273,3743,340],{"class":290},[273,3745,3746],{"class":294},"FooterFunctionArgs",[273,3748,585],{"class":290},[273,3750,321],{"class":290},[273,3752,3753,3755,3757,3759,3761,3763,3765,3768,3770,3773,3775,3777,3781,3783,3785,3788,3790,3792,3794,3796,3798,3800,3802,3804,3806],{"class":275,"line":988},[273,3754,1141],{"class":330},[273,3756,334],{"class":290},[273,3758,1146],{"class":330},[273,3760,340],{"class":290},[273,3762,1151],{"class":314},[273,3764,346],{"class":290},[273,3766,3767],{"class":330},"fmt",[273,3769,340],{"class":290},[273,3771,3772],{"class":314},"Sprintf",[273,3774,346],{"class":290},[273,3776,359],{"class":290},[273,3778,3780],{"class":3779},"swJcz","%d",[273,3782,762],{"class":362},[273,3784,3780],{"class":3779},[273,3786,3787],{"class":362}," ページ",[273,3789,359],{"class":290},[273,3791,437],{"class":290},[273,3793,3623],{"class":330},[273,3795,340],{"class":290},[273,3797,3582],{"class":330},[273,3799,437],{"class":290},[273,3801,3623],{"class":330},[273,3803,340],{"class":290},[273,3805,3585],{"class":330},[273,3807,1978],{"class":290},[273,3809,3810,3812,3814,3816,3818,3821],{"class":275,"line":993},[273,3811,1168],{"class":330},[273,3813,340],{"class":290},[273,3815,1173],{"class":314},[273,3817,346],{"class":290},[273,3819,3820],{"class":1178},"8",[273,3822,397],{"class":290},[273,3824,3825,3827,3829,3831,3833,3836,3838,3840],{"class":275,"line":998},[273,3826,1168],{"class":330},[273,3828,340],{"class":290},[273,3830,3680],{"class":314},[273,3832,346],{"class":290},[273,3834,3835],{"class":1178},"0",[273,3837,437],{"class":290},[273,3839,2667],{"class":1178},[273,3841,397],{"class":290},[273,3843,3844,3846,3848,3851,3853,3855,3857,3860],{"class":275,"line":1009},[273,3845,1168],{"class":330},[273,3847,340],{"class":290},[273,3849,3850],{"class":314},"SetTextAlignment",[273,3852,346],{"class":290},[273,3854,44],{"class":330},[273,3856,340],{"class":290},[273,3858,3859],{"class":330},"TextAlignmentCenter",[273,3861,397],{"class":290},[273,3863,3864,3866,3868,3870,3872,3874],{"class":275,"line":1050},[273,3865,3697],{"class":330},[273,3867,340],{"class":290},[273,3869,1197],{"class":314},[273,3871,346],{"class":290},[273,3873,19],{"class":330},[273,3875,397],{"class":290},[273,3877,3878],{"class":275,"line":1065},[273,3879,2782],{"class":290},[19,3881,3882],{},"ヘッダもフッタも絶対座標で描く block。Y 座標やマージンを間違えれば、ページサイズを変えるたびに座標を直すことになる。",[19,3884,3885],{},[22,3886,1301],{},[264,3888,3890],{"className":266,"code":3889,"language":268,"meta":269,"style":269},"doc := gpdf.NewDocument(\n    gpdf.WithPageSize(document.A4),\n    gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n)\n\ndoc.Header(func(p *template.PageBuilder) {\n    p.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"ACME 株式会社\", template.Bold(), template.FontSize(12))\n            c.Line(template.LineColor(pdf.Gray(0.7)))\n            c.Spacer(document.Mm(4))\n        })\n    })\n})\n\ndoc.Footer(func(p *template.PageBuilder) {\n    p.AutoRow(func(r *template.RowBuilder) {\n        r.Col(6, func(c *template.ColBuilder) {\n            c.Text(\"ACME 株式会社\",\n                template.FontSize(8), template.TextColor(pdf.Gray(0.5)))\n        })\n        r.Col(6, func(c *template.ColBuilder) {\n            c.PageNumber(template.AlignRight(),\n                template.FontSize(8), template.TextColor(pdf.Gray(0.5)))\n        })\n    })\n})\n\nfor i := 0; i \u003C 10; i++ {\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(fmt.Sprintf(\"%d ページ目の本文。\", i+1))\n        })\n    })\n}\n",[38,3891,3892,3907,3926,3956,3960,3964,3991,4015,4045,4084,4119,4142,4146,4150,4154,4158,4183,4207,4238,4257,4291,4295,4325,4345,4379,4383,4387,4391,4395,4428,4442,4466,4496,4535,4539,4543],{"__ignoreMap":269},[273,3893,3894,3897,3899,3901,3903,3905],{"class":275,"line":276},[273,3895,3896],{"class":330},"doc ",[273,3898,334],{"class":290},[273,3900,1396],{"class":330},[273,3902,340],{"class":290},[273,3904,1401],{"class":314},[273,3906,1404],{"class":290},[273,3908,3909,3912,3914,3916,3918,3920,3922,3924],{"class":275,"line":283},[273,3910,3911],{"class":330},"    gpdf",[273,3913,340],{"class":290},[273,3915,1414],{"class":314},[273,3917,346],{"class":290},[273,3919,1419],{"class":330},[273,3921,340],{"class":290},[273,3923,1424],{"class":330},[273,3925,1427],{"class":290},[273,3927,3928,3930,3932,3934,3936,3938,3940,3942,3944,3946,3948,3950,3952,3954],{"class":275,"line":301},[273,3929,3911],{"class":330},[273,3931,340],{"class":290},[273,3933,1436],{"class":314},[273,3935,346],{"class":290},[273,3937,1419],{"class":330},[273,3939,340],{"class":290},[273,3941,1445],{"class":314},[273,3943,346],{"class":290},[273,3945,1419],{"class":330},[273,3947,340],{"class":290},[273,3949,1454],{"class":314},[273,3951,346],{"class":290},[273,3953,1459],{"class":1178},[273,3955,1462],{"class":290},[273,3957,3958],{"class":275,"line":308},[273,3959,397],{"class":290},[273,3961,3962],{"class":275,"line":324},[273,3963,305],{"emptyLinePlaceholder":304},[273,3965,3966,3969,3971,3974,3976,3978,3980,3982,3984,3987,3989],{"class":275,"line":381},[273,3967,3968],{"class":330},"doc",[273,3970,340],{"class":290},[273,3972,3973],{"class":314},"Header",[273,3975,1501],{"class":290},[273,3977,19],{"class":1504},[273,3979,1508],{"class":290},[273,3981,1511],{"class":294},[273,3983,340],{"class":290},[273,3985,3986],{"class":294},"PageBuilder",[273,3988,585],{"class":290},[273,3990,321],{"class":290},[273,3992,3993,3995,3997,3999,4001,4003,4005,4007,4009,4011,4013],{"class":275,"line":400},[273,3994,1168],{"class":330},[273,3996,340],{"class":290},[273,3998,1498],{"class":314},[273,4000,1501],{"class":290},[273,4002,1505],{"class":1504},[273,4004,1508],{"class":290},[273,4006,1511],{"class":294},[273,4008,340],{"class":290},[273,4010,1516],{"class":294},[273,4012,585],{"class":290},[273,4014,321],{"class":290},[273,4016,4017,4019,4021,4023,4025,4027,4029,4031,4033,4035,4037,4039,4041,4043],{"class":275,"line":406},[273,4018,1525],{"class":330},[273,4020,340],{"class":290},[273,4022,1530],{"class":314},[273,4024,346],{"class":290},[273,4026,1535],{"class":1178},[273,4028,437],{"class":290},[273,4030,1540],{"class":290},[273,4032,1543],{"class":1504},[273,4034,1508],{"class":290},[273,4036,1511],{"class":294},[273,4038,340],{"class":290},[273,4040,1552],{"class":294},[273,4042,585],{"class":290},[273,4044,321],{"class":290},[273,4046,4047,4049,4051,4053,4055,4057,4059,4061,4063,4065,4067,4069,4072,4074,4076,4078,4080,4082],{"class":275,"line":988},[273,4048,1561],{"class":330},[273,4050,340],{"class":290},[273,4052,1566],{"class":314},[273,4054,346],{"class":290},[273,4056,359],{"class":290},[273,4058,3653],{"class":362},[273,4060,359],{"class":290},[273,4062,437],{"class":290},[273,4064,1579],{"class":330},[273,4066,340],{"class":290},[273,4068,1597],{"class":314},[273,4070,4071],{"class":290},"(),",[273,4073,1579],{"class":330},[273,4075,340],{"class":290},[273,4077,1584],{"class":314},[273,4079,346],{"class":290},[273,4081,1535],{"class":1178},[273,4083,1978],{"class":290},[273,4085,4086,4088,4090,4093,4095,4097,4099,4102,4104,4106,4108,4111,4113,4116],{"class":275,"line":993},[273,4087,1561],{"class":330},[273,4089,340],{"class":290},[273,4091,4092],{"class":314},"Line",[273,4094,346],{"class":290},[273,4096,1511],{"class":330},[273,4098,340],{"class":290},[273,4100,4101],{"class":314},"LineColor",[273,4103,346],{"class":290},[273,4105,2706],{"class":330},[273,4107,340],{"class":290},[273,4109,4110],{"class":314},"Gray",[273,4112,346],{"class":290},[273,4114,4115],{"class":1178},"0.7",[273,4117,4118],{"class":290},")))\n",[273,4120,4121,4123,4125,4128,4130,4132,4134,4136,4138,4140],{"class":275,"line":998},[273,4122,1561],{"class":330},[273,4124,340],{"class":290},[273,4126,4127],{"class":314},"Spacer",[273,4129,346],{"class":290},[273,4131,1419],{"class":330},[273,4133,340],{"class":290},[273,4135,1454],{"class":314},[273,4137,346],{"class":290},[273,4139,1789],{"class":1178},[273,4141,1978],{"class":290},[273,4143,4144],{"class":275,"line":1009},[273,4145,1605],{"class":290},[273,4147,4148],{"class":275,"line":1050},[273,4149,1610],{"class":290},[273,4151,4152],{"class":275,"line":1065},[273,4153,2782],{"class":290},[273,4155,4156],{"class":275,"line":1070},[273,4157,305],{"emptyLinePlaceholder":304},[273,4159,4160,4162,4164,4167,4169,4171,4173,4175,4177,4179,4181],{"class":275,"line":1075},[273,4161,3968],{"class":330},[273,4163,340],{"class":290},[273,4165,4166],{"class":314},"Footer",[273,4168,1501],{"class":290},[273,4170,19],{"class":1504},[273,4172,1508],{"class":290},[273,4174,1511],{"class":294},[273,4176,340],{"class":290},[273,4178,3986],{"class":294},[273,4180,585],{"class":290},[273,4182,321],{"class":290},[273,4184,4185,4187,4189,4191,4193,4195,4197,4199,4201,4203,4205],{"class":275,"line":1080},[273,4186,1168],{"class":330},[273,4188,340],{"class":290},[273,4190,1498],{"class":314},[273,4192,1501],{"class":290},[273,4194,1505],{"class":1504},[273,4196,1508],{"class":290},[273,4198,1511],{"class":294},[273,4200,340],{"class":290},[273,4202,1516],{"class":294},[273,4204,585],{"class":290},[273,4206,321],{"class":290},[273,4208,4209,4211,4213,4215,4217,4220,4222,4224,4226,4228,4230,4232,4234,4236],{"class":275,"line":1092},[273,4210,1525],{"class":330},[273,4212,340],{"class":290},[273,4214,1530],{"class":314},[273,4216,346],{"class":290},[273,4218,4219],{"class":1178},"6",[273,4221,437],{"class":290},[273,4223,1540],{"class":290},[273,4225,1543],{"class":1504},[273,4227,1508],{"class":290},[273,4229,1511],{"class":294},[273,4231,340],{"class":290},[273,4233,1552],{"class":294},[273,4235,585],{"class":290},[273,4237,321],{"class":290},[273,4239,4240,4242,4244,4246,4248,4250,4252,4254],{"class":275,"line":1111},[273,4241,1561],{"class":330},[273,4243,340],{"class":290},[273,4245,1566],{"class":314},[273,4247,346],{"class":290},[273,4249,359],{"class":290},[273,4251,3653],{"class":362},[273,4253,359],{"class":290},[273,4255,4256],{"class":290},",\n",[273,4258,4259,4261,4263,4265,4267,4269,4271,4273,4275,4277,4279,4281,4283,4285,4287,4289],{"class":275,"line":1133},[273,4260,2685],{"class":330},[273,4262,340],{"class":290},[273,4264,1584],{"class":314},[273,4266,346],{"class":290},[273,4268,3820],{"class":1178},[273,4270,490],{"class":290},[273,4272,1579],{"class":330},[273,4274,340],{"class":290},[273,4276,2701],{"class":314},[273,4278,346],{"class":290},[273,4280,2706],{"class":330},[273,4282,340],{"class":290},[273,4284,4110],{"class":314},[273,4286,346],{"class":290},[273,4288,1804],{"class":1178},[273,4290,4118],{"class":290},[273,4292,4293],{"class":275,"line":1138},[273,4294,1605],{"class":290},[273,4296,4297,4299,4301,4303,4305,4307,4309,4311,4313,4315,4317,4319,4321,4323],{"class":275,"line":1165},[273,4298,1525],{"class":330},[273,4300,340],{"class":290},[273,4302,1530],{"class":314},[273,4304,346],{"class":290},[273,4306,4219],{"class":1178},[273,4308,437],{"class":290},[273,4310,1540],{"class":290},[273,4312,1543],{"class":1504},[273,4314,1508],{"class":290},[273,4316,1511],{"class":294},[273,4318,340],{"class":290},[273,4320,1552],{"class":294},[273,4322,585],{"class":290},[273,4324,321],{"class":290},[273,4326,4327,4329,4331,4334,4336,4338,4340,4343],{"class":275,"line":1184},[273,4328,1561],{"class":330},[273,4330,340],{"class":290},[273,4332,4333],{"class":314},"PageNumber",[273,4335,346],{"class":290},[273,4337,1511],{"class":330},[273,4339,340],{"class":290},[273,4341,4342],{"class":314},"AlignRight",[273,4344,2692],{"class":290},[273,4346,4347,4349,4351,4353,4355,4357,4359,4361,4363,4365,4367,4369,4371,4373,4375,4377],{"class":275,"line":1214},[273,4348,2685],{"class":330},[273,4350,340],{"class":290},[273,4352,1584],{"class":314},[273,4354,346],{"class":290},[273,4356,3820],{"class":1178},[273,4358,490],{"class":290},[273,4360,1579],{"class":330},[273,4362,340],{"class":290},[273,4364,2701],{"class":314},[273,4366,346],{"class":290},[273,4368,2706],{"class":330},[273,4370,340],{"class":290},[273,4372,4110],{"class":314},[273,4374,346],{"class":290},[273,4376,1804],{"class":1178},[273,4378,4118],{"class":290},[273,4380,4381],{"class":275,"line":1229},[273,4382,1605],{"class":290},[273,4384,4385],{"class":275,"line":1234},[273,4386,1610],{"class":290},[273,4388,4389],{"class":275,"line":1239},[273,4390,2782],{"class":290},[273,4392,4393],{"class":275,"line":1274},[273,4394,305],{"emptyLinePlaceholder":304},[273,4396,4397,4399,4402,4404,4407,4410,4412,4415,4418,4420,4423,4426],{"class":275,"line":1289},[273,4398,2094],{"class":286},[273,4400,4401],{"class":330}," i ",[273,4403,334],{"class":290},[273,4405,4406],{"class":1178}," 0",[273,4408,4409],{"class":290},";",[273,4411,4401],{"class":330},[273,4413,4414],{"class":290},"\u003C",[273,4416,4417],{"class":1178}," 10",[273,4419,4409],{"class":290},[273,4421,4422],{"class":330}," i",[273,4424,4425],{"class":290},"++",[273,4427,321],{"class":290},[273,4429,4430,4432,4434,4436,4438,4440],{"class":275,"line":1294},[273,4431,1476],{"class":330},[273,4433,334],{"class":290},[273,4435,1481],{"class":330},[273,4437,340],{"class":290},[273,4439,1486],{"class":314},[273,4441,1108],{"class":290},[273,4443,4444,4446,4448,4450,4452,4454,4456,4458,4460,4462,4464],{"class":275,"line":1724},[273,4445,1493],{"class":330},[273,4447,340],{"class":290},[273,4449,1498],{"class":314},[273,4451,1501],{"class":290},[273,4453,1505],{"class":1504},[273,4455,1508],{"class":290},[273,4457,1511],{"class":294},[273,4459,340],{"class":290},[273,4461,1516],{"class":294},[273,4463,585],{"class":290},[273,4465,321],{"class":290},[273,4467,4468,4470,4472,4474,4476,4478,4480,4482,4484,4486,4488,4490,4492,4494],{"class":275,"line":1729},[273,4469,1525],{"class":330},[273,4471,340],{"class":290},[273,4473,1530],{"class":314},[273,4475,346],{"class":290},[273,4477,1535],{"class":1178},[273,4479,437],{"class":290},[273,4481,1540],{"class":290},[273,4483,1543],{"class":1504},[273,4485,1508],{"class":290},[273,4487,1511],{"class":294},[273,4489,340],{"class":290},[273,4491,1552],{"class":294},[273,4493,585],{"class":290},[273,4495,321],{"class":290},[273,4497,4498,4500,4502,4504,4506,4508,4510,4512,4514,4516,4518,4521,4523,4525,4527,4530,4533],{"class":275,"line":2323},[273,4499,1561],{"class":330},[273,4501,340],{"class":290},[273,4503,1566],{"class":314},[273,4505,346],{"class":290},[273,4507,3767],{"class":330},[273,4509,340],{"class":290},[273,4511,3772],{"class":314},[273,4513,346],{"class":290},[273,4515,359],{"class":290},[273,4517,3780],{"class":3779},[273,4519,4520],{"class":362}," ページ目の本文。",[273,4522,359],{"class":290},[273,4524,437],{"class":290},[273,4526,4422],{"class":330},[273,4528,4529],{"class":290},"+",[273,4531,4532],{"class":1178},"1",[273,4534,1978],{"class":290},[273,4536,4537],{"class":275,"line":2328},[273,4538,1605],{"class":290},[273,4540,4541],{"class":275,"line":2333},[273,4542,1610],{"class":290},[273,4544,4545],{"class":275,"line":2363},[273,4546,409],{"class":290},[19,4548,4549,762,4551,4553],{},[38,4550,4333],{},[38,4552,3585],{}," はプレースホルダ。ページ確定後にレイアウトエンジンが解決する。ヘッダもフッタも自前のツリー — 配置するブロックではない。エンジンが各ページに毎回スペースを確保する。A4 から Letter にページサイズを変えても、他は何も触らなくていい。",[14,4555,4557],{"id":4556},"before-after-5-aes-256-暗号化","Before / After 5: AES-256 暗号化",[19,4559,4560,4561,4563],{},"ライセンスの差が一番はっきり出るペア。unipdf の暗号化は ",[38,4562,805],{}," を経由する経路で、これは商用利用にあたり license 登録のチェックが走る。gpdf 側は単一の関数オプション。AES-256 (ISO 32000-2 Rev 6) の実装はオープンソースの MIT コアに同梱。",[19,4565,4566],{},[22,4567,922],{},[264,4569,4571],{"className":266,"code":4570,"language":268,"meta":269,"style":269},"// creator で生成 → model.PdfWriter で再エンコードして暗号化を付与。\n// ここで license チェックが発火する。\nc := creator.New()\n// ... コンテンツを描画 ...\n\nvar buf bytes.Buffer\nif err := c.Write(&buf); err != nil {\n    log.Fatal(err)\n}\n\nreader, err := model.NewPdfReader(bytes.NewReader(buf.Bytes()))\nif err != nil {\n    log.Fatal(err)\n}\n\nwriter := model.NewPdfWriter()\nencryptOpts := &model.EncryptOptions{Algorithm: model.RC4_128bit, Permissions: model.PermPrinting}\nif err := writer.Encrypt([]byte(\"user-pwd\"), []byte(\"owner-pwd\"), encryptOpts); err != nil {\n    log.Fatal(err)\n}\n\nfor i := 1; i \u003C= reader.NumPage; i++ {\n    page, _ := reader.GetPage(i)\n    writer.AddPage(page)\n}\n\nf, _ := os.Create(\"encrypted.pdf\")\ndefer f.Close()\nwriter.Write(f)\n",[38,4572,4573,4578,4583,4597,4602,4606,4621,4652,4666,4670,4674,4713,4725,4739,4743,4747,4763,4812,4872,4886,4890,4894,4928,4952,4967,4971,4975,5004,5019],{"__ignoreMap":269},[273,4574,4575],{"class":275,"line":276},[273,4576,4577],{"class":279},"// creator で生成 → model.PdfWriter で再エンコードして暗号化を付与。\n",[273,4579,4580],{"class":275,"line":283},[273,4581,4582],{"class":279},"// ここで license チェックが発火する。\n",[273,4584,4585,4587,4589,4591,4593,4595],{"class":275,"line":301},[273,4586,2896],{"class":330},[273,4588,334],{"class":290},[273,4590,1100],{"class":330},[273,4592,340],{"class":290},[273,4594,1105],{"class":314},[273,4596,1108],{"class":290},[273,4598,4599],{"class":275,"line":308},[273,4600,4601],{"class":279},"// ... コンテンツを描画 ...\n",[273,4603,4604],{"class":275,"line":324},[273,4605,305],{"emptyLinePlaceholder":304},[273,4607,4608,4610,4613,4616,4618],{"class":275,"line":381},[273,4609,3191],{"class":290},[273,4611,4612],{"class":330}," buf ",[273,4614,4615],{"class":294},"bytes",[273,4617,340],{"class":290},[273,4619,4620],{"class":294},"Buffer\n",[273,4622,4623,4625,4627,4629,4631,4633,4636,4639,4642,4644,4646,4648,4650],{"class":275,"line":400},[273,4624,2336],{"class":286},[273,4626,331],{"class":330},[273,4628,334],{"class":290},[273,4630,1146],{"class":330},[273,4632,340],{"class":290},[273,4634,4635],{"class":314},"Write",[273,4637,4638],{"class":290},"(&",[273,4640,4641],{"class":330},"buf",[273,4643,500],{"class":290},[273,4645,331],{"class":330},[273,4647,373],{"class":290},[273,4649,376],{"class":290},[273,4651,321],{"class":290},[273,4653,4654,4656,4658,4660,4662,4664],{"class":275,"line":406},[273,4655,2366],{"class":330},[273,4657,340],{"class":290},[273,4659,389],{"class":314},[273,4661,346],{"class":290},[273,4663,394],{"class":330},[273,4665,397],{"class":290},[273,4667,4668],{"class":275,"line":988},[273,4669,409],{"class":290},[273,4671,4672],{"class":275,"line":993},[273,4673,305],{"emptyLinePlaceholder":304},[273,4675,4676,4679,4681,4683,4685,4687,4689,4692,4694,4696,4698,4701,4703,4705,4707,4710],{"class":275,"line":998},[273,4677,4678],{"class":330},"reader",[273,4680,437],{"class":290},[273,4682,331],{"class":330},[273,4684,334],{"class":290},[273,4686,1860],{"class":330},[273,4688,340],{"class":290},[273,4690,4691],{"class":314},"NewPdfReader",[273,4693,346],{"class":290},[273,4695,4615],{"class":330},[273,4697,340],{"class":290},[273,4699,4700],{"class":314},"NewReader",[273,4702,346],{"class":290},[273,4704,4641],{"class":330},[273,4706,340],{"class":290},[273,4708,4709],{"class":314},"Bytes",[273,4711,4712],{"class":290},"()))\n",[273,4714,4715,4717,4719,4721,4723],{"class":275,"line":1009},[273,4716,2336],{"class":286},[273,4718,331],{"class":330},[273,4720,373],{"class":290},[273,4722,376],{"class":290},[273,4724,321],{"class":290},[273,4726,4727,4729,4731,4733,4735,4737],{"class":275,"line":1050},[273,4728,2366],{"class":330},[273,4730,340],{"class":290},[273,4732,389],{"class":314},[273,4734,346],{"class":290},[273,4736,394],{"class":330},[273,4738,397],{"class":290},[273,4740,4741],{"class":275,"line":1065},[273,4742,409],{"class":290},[273,4744,4745],{"class":275,"line":1070},[273,4746,305],{"emptyLinePlaceholder":304},[273,4748,4749,4752,4754,4756,4758,4761],{"class":275,"line":1075},[273,4750,4751],{"class":330},"writer ",[273,4753,334],{"class":290},[273,4755,1860],{"class":330},[273,4757,340],{"class":290},[273,4759,4760],{"class":314},"NewPdfWriter",[273,4762,1108],{"class":290},[273,4764,4765,4768,4770,4773,4776,4778,4781,4783,4786,4789,4791,4793,4796,4798,4801,4803,4805,4807,4810],{"class":275,"line":1080},[273,4766,4767],{"class":330},"encryptOpts ",[273,4769,334],{"class":290},[273,4771,4772],{"class":290}," &",[273,4774,4775],{"class":294},"model",[273,4777,340],{"class":290},[273,4779,4780],{"class":294},"EncryptOptions",[273,4782,2115],{"class":290},[273,4784,4785],{"class":330},"Algorithm",[273,4787,4788],{"class":290},":",[273,4790,1860],{"class":330},[273,4792,340],{"class":290},[273,4794,4795],{"class":330},"RC4_128bit",[273,4797,437],{"class":290},[273,4799,4800],{"class":330}," Permissions",[273,4802,4788],{"class":290},[273,4804,1860],{"class":330},[273,4806,340],{"class":290},[273,4808,4809],{"class":330},"PermPrinting",[273,4811,409],{"class":290},[273,4813,4814,4816,4818,4820,4823,4825,4827,4830,4833,4835,4837,4840,4842,4844,4846,4848,4850,4852,4855,4857,4859,4862,4864,4866,4868,4870],{"class":275,"line":1092},[273,4815,2336],{"class":286},[273,4817,331],{"class":330},[273,4819,334],{"class":290},[273,4821,4822],{"class":330}," writer",[273,4824,340],{"class":290},[273,4826,809],{"class":314},[273,4828,4829],{"class":290},"([]",[273,4831,4832],{"class":481},"byte",[273,4834,346],{"class":290},[273,4836,359],{"class":290},[273,4838,4839],{"class":362},"user-pwd",[273,4841,359],{"class":290},[273,4843,490],{"class":290},[273,4845,2110],{"class":290},[273,4847,4832],{"class":481},[273,4849,346],{"class":290},[273,4851,359],{"class":290},[273,4853,4854],{"class":362},"owner-pwd",[273,4856,359],{"class":290},[273,4858,490],{"class":290},[273,4860,4861],{"class":330}," encryptOpts",[273,4863,500],{"class":290},[273,4865,331],{"class":330},[273,4867,373],{"class":290},[273,4869,376],{"class":290},[273,4871,321],{"class":290},[273,4873,4874,4876,4878,4880,4882,4884],{"class":275,"line":1111},[273,4875,2366],{"class":330},[273,4877,340],{"class":290},[273,4879,389],{"class":314},[273,4881,346],{"class":290},[273,4883,394],{"class":330},[273,4885,397],{"class":290},[273,4887,4888],{"class":275,"line":1133},[273,4889,409],{"class":290},[273,4891,4892],{"class":275,"line":1138},[273,4893,305],{"emptyLinePlaceholder":304},[273,4895,4896,4898,4900,4902,4905,4907,4909,4912,4915,4917,4920,4922,4924,4926],{"class":275,"line":1165},[273,4897,2094],{"class":286},[273,4899,4401],{"class":330},[273,4901,334],{"class":290},[273,4903,4904],{"class":1178}," 1",[273,4906,4409],{"class":290},[273,4908,4401],{"class":330},[273,4910,4911],{"class":290},"\u003C=",[273,4913,4914],{"class":330}," reader",[273,4916,340],{"class":290},[273,4918,4919],{"class":330},"NumPage",[273,4921,4409],{"class":290},[273,4923,4422],{"class":330},[273,4925,4425],{"class":290},[273,4927,321],{"class":290},[273,4929,4930,4932,4934,4936,4938,4940,4942,4945,4947,4950],{"class":275,"line":1184},[273,4931,1493],{"class":330},[273,4933,437],{"class":290},[273,4935,440],{"class":330},[273,4937,334],{"class":290},[273,4939,4914],{"class":330},[273,4941,340],{"class":290},[273,4943,4944],{"class":314},"GetPage",[273,4946,346],{"class":290},[273,4948,4949],{"class":330},"i",[273,4951,397],{"class":290},[273,4953,4954,4957,4959,4961,4963,4965],{"class":275,"line":1214},[273,4955,4956],{"class":330},"    writer",[273,4958,340],{"class":290},[273,4960,1486],{"class":314},[273,4962,346],{"class":290},[273,4964,2398],{"class":330},[273,4966,397],{"class":290},[273,4968,4969],{"class":275,"line":1229},[273,4970,409],{"class":290},[273,4972,4973],{"class":275,"line":1234},[273,4974,305],{"emptyLinePlaceholder":304},[273,4976,4977,4980,4982,4984,4986,4988,4990,4993,4995,4997,5000,5002],{"class":275,"line":1239},[273,4978,4979],{"class":330},"f",[273,4981,437],{"class":290},[273,4983,440],{"class":330},[273,4985,334],{"class":290},[273,4987,445],{"class":330},[273,4989,340],{"class":290},[273,4991,4992],{"class":314},"Create",[273,4994,346],{"class":290},[273,4996,359],{"class":290},[273,4998,4999],{"class":362},"encrypted.pdf",[273,5001,359],{"class":290},[273,5003,397],{"class":290},[273,5005,5006,5009,5012,5014,5017],{"class":275,"line":1274},[273,5007,5008],{"class":286},"defer",[273,5010,5011],{"class":330}," f",[273,5013,340],{"class":290},[273,5015,5016],{"class":314},"Close",[273,5018,1108],{"class":290},[273,5020,5021,5024,5026,5028,5030,5032],{"class":275,"line":1289},[273,5022,5023],{"class":330},"writer",[273,5025,340],{"class":290},[273,5027,4635],{"class":314},[273,5029,346],{"class":290},[273,5031,4979],{"class":330},[273,5033,397],{"class":290},[19,5035,5036],{},[22,5037,1301],{},[264,5039,5041],{"className":266,"code":5040,"language":268,"meta":269,"style":269},"doc := gpdf.NewDocument(\n    gpdf.WithPageSize(document.A4),\n    gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n    gpdf.WithEncryption(\n        gpdf.AES256,\n        \"user-pwd\",\n        \"owner-pwd\",\n        gpdf.PermPrinting|gpdf.PermCopyContent,\n    ),\n)\n\npage := doc.AddPage()\npage.AutoRow(func(r *template.RowBuilder) {\n    r.Col(12, func(c *template.ColBuilder) {\n        c.Text(\"社外秘\")\n    })\n})\n\ndata, _ := doc.Generate()\nos.WriteFile(\"encrypted.pdf\", data, 0o644)\n",[38,5042,5043,5057,5075,5105,5116,5127,5137,5147,5167,5172,5176,5180,5195,5219,5249,5268,5272,5276,5280,5299],{"__ignoreMap":269},[273,5044,5045,5047,5049,5051,5053,5055],{"class":275,"line":276},[273,5046,3896],{"class":330},[273,5048,334],{"class":290},[273,5050,1396],{"class":330},[273,5052,340],{"class":290},[273,5054,1401],{"class":314},[273,5056,1404],{"class":290},[273,5058,5059,5061,5063,5065,5067,5069,5071,5073],{"class":275,"line":283},[273,5060,3911],{"class":330},[273,5062,340],{"class":290},[273,5064,1414],{"class":314},[273,5066,346],{"class":290},[273,5068,1419],{"class":330},[273,5070,340],{"class":290},[273,5072,1424],{"class":330},[273,5074,1427],{"class":290},[273,5076,5077,5079,5081,5083,5085,5087,5089,5091,5093,5095,5097,5099,5101,5103],{"class":275,"line":301},[273,5078,3911],{"class":330},[273,5080,340],{"class":290},[273,5082,1436],{"class":314},[273,5084,346],{"class":290},[273,5086,1419],{"class":330},[273,5088,340],{"class":290},[273,5090,1445],{"class":314},[273,5092,346],{"class":290},[273,5094,1419],{"class":330},[273,5096,340],{"class":290},[273,5098,1454],{"class":314},[273,5100,346],{"class":290},[273,5102,1459],{"class":1178},[273,5104,1462],{"class":290},[273,5106,5107,5109,5111,5114],{"class":275,"line":308},[273,5108,3911],{"class":330},[273,5110,340],{"class":290},[273,5112,5113],{"class":314},"WithEncryption",[273,5115,1404],{"class":290},[273,5117,5118,5120,5122,5125],{"class":275,"line":324},[273,5119,1409],{"class":330},[273,5121,340],{"class":290},[273,5123,5124],{"class":330},"AES256",[273,5126,4256],{"class":290},[273,5128,5129,5131,5133,5135],{"class":275,"line":381},[273,5130,2608],{"class":290},[273,5132,4839],{"class":362},[273,5134,359],{"class":290},[273,5136,4256],{"class":290},[273,5138,5139,5141,5143,5145],{"class":275,"line":400},[273,5140,2608],{"class":290},[273,5142,4854],{"class":362},[273,5144,359],{"class":290},[273,5146,4256],{"class":290},[273,5148,5149,5151,5153,5155,5158,5160,5162,5165],{"class":275,"line":406},[273,5150,1409],{"class":330},[273,5152,340],{"class":290},[273,5154,4809],{"class":330},[273,5156,5157],{"class":290},"|",[273,5159,24],{"class":330},[273,5161,340],{"class":290},[273,5163,5164],{"class":330},"PermCopyContent",[273,5166,4256],{"class":290},[273,5168,5169],{"class":275,"line":988},[273,5170,5171],{"class":290},"    ),\n",[273,5173,5174],{"class":275,"line":993},[273,5175,397],{"class":290},[273,5177,5178],{"class":275,"line":998},[273,5179,305],{"emptyLinePlaceholder":304},[273,5181,5182,5185,5187,5189,5191,5193],{"class":275,"line":1009},[273,5183,5184],{"class":330},"page ",[273,5186,334],{"class":290},[273,5188,1481],{"class":330},[273,5190,340],{"class":290},[273,5192,1486],{"class":314},[273,5194,1108],{"class":290},[273,5196,5197,5199,5201,5203,5205,5207,5209,5211,5213,5215,5217],{"class":275,"line":1050},[273,5198,2398],{"class":330},[273,5200,340],{"class":290},[273,5202,1498],{"class":314},[273,5204,1501],{"class":290},[273,5206,1505],{"class":1504},[273,5208,1508],{"class":290},[273,5210,1511],{"class":294},[273,5212,340],{"class":290},[273,5214,1516],{"class":294},[273,5216,585],{"class":290},[273,5218,321],{"class":290},[273,5220,5221,5223,5225,5227,5229,5231,5233,5235,5237,5239,5241,5243,5245,5247],{"class":275,"line":1065},[273,5222,2423],{"class":330},[273,5224,340],{"class":290},[273,5226,1530],{"class":314},[273,5228,346],{"class":290},[273,5230,1535],{"class":1178},[273,5232,437],{"class":290},[273,5234,1540],{"class":290},[273,5236,1543],{"class":1504},[273,5238,1508],{"class":290},[273,5240,1511],{"class":294},[273,5242,340],{"class":290},[273,5244,1552],{"class":294},[273,5246,585],{"class":290},[273,5248,321],{"class":290},[273,5250,5251,5253,5255,5257,5259,5261,5264,5266],{"class":275,"line":1070},[273,5252,2454],{"class":330},[273,5254,340],{"class":290},[273,5256,1566],{"class":314},[273,5258,346],{"class":290},[273,5260,359],{"class":290},[273,5262,5263],{"class":362},"社外秘",[273,5265,359],{"class":290},[273,5267,397],{"class":290},[273,5269,5270],{"class":275,"line":1075},[273,5271,1610],{"class":290},[273,5273,5274],{"class":275,"line":1080},[273,5275,2782],{"class":290},[273,5277,5278],{"class":275,"line":1092},[273,5279,305],{"emptyLinePlaceholder":304},[273,5281,5282,5285,5287,5289,5291,5293,5295,5297],{"class":275,"line":1111},[273,5283,5284],{"class":330},"data",[273,5286,437],{"class":290},[273,5288,440],{"class":330},[273,5290,334],{"class":290},[273,5292,1481],{"class":330},[273,5294,340],{"class":290},[273,5296,1632],{"class":314},[273,5298,1108],{"class":290},[273,5300,5301,5303,5305,5307,5309,5311,5313,5315,5317,5319,5321,5323],{"class":275,"line":1133},[273,5302,349],{"class":330},[273,5304,340],{"class":290},[273,5306,1679],{"class":314},[273,5308,346],{"class":290},[273,5310,359],{"class":290},[273,5312,4999],{"class":362},[273,5314,359],{"class":290},[273,5316,437],{"class":290},[273,5318,1692],{"class":330},[273,5320,437],{"class":290},[273,5322,1697],{"class":1178},[273,5324,397],{"class":290},[19,5326,5327,5328,5331,5332,5335],{},"オプション 1 つ、デフォルト AES-256、別 writer パスなし。暗号化経路は MIT コア内 — 同じモジュール、同じ ",[38,5329,5330],{},"go get","。署名も同じ話で、",[38,5333,5334],{},"gpdf.SignDocument(pdfBytes, signer, gpdf.WithTSA(\"http://timestamp.digicert.com\"))"," で PKCS#7 + RFC 3161 タイムスタンプを後処理として付与する。追加パッケージもキー登録もない。",[14,5337,5338],{"id":5338},"どれくらい速いのか",[19,5340,5341,5344],{},[38,5342,5343],{},"_benchmark/benchmark_test.go"," を Apple M1 / Go 1.25 で実行した結果。unipdf は別実行で同条件 (Apple M1 / Go 1.25 / unipdf v3) で計測した値。",[121,5346,5347,5365],{},[124,5348,5349],{},[127,5350,5351,5354,5356,5359,5362],{},[130,5352,5353],{},"ベンチマーク",[130,5355,24],{},[130,5357,5358],{},"unipdf*",[130,5360,5361],{},"gofpdf",[130,5363,5364],{},"Maroto v2",[139,5366,5367,5386,5403,5422],{},[127,5368,5369,5372,5377,5380,5383],{},[144,5370,5371],{},"単一ページ",[144,5373,5374],{},[22,5375,5376],{},"13 µs",[144,5378,5379],{},"~180 µs",[144,5381,5382],{},"132 µs",[144,5384,5385],{},"237 µs",[127,5387,5388,5391,5395,5398,5401],{},[144,5389,5390],{},"4×10 請求書テーブル",[144,5392,5393],{},[22,5394,2804],{},[144,5396,5397],{},"~8.6 ms",[144,5399,5400],{},"241 µs",[144,5402,2800],{},[127,5404,5405,5408,5413,5416,5419],{},[144,5406,5407],{},"100 ページレポート",[144,5409,5410],{},[22,5411,5412],{},"683 µs",[144,5414,5415],{},"~95 ms",[144,5417,5418],{},"11.7 ms",[144,5420,5421],{},"19.8 ms",[127,5423,5424,5427,5432,5435,5438],{},[144,5425,5426],{},"複雑な CJK 請求書",[144,5428,5429],{},[22,5430,5431],{},"133 µs",[144,5433,5434],{},"~12 ms",[144,5436,5437],{},"254 µs",[144,5439,5440],{},"10.4 ms",[19,5442,5443],{},"* unipdf の数値は別実行で取得した参考値。同等ハードでの計測だが、gpdf の committed suite には含まれていない。",[19,5445,5446],{},"形は gofpdf 比較と同じ。実運用で使われるワークロードに対しては 10〜80 倍速い。テーブル多めで 1 ページ 108 µs ということは、1 コアで 1 秒間に 9,000 通の請求書。「PDF 生成をキューに入れるか、リクエスト経路で生成するか」の議論が、ほぼリクエスト経路で完結する側に寄る。",[14,5448,5450],{"id":5449},"gpdf-にない部分の正直な扱い","gpdf にない部分の正直な扱い",[19,5452,5453],{},"unipdf の請求書を OCR・redaction・PDF 解析が支えている場合、この移行ではカバーしきれない。正直な選択肢:",[5455,5456,5457,5470,5481,5487],"ul",{},[89,5458,5459,5461,5462,5469],{},[22,5460,225],{},": gpdf は OCR をやらないし、当面やる予定もない。",[5463,5464,5468],"a",{"href":5465,"rel":5466},"https://github.com/tesseract-ocr/tesseract",[5467],"nofollow","Tesseract"," を gosseract 経由で、または OCR API を使う。生成は gpdf、OCR は別経路。",[89,5471,5472,5474,5475,5480],{},[22,5473,215],{},": gpdf は生成専用。読み取りは ",[5463,5476,5479],{"href":5477,"rel":5478},"https://github.com/pdfcpu/pdfcpu",[5467],"pdfcpu"," が広く使え (Apache 2.0)、unipdf を解析専用に残せばライセンス購入数を減らせる可能性がある。",[89,5482,5483,5486],{},[22,5484,5485],{},"AcroForm の新規フィールド作成",": gpdf は既存 AcroForm のフラット化はできるが、新規フィールドの作成はまだ。ビューアでユーザーが入力するフォーム PDF を作っているなら、ここがギャップ。ロードマップに乗っている。",[89,5488,5489,5492],{},[22,5490,5491],{},"Redaction (黒塗り)",": gpdf のロードマップにはない。redaction は何を黒塗りするかを判定するためにレンダラ側の知識が必要で、生成とは別アーキテクチャ。",[19,5494,5495,5497],{},[22,5496,255],{}," ─ これは大半の unipdf 請求書の対象 ─ は完全に置き換えられる。",[14,5499,5501],{"id":5500},"faq","FAQ",[19,5503,5504,5507],{},[22,5505,5506],{},"gpdf は unipdf のフォークですか?","\n違う。gpdf は純 Go によるクリーンな再実装。PDF のワイヤフォーマット、レイアウトエンジン、TrueType サブセッタ、AES、PKCS#7 — 全てゼロから書かれている。unipdf からコードをコピーしていないため、ライセンス上の論争にもならない。",[19,5509,5510,5513,5514,5519],{},[22,5511,5512],{},"本当に MIT なのか? 「条件次第で AGPL」みたいな付帯条項はない?","\nない。リポジトリの ",[5463,5515,5518],{"href":5516,"rel":5517},"https://github.com/gpdf-dev/gpdf/blob/main/LICENSE",[5467],"LICENSE"," は MIT そのまま。追記なし、分野別の使用制限なし、商用枠の切り出しなし。クローズドソースの製品に組み込んで配布、商用 SaaS に同梱、オンプレアプライアンスに同梱、すべて可能。義務は配布物にライセンス・著作権表記を含めることだけ。",[19,5521,5522,5525,5526,5529,5530,5533,5534,5536,5537,5540],{},[22,5523,5524],{},"推移的依存に copyleft が混入していたりしない?","\ngpdf コアの ",[38,5527,5528],{},"go.mod"," の ",[38,5531,5532],{},"require"," ブロックは空。推移的 AGPL も GPL も何もない。",[38,5535,5330],{}," 後に ",[38,5538,5539],{},"go mod graph | grep gpdf"," で確認できる。",[19,5542,5543,5546],{},[22,5544,5545],{},"ライセンスキーを消すことが、そんなに重要?","\nチームによっては「全て」。キーはシークレットマネージャに置き、ローテーションし、監査され、全コンテナイメージに含め、ログに漏らさないように扱う必要がある。マルチテナント SaaS で Pod が数百あれば、これは実運用上の負担。要件自体を消すと、インシデントの 1 クラスがなくなる。",[19,5548,5549,5556,5557,5560,5561,5565],{},[22,5550,5551,5552,5555],{},"今の unipdf コードは ",[38,5553,5554],{},"creator.Block.SetPos"," で絶対座標を多用している。gpdf に対応物は?","\nある。",[38,5558,5559],{},"page.Absolute(x, y, fn)"," でサブツリーを明示座標に置ける。ただしコードが絶対座標まみれの場合、レイアウトエンジンモデルへの移行は構文の話ではなく思考様式の話。見積もり前に ",[5463,5562,5564],{"href":5563},"/ja/blog/12-column-grid","12 カラムグリッドの記事"," を読むのが安全。書き直し後はだいたい元より短くなる。",[19,5567,5568,5571],{},[22,5569,5570],{},"もし将来 UniDoc が unipdf を MIT に再ライセンスしたら?","\n選択肢が 1 つ増える。gpdf の主張は「unipdf が永遠に AGPL である」ではなく、「起動時の登録呼び出しを要求するライセンスと、開発者ごとの財務更新は、大半のワークロードでは存在しなくていいコスト」というもの。仮に明日再ライセンスされても、ライセンスキーの運用面は削除されるまで残る。",[14,5573,5575],{"id":5574},"gpdf-を使ってみる","gpdf を使ってみる",[19,5577,5578],{},"gpdf は Go の PDF 生成ライブラリ。MIT、外部依存ゼロ、ライセンスキー不要、ネイティブ CJK 対応。",[264,5580,5584],{"className":5581,"code":5582,"language":5583,"meta":269,"style":269},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[38,5585,5586],{"__ignoreMap":269},[273,5587,5588,5590,5593],{"class":275,"line":276},[273,5589,268],{"class":294},[273,5591,5592],{"class":362}," get",[273,5594,5595],{"class":362}," github.com/gpdf-dev/gpdf\n",[19,5597,5598,5603,5604],{},[5463,5599,5602],{"href":5600,"rel":5601},"https://github.com/gpdf-dev/gpdf",[5467],"⭐ Star on GitHub"," · ",[5463,5605,5608],{"href":5606,"rel":5607},"https://gpdf.dev/ja/docs/quickstart",[5467],"ドキュメント",[14,5610,5611],{"id":5611},"次に読む",[5455,5613,5614,5620,5625,5631],{},[89,5615,5616],{},[5463,5617,5619],{"href":5618},"/ja/blog/embed-japanese-font","日本語フォントを gpdf に埋め込む方法",[89,5621,5622],{},[5463,5623,5624],{"href":5563},"12 カラムグリッド: Bootstrap 思考を PDF に持ち込む",[89,5626,5627],{},[5463,5628,5630],{"href":5629},"/ja/blog/gofpdf-migration","gofpdf はアーカイブされた。gpdf への移行ガイド",[89,5632,5633,5637],{},[5463,5634,5636],{"href":5606,"rel":5635},[5467],"Quickstart"," — 5 分セットアップ",[2948,5639,5640],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":269,"searchDepth":283,"depth":283,"links":5642},[5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,5654,5655,5656,5657],{"id":16,"depth":283,"text":17},{"id":77,"depth":283,"text":78},{"id":116,"depth":283,"text":116},{"id":259,"depth":283,"text":259},{"id":558,"depth":283,"text":559},{"id":913,"depth":283,"text":914},{"id":1743,"depth":283,"text":1744},{"id":2815,"depth":283,"text":2816},{"id":3570,"depth":283,"text":3571},{"id":4556,"depth":283,"text":4557},{"id":5338,"depth":283,"text":5338},{"id":5449,"depth":283,"text":5450},{"id":5500,"depth":283,"text":5501},{"id":5574,"depth":283,"text":5575},{"id":5611,"depth":283,"text":5611},"2026-04-29","unidoc/unipdf は AGPL v3 もしくは開発者ごとの商用ライセンス。MIT・ゼロ依存・ライセンスキー不要の gpdf への移行ガイド。",false,"md",{"name":5663,"totalTime":5664,"tools":5665,"steps":5667},"Go プロジェクトを unidoc/unipdf から gpdf に移行する","PT45M",[5666],"Go 1.22+",[5668,5670,5673,5676,5679,5682,5685],{"name":259,"text":5669},"main や init() 内の license.SetMeteredKey / license.SetLicenseKey 呼び出しを削除する。gpdf にはライセンスキーも metering API も起動時の登録手順も存在しない。",{"name":5671,"text":5672},"import パスを置き換える","github.com/unidoc/unipdf/v3/creator と github.com/unidoc/unipdf/v3/model を、github.com/gpdf-dev/gpdf、github.com/gpdf-dev/gpdf/document、github.com/gpdf-dev/gpdf/template に差し替える。",{"name":5674,"text":5675},"creator.New を gpdf.NewDocument に置き換える","gpdf.NewDocument(WithPageSize(document.A4), WithMargins(...)) でドキュメントを構築する。ページは doc.AddPage() が返す PageBuilder 単位で扱い、自由カーソルは持たない。",{"name":5677,"text":5678},"Paragraph / StyledParagraph を c.Text に書き換える","Paragraph を組み立てて c.Draw に渡す代わりに、カラム内で c.Text(string, options...) を呼ぶ。フォント・サイズ・色は構造体フィールドではなく per-text のオプションになる。",{"name":5680,"text":5681},"テーブルを 12 カラムグリッドで書き直す","creator.NewTable(cols).SetColumnWidths と SetCellSpan を、AutoRow 内の row.Col(span, fn) に置き換える。12 カラムグリッドが幅をパーセンテージで扱い、ページ分割も自動で行う。",{"name":5683,"text":5684},"フォントをパスではなくバイト列で再登録する","model.NewCompositePdfFontFromTTFFile を、構築時の gpdf.WithFont(name, ttfBytes) に置き換える。//go:embed で TTF をバイナリに同梱すれば、実行時にフォントパスを参照する必要がなくなる。",{"name":5686,"text":5687},"出力呼び出しを切り替える","c.WriteToFile(path) を doc.Generate() + os.WriteFile(path, data, 0o644) に書き換える。io.Writer に直接書くなら doc.Render(w) を使う。",null,{},"/ja/blog/unidoc-migration",{"title":5,"description":5659},"ja/blog/016.unidoc-migration",[5694,5695,5696],"migration","comparison","tutorial","Yk_lE-VbsFkws5292vQBiiVold7VUbGG8oaztHohD8U",1779199021904]