[{"data":1,"prerenderedAt":1550},["ShallowReactive",2],{"blog-zh-embed-japanese-font":3},{"id":4,"title":5,"author":6,"body":9,"date":1517,"description":1518,"draft":1519,"extension":1520,"howTo":1521,"image":1540,"meta":1541,"navigation":82,"path":1542,"seo":1543,"stem":1544,"tags":1545,"updated":1540,"__hash__":1549},"blogZh/zh/blog/003.embed-japanese-font.md","如何在 gpdf 中嵌入日文字体？",{"name":7,"url":8},"gpdf team","https://gpdf.dev",{"type":10,"value":11,"toc":1506},"minimark",[12,16,33,36,52,55,704,724,727,730,736,746,760,763,774,928,946,949,956,1389,1396,1400,1406,1414,1430,1433,1466,1470,1473,1490,1502],[13,14,15],"h2",{"id":15},"这个问题的另一种表达",[17,18,19,20,27,28,32],"p",{},"如何用 ",[21,22,26],"a",{"href":23,"rel":24},"https://github.com/gpdf-dev/gpdf",[25],"nofollow","gpdf"," 生成带日文（或任意 CJK）文本的 PDF —— 不用重复 ",[29,30,31],"code",{},"AddUTF8Font"," 那一套，不引入 CGO，也不在每个 PDF 里塞 5 MB 的字体文件？",[13,34,35],{"id":35},"速答",[17,37,38,39,42,43,46,47,51],{},"读取 TTF 字节；把 ",[29,40,41],{},"gpdf.WithFont(\"NotoSansJP\", fontBytes)"," 传给 ",[29,44,45],{},"NewDocument","；可选地设为默认字体。",[48,49,50],"strong",{},"三行设置，gpdf 会自动把实际用到的字形子集化","，最终 PDF 里只携带你用到的那部分字形。",[13,53,54],{"id":54},"完整示例",[56,57,62],"pre",{"className":58,"code":59,"language":60,"meta":61,"style":61},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","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    font, err := os.ReadFile(\"NotoSansJP-Regular.ttf\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(gpdf.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n        gpdf.WithFont(\"NotoSansJP\", font),\n        gpdf.WithDefaultFont(\"NotoSansJP\", 12),\n    )\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"こんにちは、世界。\", template.FontSize(24), template.Bold())\n            c.Text(\"日本語 PDF、これだけ。\")\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","go","",[29,63,64,77,84,94,106,116,121,131,141,151,157,162,178,217,233,251,257,262,280,303,341,367,392,398,403,422,456,493,541,561,567,573,578,599,612,627,632,678,693,698],{"__ignoreMap":61},[65,66,69,73],"span",{"class":67,"line":68},"line",1,[65,70,72],{"class":71},"sMK4o","package",[65,74,76],{"class":75},"sBMFI"," main\n",[65,78,80],{"class":67,"line":79},2,[65,81,83],{"emptyLinePlaceholder":82},true,"\n",[65,85,87,91],{"class":67,"line":86},3,[65,88,90],{"class":89},"s7zQu","import",[65,92,93],{"class":71}," (\n",[65,95,97,100,103],{"class":67,"line":96},4,[65,98,99],{"class":71},"    \"",[65,101,102],{"class":75},"log",[65,104,105],{"class":71},"\"\n",[65,107,109,111,114],{"class":67,"line":108},5,[65,110,99],{"class":71},[65,112,113],{"class":75},"os",[65,115,105],{"class":71},[65,117,119],{"class":67,"line":118},6,[65,120,83],{"emptyLinePlaceholder":82},[65,122,124,126,129],{"class":67,"line":123},7,[65,125,99],{"class":71},[65,127,128],{"class":75},"github.com/gpdf-dev/gpdf",[65,130,105],{"class":71},[65,132,134,136,139],{"class":67,"line":133},8,[65,135,99],{"class":71},[65,137,138],{"class":75},"github.com/gpdf-dev/gpdf/document",[65,140,105],{"class":71},[65,142,144,146,149],{"class":67,"line":143},9,[65,145,99],{"class":71},[65,147,148],{"class":75},"github.com/gpdf-dev/gpdf/template",[65,150,105],{"class":71},[65,152,154],{"class":67,"line":153},10,[65,155,156],{"class":71},")\n",[65,158,160],{"class":67,"line":159},11,[65,161,83],{"emptyLinePlaceholder":82},[65,163,165,168,172,175],{"class":67,"line":164},12,[65,166,167],{"class":71},"func",[65,169,171],{"class":170},"s2Zo4"," main",[65,173,174],{"class":71},"()",[65,176,177],{"class":71}," {\n",[65,179,181,185,188,191,194,197,200,203,206,209,213,215],{"class":67,"line":180},13,[65,182,184],{"class":183},"sTEyZ","    font",[65,186,187],{"class":71},",",[65,189,190],{"class":183}," err ",[65,192,193],{"class":71},":=",[65,195,196],{"class":183}," os",[65,198,199],{"class":71},".",[65,201,202],{"class":170},"ReadFile",[65,204,205],{"class":71},"(",[65,207,208],{"class":71},"\"",[65,210,212],{"class":211},"sfazB","NotoSansJP-Regular.ttf",[65,214,208],{"class":71},[65,216,156],{"class":71},[65,218,220,223,225,228,231],{"class":67,"line":219},14,[65,221,222],{"class":89},"    if",[65,224,190],{"class":183},[65,226,227],{"class":71},"!=",[65,229,230],{"class":71}," nil",[65,232,177],{"class":71},[65,234,236,239,241,244,246,249],{"class":67,"line":235},15,[65,237,238],{"class":183},"        log",[65,240,199],{"class":71},[65,242,243],{"class":170},"Fatal",[65,245,205],{"class":71},[65,247,248],{"class":183},"err",[65,250,156],{"class":71},[65,252,254],{"class":67,"line":253},16,[65,255,256],{"class":71},"    }\n",[65,258,260],{"class":67,"line":259},17,[65,261,83],{"emptyLinePlaceholder":82},[65,263,265,268,270,273,275,277],{"class":67,"line":264},18,[65,266,267],{"class":183},"    doc ",[65,269,193],{"class":71},[65,271,272],{"class":183}," gpdf",[65,274,199],{"class":71},[65,276,45],{"class":170},[65,278,279],{"class":71},"(\n",[65,281,283,286,288,291,293,295,297,300],{"class":67,"line":282},19,[65,284,285],{"class":183},"        gpdf",[65,287,199],{"class":71},[65,289,290],{"class":170},"WithPageSize",[65,292,205],{"class":71},[65,294,26],{"class":183},[65,296,199],{"class":71},[65,298,299],{"class":183},"A4",[65,301,302],{"class":71},"),\n",[65,304,306,308,310,313,315,318,320,323,325,327,329,332,334,338],{"class":67,"line":305},20,[65,307,285],{"class":183},[65,309,199],{"class":71},[65,311,312],{"class":170},"WithMargins",[65,314,205],{"class":71},[65,316,317],{"class":183},"document",[65,319,199],{"class":71},[65,321,322],{"class":170},"UniformEdges",[65,324,205],{"class":71},[65,326,317],{"class":183},[65,328,199],{"class":71},[65,330,331],{"class":170},"Mm",[65,333,205],{"class":71},[65,335,337],{"class":336},"sbssI","20",[65,339,340],{"class":71},"))),\n",[65,342,344,346,348,351,353,355,358,360,362,365],{"class":67,"line":343},21,[65,345,285],{"class":183},[65,347,199],{"class":71},[65,349,350],{"class":170},"WithFont",[65,352,205],{"class":71},[65,354,208],{"class":71},[65,356,357],{"class":211},"NotoSansJP",[65,359,208],{"class":71},[65,361,187],{"class":71},[65,363,364],{"class":183}," font",[65,366,302],{"class":71},[65,368,370,372,374,377,379,381,383,385,387,390],{"class":67,"line":369},22,[65,371,285],{"class":183},[65,373,199],{"class":71},[65,375,376],{"class":170},"WithDefaultFont",[65,378,205],{"class":71},[65,380,208],{"class":71},[65,382,357],{"class":211},[65,384,208],{"class":71},[65,386,187],{"class":71},[65,388,389],{"class":336}," 12",[65,391,302],{"class":71},[65,393,395],{"class":67,"line":394},23,[65,396,397],{"class":71},"    )\n",[65,399,401],{"class":67,"line":400},24,[65,402,83],{"emptyLinePlaceholder":82},[65,404,406,409,411,414,416,419],{"class":67,"line":405},25,[65,407,408],{"class":183},"    page ",[65,410,193],{"class":71},[65,412,413],{"class":183}," doc",[65,415,199],{"class":71},[65,417,418],{"class":170},"AddPage",[65,420,421],{"class":71},"()\n",[65,423,425,428,430,433,436,440,443,446,448,451,454],{"class":67,"line":424},26,[65,426,427],{"class":183},"    page",[65,429,199],{"class":71},[65,431,432],{"class":170},"AutoRow",[65,434,435],{"class":71},"(func(",[65,437,439],{"class":438},"sHdIc","r",[65,441,442],{"class":71}," *",[65,444,445],{"class":75},"template",[65,447,199],{"class":71},[65,449,450],{"class":75},"RowBuilder",[65,452,453],{"class":71},")",[65,455,177],{"class":71},[65,457,459,462,464,467,469,472,474,477,480,482,484,486,489,491],{"class":67,"line":458},27,[65,460,461],{"class":183},"        r",[65,463,199],{"class":71},[65,465,466],{"class":170},"Col",[65,468,205],{"class":71},[65,470,471],{"class":336},"12",[65,473,187],{"class":71},[65,475,476],{"class":71}," func(",[65,478,479],{"class":438},"c",[65,481,442],{"class":71},[65,483,445],{"class":75},[65,485,199],{"class":71},[65,487,488],{"class":75},"ColBuilder",[65,490,453],{"class":71},[65,492,177],{"class":71},[65,494,496,499,501,504,506,508,511,513,515,518,520,523,525,528,531,533,535,538],{"class":67,"line":495},28,[65,497,498],{"class":183},"            c",[65,500,199],{"class":71},[65,502,503],{"class":170},"Text",[65,505,205],{"class":71},[65,507,208],{"class":71},[65,509,510],{"class":211},"こんにちは、世界。",[65,512,208],{"class":71},[65,514,187],{"class":71},[65,516,517],{"class":183}," template",[65,519,199],{"class":71},[65,521,522],{"class":170},"FontSize",[65,524,205],{"class":71},[65,526,527],{"class":336},"24",[65,529,530],{"class":71},"),",[65,532,517],{"class":183},[65,534,199],{"class":71},[65,536,537],{"class":170},"Bold",[65,539,540],{"class":71},"())\n",[65,542,544,546,548,550,552,554,557,559],{"class":67,"line":543},29,[65,545,498],{"class":183},[65,547,199],{"class":71},[65,549,503],{"class":170},[65,551,205],{"class":71},[65,553,208],{"class":71},[65,555,556],{"class":211},"日本語 PDF、これだけ。",[65,558,208],{"class":71},[65,560,156],{"class":71},[65,562,564],{"class":67,"line":563},30,[65,565,566],{"class":71},"        })\n",[65,568,570],{"class":67,"line":569},31,[65,571,572],{"class":71},"    })\n",[65,574,576],{"class":67,"line":575},32,[65,577,83],{"emptyLinePlaceholder":82},[65,579,581,584,586,588,590,592,594,597],{"class":67,"line":580},33,[65,582,583],{"class":183},"    data",[65,585,187],{"class":71},[65,587,190],{"class":183},[65,589,193],{"class":71},[65,591,413],{"class":183},[65,593,199],{"class":71},[65,595,596],{"class":170},"Generate",[65,598,421],{"class":71},[65,600,602,604,606,608,610],{"class":67,"line":601},34,[65,603,222],{"class":89},[65,605,190],{"class":183},[65,607,227],{"class":71},[65,609,230],{"class":71},[65,611,177],{"class":71},[65,613,615,617,619,621,623,625],{"class":67,"line":614},35,[65,616,238],{"class":183},[65,618,199],{"class":71},[65,620,243],{"class":170},[65,622,205],{"class":71},[65,624,248],{"class":183},[65,626,156],{"class":71},[65,628,630],{"class":67,"line":629},36,[65,631,256],{"class":71},[65,633,635,637,639,641,643,645,648,650,652,655,657,659,662,664,667,670,672,674,676],{"class":67,"line":634},37,[65,636,222],{"class":89},[65,638,190],{"class":183},[65,640,193],{"class":71},[65,642,196],{"class":183},[65,644,199],{"class":71},[65,646,647],{"class":170},"WriteFile",[65,649,205],{"class":71},[65,651,208],{"class":71},[65,653,654],{"class":211},"hello.pdf",[65,656,208],{"class":71},[65,658,187],{"class":71},[65,660,661],{"class":183}," data",[65,663,187],{"class":71},[65,665,666],{"class":336}," 0o644",[65,668,669],{"class":71},");",[65,671,190],{"class":183},[65,673,227],{"class":71},[65,675,230],{"class":71},[65,677,177],{"class":71},[65,679,681,683,685,687,689,691],{"class":67,"line":680},38,[65,682,238],{"class":183},[65,684,199],{"class":71},[65,686,243],{"class":170},[65,688,205],{"class":71},[65,690,248],{"class":183},[65,692,156],{"class":71},[65,694,696],{"class":67,"line":695},39,[65,697,256],{"class":71},[65,699,701],{"class":67,"line":700},40,[65,702,703],{"class":71},"}\n",[17,705,706,707,712,713,715,716,719,720,723],{},"从 ",[21,708,711],{"href":709,"rel":710},"https://fonts.google.com/noto/specimen/Noto+Sans+JP",[25],"Google Fonts"," 下载 ",[29,714,212],{},"，放到 ",[29,717,718],{},"main.go"," 旁边，运行 ",[29,721,722],{},"go run main.go","，就能得到一页带日文的 PDF。",[13,725,726],{"id":726},"这三行背后发生了什么",[17,728,729],{},"两件事在后台默默完成，都不需要你插手。",[17,731,732,735],{},[48,733,734],{},"子集化嵌入。"," Noto Sans JP 含约 17,000 个字形，Regular 单体约 5 MB。如果整字体直接嵌入，一张只印了四行日文的收据也会是 5 MB 起步。gpdf 会扫描已渲染的文本，算出用到的字形 ID，仅把这个子集写进 PDF。一张短小的发票通常只携带 20–40 KB 的字体数据，而不是 5 MB。",[17,737,738,739,741,742,745],{},"gofpdf 也能做子集化，但它要求 ",[29,740,31],{}," 接收文件路径和 UTF-8 标志，并在游标移动过程中完成加载 —— 文档中途切换字体就显得别扭。gpdf 在构造阶段一次性注册，之后每次 ",[29,743,744],{},"c.Text"," 只按字体族名引用，不再需要逐次准备。",[17,747,748,751,752,755,756,759],{},[48,749,750],{},"不使用 CGO。"," 这一点比听起来重要。很多语言生态里的字体处理要走 FreeType 或 HarfBuzz，结果就是一个 C 依赖、构建缓存失效方式改变、Docker 镜像多出层次、从 macOS 交叉编译到 ",[29,753,754],{},"linux/arm64"," 也开始需要额外配置。gpdf 用纯 Go 解析 TrueType 表，",[29,757,758],{},"go build"," 仍然产出静态二进制。distroless 镜像里放一个 Go 二进制加一个 TTF 文件就够了。",[13,761,762],{"id":762},"粗体与斜体",[17,764,765,766,769,770,773],{},"日文 Noto 家族每个字重都是单独的文件。要用",[48,767,768],{},"粗体","，把 Bold 的 TTF 以 ",[29,771,772],{},"-Bold"," 后缀单独注册：",[56,775,777],{"className":58,"code":776,"language":60,"meta":61,"style":61},"reg, _ := os.ReadFile(\"NotoSansJP-Regular.ttf\")\nbold, _ := os.ReadFile(\"NotoSansJP-Bold.ttf\")\n\ndoc := gpdf.NewDocument(\n    gpdf.WithFont(\"NotoSansJP\", reg),\n    gpdf.WithFont(\"NotoSansJP-Bold\", bold),\n    gpdf.WithDefaultFont(\"NotoSansJP\", 12),\n)\n",[29,778,779,807,835,839,854,878,902,924],{"__ignoreMap":61},[65,780,781,784,786,789,791,793,795,797,799,801,803,805],{"class":67,"line":68},[65,782,783],{"class":183},"reg",[65,785,187],{"class":71},[65,787,788],{"class":183}," _ ",[65,790,193],{"class":71},[65,792,196],{"class":183},[65,794,199],{"class":71},[65,796,202],{"class":170},[65,798,205],{"class":71},[65,800,208],{"class":71},[65,802,212],{"class":211},[65,804,208],{"class":71},[65,806,156],{"class":71},[65,808,809,812,814,816,818,820,822,824,826,828,831,833],{"class":67,"line":79},[65,810,811],{"class":183},"bold",[65,813,187],{"class":71},[65,815,788],{"class":183},[65,817,193],{"class":71},[65,819,196],{"class":183},[65,821,199],{"class":71},[65,823,202],{"class":170},[65,825,205],{"class":71},[65,827,208],{"class":71},[65,829,830],{"class":211},"NotoSansJP-Bold.ttf",[65,832,208],{"class":71},[65,834,156],{"class":71},[65,836,837],{"class":67,"line":86},[65,838,83],{"emptyLinePlaceholder":82},[65,840,841,844,846,848,850,852],{"class":67,"line":96},[65,842,843],{"class":183},"doc ",[65,845,193],{"class":71},[65,847,272],{"class":183},[65,849,199],{"class":71},[65,851,45],{"class":170},[65,853,279],{"class":71},[65,855,856,859,861,863,865,867,869,871,873,876],{"class":67,"line":108},[65,857,858],{"class":183},"    gpdf",[65,860,199],{"class":71},[65,862,350],{"class":170},[65,864,205],{"class":71},[65,866,208],{"class":71},[65,868,357],{"class":211},[65,870,208],{"class":71},[65,872,187],{"class":71},[65,874,875],{"class":183}," reg",[65,877,302],{"class":71},[65,879,880,882,884,886,888,890,893,895,897,900],{"class":67,"line":118},[65,881,858],{"class":183},[65,883,199],{"class":71},[65,885,350],{"class":170},[65,887,205],{"class":71},[65,889,208],{"class":71},[65,891,892],{"class":211},"NotoSansJP-Bold",[65,894,208],{"class":71},[65,896,187],{"class":71},[65,898,899],{"class":183}," bold",[65,901,302],{"class":71},[65,903,904,906,908,910,912,914,916,918,920,922],{"class":67,"line":123},[65,905,858],{"class":183},[65,907,199],{"class":71},[65,909,376],{"class":170},[65,911,205],{"class":71},[65,913,208],{"class":71},[65,915,357],{"class":211},[65,917,208],{"class":71},[65,919,187],{"class":71},[65,921,389],{"class":336},[65,923,302],{"class":71},[65,925,926],{"class":67,"line":133},[65,927,156],{"class":71},[17,929,930,931,934,935,937,938,941,942,945],{},"然后 ",[29,932,933],{},"template.Bold()"," 就会选中 ",[29,936,772],{}," 变体。",[29,939,940],{},"-Italic"," 与 ",[29,943,944],{},"-BoldItalic"," 同理。没注册变体时会回退到合成字重 —— 屏幕上能读，但字形并不地道。正式发票请注册真实字重。",[13,947,948],{"id":948},"在同一文档中混用中日韩",[17,950,951,952,955],{},"注册多少字体族都行，gpdf 彼此独立管理。用 ",[29,953,954],{},"template.FontFamily(...)"," 按文本切换：",[56,957,959],{"className":58,"code":958,"language":60,"meta":61,"style":61},"jp, _ := os.ReadFile(\"NotoSansJP-Regular.ttf\")\nsc, _ := os.ReadFile(\"NotoSansSC-Regular.ttf\")\nkr, _ := os.ReadFile(\"NotoSansKR-Regular.ttf\")\n\ndoc := gpdf.NewDocument(\n    gpdf.WithFont(\"NotoSansJP\", jp),\n    gpdf.WithFont(\"NotoSansSC\", sc),\n    gpdf.WithFont(\"NotoSansKR\", kr),\n    gpdf.WithDefaultFont(\"NotoSansJP\", 12),\n)\n\npage.AutoRow(func(r *template.RowBuilder) {\n    r.Col(4, func(c *template.ColBuilder) {\n        c.Text(\"日本語\")\n    })\n    r.Col(4, func(c *template.ColBuilder) {\n        c.Text(\"中文\", template.FontFamily(\"NotoSansSC\"))\n    })\n    r.Col(4, func(c *template.ColBuilder) {\n        c.Text(\"한국어\", template.FontFamily(\"NotoSansKR\"))\n    })\n})\n",[29,960,961,988,1016,1044,1048,1062,1085,1109,1133,1155,1159,1163,1188,1220,1240,1244,1274,1311,1315,1345,1380,1384],{"__ignoreMap":61},[65,962,963,966,968,970,972,974,976,978,980,982,984,986],{"class":67,"line":68},[65,964,965],{"class":183},"jp",[65,967,187],{"class":71},[65,969,788],{"class":183},[65,971,193],{"class":71},[65,973,196],{"class":183},[65,975,199],{"class":71},[65,977,202],{"class":170},[65,979,205],{"class":71},[65,981,208],{"class":71},[65,983,212],{"class":211},[65,985,208],{"class":71},[65,987,156],{"class":71},[65,989,990,993,995,997,999,1001,1003,1005,1007,1009,1012,1014],{"class":67,"line":79},[65,991,992],{"class":183},"sc",[65,994,187],{"class":71},[65,996,788],{"class":183},[65,998,193],{"class":71},[65,1000,196],{"class":183},[65,1002,199],{"class":71},[65,1004,202],{"class":170},[65,1006,205],{"class":71},[65,1008,208],{"class":71},[65,1010,1011],{"class":211},"NotoSansSC-Regular.ttf",[65,1013,208],{"class":71},[65,1015,156],{"class":71},[65,1017,1018,1021,1023,1025,1027,1029,1031,1033,1035,1037,1040,1042],{"class":67,"line":86},[65,1019,1020],{"class":183},"kr",[65,1022,187],{"class":71},[65,1024,788],{"class":183},[65,1026,193],{"class":71},[65,1028,196],{"class":183},[65,1030,199],{"class":71},[65,1032,202],{"class":170},[65,1034,205],{"class":71},[65,1036,208],{"class":71},[65,1038,1039],{"class":211},"NotoSansKR-Regular.ttf",[65,1041,208],{"class":71},[65,1043,156],{"class":71},[65,1045,1046],{"class":67,"line":96},[65,1047,83],{"emptyLinePlaceholder":82},[65,1049,1050,1052,1054,1056,1058,1060],{"class":67,"line":108},[65,1051,843],{"class":183},[65,1053,193],{"class":71},[65,1055,272],{"class":183},[65,1057,199],{"class":71},[65,1059,45],{"class":170},[65,1061,279],{"class":71},[65,1063,1064,1066,1068,1070,1072,1074,1076,1078,1080,1083],{"class":67,"line":118},[65,1065,858],{"class":183},[65,1067,199],{"class":71},[65,1069,350],{"class":170},[65,1071,205],{"class":71},[65,1073,208],{"class":71},[65,1075,357],{"class":211},[65,1077,208],{"class":71},[65,1079,187],{"class":71},[65,1081,1082],{"class":183}," jp",[65,1084,302],{"class":71},[65,1086,1087,1089,1091,1093,1095,1097,1100,1102,1104,1107],{"class":67,"line":123},[65,1088,858],{"class":183},[65,1090,199],{"class":71},[65,1092,350],{"class":170},[65,1094,205],{"class":71},[65,1096,208],{"class":71},[65,1098,1099],{"class":211},"NotoSansSC",[65,1101,208],{"class":71},[65,1103,187],{"class":71},[65,1105,1106],{"class":183}," sc",[65,1108,302],{"class":71},[65,1110,1111,1113,1115,1117,1119,1121,1124,1126,1128,1131],{"class":67,"line":133},[65,1112,858],{"class":183},[65,1114,199],{"class":71},[65,1116,350],{"class":170},[65,1118,205],{"class":71},[65,1120,208],{"class":71},[65,1122,1123],{"class":211},"NotoSansKR",[65,1125,208],{"class":71},[65,1127,187],{"class":71},[65,1129,1130],{"class":183}," kr",[65,1132,302],{"class":71},[65,1134,1135,1137,1139,1141,1143,1145,1147,1149,1151,1153],{"class":67,"line":143},[65,1136,858],{"class":183},[65,1138,199],{"class":71},[65,1140,376],{"class":170},[65,1142,205],{"class":71},[65,1144,208],{"class":71},[65,1146,357],{"class":211},[65,1148,208],{"class":71},[65,1150,187],{"class":71},[65,1152,389],{"class":336},[65,1154,302],{"class":71},[65,1156,1157],{"class":67,"line":153},[65,1158,156],{"class":71},[65,1160,1161],{"class":67,"line":159},[65,1162,83],{"emptyLinePlaceholder":82},[65,1164,1165,1168,1170,1172,1174,1176,1178,1180,1182,1184,1186],{"class":67,"line":164},[65,1166,1167],{"class":183},"page",[65,1169,199],{"class":71},[65,1171,432],{"class":170},[65,1173,435],{"class":71},[65,1175,439],{"class":438},[65,1177,442],{"class":71},[65,1179,445],{"class":75},[65,1181,199],{"class":71},[65,1183,450],{"class":75},[65,1185,453],{"class":71},[65,1187,177],{"class":71},[65,1189,1190,1193,1195,1197,1199,1202,1204,1206,1208,1210,1212,1214,1216,1218],{"class":67,"line":180},[65,1191,1192],{"class":183},"    r",[65,1194,199],{"class":71},[65,1196,466],{"class":170},[65,1198,205],{"class":71},[65,1200,1201],{"class":336},"4",[65,1203,187],{"class":71},[65,1205,476],{"class":71},[65,1207,479],{"class":438},[65,1209,442],{"class":71},[65,1211,445],{"class":75},[65,1213,199],{"class":71},[65,1215,488],{"class":75},[65,1217,453],{"class":71},[65,1219,177],{"class":71},[65,1221,1222,1225,1227,1229,1231,1233,1236,1238],{"class":67,"line":219},[65,1223,1224],{"class":183},"        c",[65,1226,199],{"class":71},[65,1228,503],{"class":170},[65,1230,205],{"class":71},[65,1232,208],{"class":71},[65,1234,1235],{"class":211},"日本語",[65,1237,208],{"class":71},[65,1239,156],{"class":71},[65,1241,1242],{"class":67,"line":235},[65,1243,572],{"class":71},[65,1245,1246,1248,1250,1252,1254,1256,1258,1260,1262,1264,1266,1268,1270,1272],{"class":67,"line":253},[65,1247,1192],{"class":183},[65,1249,199],{"class":71},[65,1251,466],{"class":170},[65,1253,205],{"class":71},[65,1255,1201],{"class":336},[65,1257,187],{"class":71},[65,1259,476],{"class":71},[65,1261,479],{"class":438},[65,1263,442],{"class":71},[65,1265,445],{"class":75},[65,1267,199],{"class":71},[65,1269,488],{"class":75},[65,1271,453],{"class":71},[65,1273,177],{"class":71},[65,1275,1276,1278,1280,1282,1284,1286,1289,1291,1293,1295,1297,1300,1302,1304,1306,1308],{"class":67,"line":259},[65,1277,1224],{"class":183},[65,1279,199],{"class":71},[65,1281,503],{"class":170},[65,1283,205],{"class":71},[65,1285,208],{"class":71},[65,1287,1288],{"class":211},"中文",[65,1290,208],{"class":71},[65,1292,187],{"class":71},[65,1294,517],{"class":183},[65,1296,199],{"class":71},[65,1298,1299],{"class":170},"FontFamily",[65,1301,205],{"class":71},[65,1303,208],{"class":71},[65,1305,1099],{"class":211},[65,1307,208],{"class":71},[65,1309,1310],{"class":71},"))\n",[65,1312,1313],{"class":67,"line":264},[65,1314,572],{"class":71},[65,1316,1317,1319,1321,1323,1325,1327,1329,1331,1333,1335,1337,1339,1341,1343],{"class":67,"line":282},[65,1318,1192],{"class":183},[65,1320,199],{"class":71},[65,1322,466],{"class":170},[65,1324,205],{"class":71},[65,1326,1201],{"class":336},[65,1328,187],{"class":71},[65,1330,476],{"class":71},[65,1332,479],{"class":438},[65,1334,442],{"class":71},[65,1336,445],{"class":75},[65,1338,199],{"class":71},[65,1340,488],{"class":75},[65,1342,453],{"class":71},[65,1344,177],{"class":71},[65,1346,1347,1349,1351,1353,1355,1357,1360,1362,1364,1366,1368,1370,1372,1374,1376,1378],{"class":67,"line":305},[65,1348,1224],{"class":183},[65,1350,199],{"class":71},[65,1352,503],{"class":170},[65,1354,205],{"class":71},[65,1356,208],{"class":71},[65,1358,1359],{"class":211},"한국어",[65,1361,208],{"class":71},[65,1363,187],{"class":71},[65,1365,517],{"class":183},[65,1367,199],{"class":71},[65,1369,1299],{"class":170},[65,1371,205],{"class":71},[65,1373,208],{"class":71},[65,1375,1123],{"class":211},[65,1377,208],{"class":71},[65,1379,1310],{"class":71},[65,1381,1382],{"class":67,"line":343},[65,1383,572],{"class":71},[65,1385,1386],{"class":67,"line":369},[65,1387,1388],{"class":71},"})\n",[17,1390,1391,1392,1395],{},"受 Han Unification 影响，日文与简体中文共享 Unicode 码位，但字形并不相同。",[48,1393,1394],{},"同一码位在不同字体下会渲染成不同字形"," —— 字体选择不是美学问题，而是正确性问题。给跨境业务做发票、运单时，需要同时注册两个字体族。",[13,1397,1399],{"id":1398},"常见陷阱豆腐字","常见陷阱：豆腐字",[17,1401,1402,1403,1405],{},"如果写了日文却没注册 ",[29,1404,350],{},"，gpdf 会回退到 Base-14 标准 PDF 字体 —— 它们不包含 CJK 字形，结果字符会显示成一串空矩形，俗称「豆腐字」：",[56,1407,1412],{"className":1408,"code":1410,"language":1411},[1409],"language-text","□□□□□、□□。\n","text",[29,1413,1410],{"__ignoreMap":61},[17,1415,1416,1417,1419,1420,1422,1423,1425,1426,1429],{},"看到这种输出，原因只有一个：没有注册 CJK 字体，或者用的字体族不含这些字形。修复方式也只有一个：加上 ",[29,1418,350],{},"，再用 ",[29,1421,376],{}," 设为默认，或在 ",[29,1424,744],{}," 上显式传入 ",[29,1427,1428],{},"template.FontFamily","。",[13,1431,1432],{"id":1432},"延伸阅读",[1434,1435,1436,1448,1455],"ul",{},[1437,1438,1439,1443,1444,1447],"li",{},[21,1440,1442],{"href":1441},"/zh/blog/gofpdf-migration","gofpdf 已归档。如何迁移到 gpdf。"," —— 从 ",[29,1445,1446],{},"pdf.AddUTF8Font"," 迁移的完整映射",[1437,1449,1450,1454],{},[21,1451,1453],{"href":1452},"/zh/blog/go-pdf-library-showdown-2026","Go PDF 库横评 2026"," —— gpdf 与 gofpdf、gopdf、Maroto、unipdf 在 CJK 上的对比",[1437,1456,1457,1462,1463,1465],{},[21,1458,1461],{"href":1459,"rel":1460},"https://gpdf.dev/zh/docs/guide/fonts",[25],"字体指南"," —— ",[29,1464,350],{}," 的完整参考与变体命名规则",[13,1467,1469],{"id":1468},"试试-gpdf","试试 gpdf",[17,1471,1472],{},"gpdf 是一个 Go PDF 生成库。MIT 协议、零外部依赖、原生支持 CJK。",[56,1474,1478],{"className":1475,"code":1476,"language":1477,"meta":61,"style":61},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[29,1479,1480],{"__ignoreMap":61},[65,1481,1482,1484,1487],{"class":67,"line":68},[65,1483,60],{"class":75},[65,1485,1486],{"class":211}," get",[65,1488,1489],{"class":211}," github.com/gpdf-dev/gpdf\n",[17,1491,1492,1496,1497],{},[21,1493,1495],{"href":23,"rel":1494},[25],"⭐ 在 GitHub 上 Star"," · ",[21,1498,1501],{"href":1499,"rel":1500},"https://gpdf.dev/zh/docs/quickstart",[25],"阅读文档",[1503,1504,1505],"style",{},"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 .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 .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 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 .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);}",{"title":61,"searchDepth":79,"depth":79,"links":1507},[1508,1509,1510,1511,1512,1513,1514,1515,1516],{"id":15,"depth":79,"text":15},{"id":35,"depth":79,"text":35},{"id":54,"depth":79,"text":54},{"id":726,"depth":79,"text":726},{"id":762,"depth":79,"text":762},{"id":948,"depth":79,"text":948},{"id":1398,"depth":79,"text":1399},{"id":1432,"depth":79,"text":1432},{"id":1468,"depth":79,"text":1469},"2026-04-15","将 TTF 字节传给 gpdf.WithFont 即可。自动子集化嵌入、无需 CGO，用 Go 生成日文 PDF 的最短路径。",false,"md",{"name":1522,"totalTime":1523,"tools":1524,"steps":1527},"在 gpdf 文档中嵌入日文 TrueType 字体","PT10M",[1525,1526],"Go 1.22+","NotoSansJP-Regular.ttf（或任意支持 CJK 的 TTF）",[1528,1531,1534,1537],{"name":1529,"text":1530},"读取 TTF 字节","程序启动时用 os.ReadFile 将 NotoSansJP-Regular.ttf 读入 []byte。若希望把字体编进二进制，也可以使用 //go:embed。",{"name":1532,"text":1533},"在构造文档时注册字体","把 gpdf.WithFont(\"NotoSansJP\", fontBytes) 传给 gpdf.NewDocument。字体族名可自由命名 —— 只要后续引用的名字一致即可。gpdf 在渲染时会自动做字形子集化。",{"name":1535,"text":1536},"设为默认字体","再加一行 gpdf.WithDefaultFont(\"NotoSansJP\", 12)，之后 c.Text 调用就会默认使用日文字体，无需每次传 FontFamily。",{"name":1538,"text":1539},"写入日文并生成 PDF","在列中调用 c.Text(\"こんにちは、世界。\")。然后 doc.Generate() 返回 []byte，再用 os.WriteFile 写盘即可。",null,{},"/zh/blog/embed-japanese-font",{"title":5,"description":1518},"zh/blog/003.embed-japanese-font",[1546,1547,1548],"recipe","cjk","tutorial","3Ln4Ib5HbWG7IO0kOQdIug4QaGnJzDe3GaMA8MoPtKk",1776529262330]