[{"data":1,"prerenderedAt":1612},["ShallowReactive",2],{"blog-en-noto-sans-jp-with-gpdf":3},{"id":4,"title":5,"author":6,"body":9,"date":1579,"description":1580,"draft":1581,"extension":1582,"howTo":1583,"image":1602,"meta":1603,"navigation":85,"path":1604,"seo":1605,"stem":1606,"tags":1607,"updated":1602,"__hash__":1611},"blog/blog/004.noto-sans-jp-with-gpdf.md","How do I use Noto Sans JP with gpdf?",{"name":7,"url":8},"gpdf team","https://gpdf.dev",{"type":10,"value":11,"toc":1566},"minimark",[12,17,29,33,54,58,707,727,731,742,769,774,801,804,808,811,880,902,915,919,922,1075,1094,1097,1169,1180,1184,1187,1190,1257,1260,1263,1267,1270,1276,1289,1298,1312,1316,1319,1478,1485,1489,1526,1530,1533,1550,1562],[13,14,16],"h2",{"id":15},"the-question-in-other-words","The question, in other words",[18,19,20,21,28],"p",{},"You want Japanese text in a ",[22,23,27],"a",{"href":24,"rel":25},"https://github.com/gpdf-dev/gpdf",[26],"nofollow","gpdf"," document, you've picked Noto Sans JP — Google's free, SIL-OFL-licensed sans-serif that covers the full JIS range — and you want to know the three things nobody spells out: which file to download, which weights to register, and the one footgun hiding in the zip.",[13,30,32],{"id":31},"tldr","TL;DR",[18,34,35,36,40,41,45,46,49,50,53],{},"Use the ",[37,38,39],"strong",{},"static"," ",[42,43,44],"code",{},"NotoSansJP-Regular.ttf"," from the ",[42,47,48],{},"static/"," folder inside the Google Fonts zip. Not the variable font at the root. Pass it to ",[42,51,52],{},"gpdf.WithFont(\"NotoSansJP\", bytes)"," and set it as the default. gpdf subsets the ~17,000 glyphs down to whatever you rendered — an invoice typically carries 20–40 KB of font data in the final PDF.",[13,55,57],{"id":56},"the-complete-example","The complete example",[59,60,65],"pre",{"className":61,"code":62,"language":63,"meta":64,"style":64},"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\", 11),\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(28), template.Bold())\n            c.Text(\"Noto Sans JP、これで十分。\")\n        })\n    })\n\n    data, err := doc.Generate()\n    if err != nil {\n        log.Fatal(err)\n    }\n    if err := os.WriteFile(\"invoice.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n","go","",[42,66,67,80,87,97,109,119,124,134,144,154,160,165,181,219,235,253,259,264,283,306,344,370,395,401,406,425,459,496,544,564,570,576,581,602,615,630,635,681,696,701],{"__ignoreMap":64},[68,69,72,76],"span",{"class":70,"line":71},"line",1,[68,73,75],{"class":74},"sMK4o","package",[68,77,79],{"class":78},"sBMFI"," main\n",[68,81,83],{"class":70,"line":82},2,[68,84,86],{"emptyLinePlaceholder":85},true,"\n",[68,88,90,94],{"class":70,"line":89},3,[68,91,93],{"class":92},"s7zQu","import",[68,95,96],{"class":74}," (\n",[68,98,100,103,106],{"class":70,"line":99},4,[68,101,102],{"class":74},"    \"",[68,104,105],{"class":78},"log",[68,107,108],{"class":74},"\"\n",[68,110,112,114,117],{"class":70,"line":111},5,[68,113,102],{"class":74},[68,115,116],{"class":78},"os",[68,118,108],{"class":74},[68,120,122],{"class":70,"line":121},6,[68,123,86],{"emptyLinePlaceholder":85},[68,125,127,129,132],{"class":70,"line":126},7,[68,128,102],{"class":74},[68,130,131],{"class":78},"github.com/gpdf-dev/gpdf",[68,133,108],{"class":74},[68,135,137,139,142],{"class":70,"line":136},8,[68,138,102],{"class":74},[68,140,141],{"class":78},"github.com/gpdf-dev/gpdf/document",[68,143,108],{"class":74},[68,145,147,149,152],{"class":70,"line":146},9,[68,148,102],{"class":74},[68,150,151],{"class":78},"github.com/gpdf-dev/gpdf/template",[68,153,108],{"class":74},[68,155,157],{"class":70,"line":156},10,[68,158,159],{"class":74},")\n",[68,161,163],{"class":70,"line":162},11,[68,164,86],{"emptyLinePlaceholder":85},[68,166,168,171,175,178],{"class":70,"line":167},12,[68,169,170],{"class":74},"func",[68,172,174],{"class":173},"s2Zo4"," main",[68,176,177],{"class":74},"()",[68,179,180],{"class":74}," {\n",[68,182,184,188,191,194,197,200,203,206,209,212,215,217],{"class":70,"line":183},13,[68,185,187],{"class":186},"sTEyZ","    font",[68,189,190],{"class":74},",",[68,192,193],{"class":186}," err ",[68,195,196],{"class":74},":=",[68,198,199],{"class":186}," os",[68,201,202],{"class":74},".",[68,204,205],{"class":173},"ReadFile",[68,207,208],{"class":74},"(",[68,210,211],{"class":74},"\"",[68,213,44],{"class":214},"sfazB",[68,216,211],{"class":74},[68,218,159],{"class":74},[68,220,222,225,227,230,233],{"class":70,"line":221},14,[68,223,224],{"class":92},"    if",[68,226,193],{"class":186},[68,228,229],{"class":74},"!=",[68,231,232],{"class":74}," nil",[68,234,180],{"class":74},[68,236,238,241,243,246,248,251],{"class":70,"line":237},15,[68,239,240],{"class":186},"        log",[68,242,202],{"class":74},[68,244,245],{"class":173},"Fatal",[68,247,208],{"class":74},[68,249,250],{"class":186},"err",[68,252,159],{"class":74},[68,254,256],{"class":70,"line":255},16,[68,257,258],{"class":74},"    }\n",[68,260,262],{"class":70,"line":261},17,[68,263,86],{"emptyLinePlaceholder":85},[68,265,267,270,272,275,277,280],{"class":70,"line":266},18,[68,268,269],{"class":186},"    doc ",[68,271,196],{"class":74},[68,273,274],{"class":186}," gpdf",[68,276,202],{"class":74},[68,278,279],{"class":173},"NewDocument",[68,281,282],{"class":74},"(\n",[68,284,286,289,291,294,296,298,300,303],{"class":70,"line":285},19,[68,287,288],{"class":186},"        gpdf",[68,290,202],{"class":74},[68,292,293],{"class":173},"WithPageSize",[68,295,208],{"class":74},[68,297,27],{"class":186},[68,299,202],{"class":74},[68,301,302],{"class":186},"A4",[68,304,305],{"class":74},"),\n",[68,307,309,311,313,316,318,321,323,326,328,330,332,335,337,341],{"class":70,"line":308},20,[68,310,288],{"class":186},[68,312,202],{"class":74},[68,314,315],{"class":173},"WithMargins",[68,317,208],{"class":74},[68,319,320],{"class":186},"document",[68,322,202],{"class":74},[68,324,325],{"class":173},"UniformEdges",[68,327,208],{"class":74},[68,329,320],{"class":186},[68,331,202],{"class":74},[68,333,334],{"class":173},"Mm",[68,336,208],{"class":74},[68,338,340],{"class":339},"sbssI","20",[68,342,343],{"class":74},"))),\n",[68,345,347,349,351,354,356,358,361,363,365,368],{"class":70,"line":346},21,[68,348,288],{"class":186},[68,350,202],{"class":74},[68,352,353],{"class":173},"WithFont",[68,355,208],{"class":74},[68,357,211],{"class":74},[68,359,360],{"class":214},"NotoSansJP",[68,362,211],{"class":74},[68,364,190],{"class":74},[68,366,367],{"class":186}," font",[68,369,305],{"class":74},[68,371,373,375,377,380,382,384,386,388,390,393],{"class":70,"line":372},22,[68,374,288],{"class":186},[68,376,202],{"class":74},[68,378,379],{"class":173},"WithDefaultFont",[68,381,208],{"class":74},[68,383,211],{"class":74},[68,385,360],{"class":214},[68,387,211],{"class":74},[68,389,190],{"class":74},[68,391,392],{"class":339}," 11",[68,394,305],{"class":74},[68,396,398],{"class":70,"line":397},23,[68,399,400],{"class":74},"    )\n",[68,402,404],{"class":70,"line":403},24,[68,405,86],{"emptyLinePlaceholder":85},[68,407,409,412,414,417,419,422],{"class":70,"line":408},25,[68,410,411],{"class":186},"    page ",[68,413,196],{"class":74},[68,415,416],{"class":186}," doc",[68,418,202],{"class":74},[68,420,421],{"class":173},"AddPage",[68,423,424],{"class":74},"()\n",[68,426,428,431,433,436,439,443,446,449,451,454,457],{"class":70,"line":427},26,[68,429,430],{"class":186},"    page",[68,432,202],{"class":74},[68,434,435],{"class":173},"AutoRow",[68,437,438],{"class":74},"(func(",[68,440,442],{"class":441},"sHdIc","r",[68,444,445],{"class":74}," *",[68,447,448],{"class":78},"template",[68,450,202],{"class":74},[68,452,453],{"class":78},"RowBuilder",[68,455,456],{"class":74},")",[68,458,180],{"class":74},[68,460,462,465,467,470,472,475,477,480,483,485,487,489,492,494],{"class":70,"line":461},27,[68,463,464],{"class":186},"        r",[68,466,202],{"class":74},[68,468,469],{"class":173},"Col",[68,471,208],{"class":74},[68,473,474],{"class":339},"12",[68,476,190],{"class":74},[68,478,479],{"class":74}," func(",[68,481,482],{"class":441},"c",[68,484,445],{"class":74},[68,486,448],{"class":78},[68,488,202],{"class":74},[68,490,491],{"class":78},"ColBuilder",[68,493,456],{"class":74},[68,495,180],{"class":74},[68,497,499,502,504,507,509,511,514,516,518,521,523,526,528,531,534,536,538,541],{"class":70,"line":498},28,[68,500,501],{"class":186},"            c",[68,503,202],{"class":74},[68,505,506],{"class":173},"Text",[68,508,208],{"class":74},[68,510,211],{"class":74},[68,512,513],{"class":214},"請求書",[68,515,211],{"class":74},[68,517,190],{"class":74},[68,519,520],{"class":186}," template",[68,522,202],{"class":74},[68,524,525],{"class":173},"FontSize",[68,527,208],{"class":74},[68,529,530],{"class":339},"28",[68,532,533],{"class":74},"),",[68,535,520],{"class":186},[68,537,202],{"class":74},[68,539,540],{"class":173},"Bold",[68,542,543],{"class":74},"())\n",[68,545,547,549,551,553,555,557,560,562],{"class":70,"line":546},29,[68,548,501],{"class":186},[68,550,202],{"class":74},[68,552,506],{"class":173},[68,554,208],{"class":74},[68,556,211],{"class":74},[68,558,559],{"class":214},"Noto Sans JP、これで十分。",[68,561,211],{"class":74},[68,563,159],{"class":74},[68,565,567],{"class":70,"line":566},30,[68,568,569],{"class":74},"        })\n",[68,571,573],{"class":70,"line":572},31,[68,574,575],{"class":74},"    })\n",[68,577,579],{"class":70,"line":578},32,[68,580,86],{"emptyLinePlaceholder":85},[68,582,584,587,589,591,593,595,597,600],{"class":70,"line":583},33,[68,585,586],{"class":186},"    data",[68,588,190],{"class":74},[68,590,193],{"class":186},[68,592,196],{"class":74},[68,594,416],{"class":186},[68,596,202],{"class":74},[68,598,599],{"class":173},"Generate",[68,601,424],{"class":74},[68,603,605,607,609,611,613],{"class":70,"line":604},34,[68,606,224],{"class":92},[68,608,193],{"class":186},[68,610,229],{"class":74},[68,612,232],{"class":74},[68,614,180],{"class":74},[68,616,618,620,622,624,626,628],{"class":70,"line":617},35,[68,619,240],{"class":186},[68,621,202],{"class":74},[68,623,245],{"class":173},[68,625,208],{"class":74},[68,627,250],{"class":186},[68,629,159],{"class":74},[68,631,633],{"class":70,"line":632},36,[68,634,258],{"class":74},[68,636,638,640,642,644,646,648,651,653,655,658,660,662,665,667,670,673,675,677,679],{"class":70,"line":637},37,[68,639,224],{"class":92},[68,641,193],{"class":186},[68,643,196],{"class":74},[68,645,199],{"class":186},[68,647,202],{"class":74},[68,649,650],{"class":173},"WriteFile",[68,652,208],{"class":74},[68,654,211],{"class":74},[68,656,657],{"class":214},"invoice.pdf",[68,659,211],{"class":74},[68,661,190],{"class":74},[68,663,664],{"class":186}," data",[68,666,190],{"class":74},[68,668,669],{"class":339}," 0o644",[68,671,672],{"class":74},");",[68,674,193],{"class":186},[68,676,229],{"class":74},[68,678,232],{"class":74},[68,680,180],{"class":74},[68,682,684,686,688,690,692,694],{"class":70,"line":683},38,[68,685,240],{"class":186},[68,687,202],{"class":74},[68,689,245],{"class":173},[68,691,208],{"class":74},[68,693,250],{"class":186},[68,695,159],{"class":74},[68,697,699],{"class":70,"line":698},39,[68,700,258],{"class":74},[68,702,704],{"class":70,"line":703},40,[68,705,706],{"class":74},"}\n",[18,708,709,710,715,716,719,720,723,724,202],{},"Download the Noto Sans JP zip from ",[22,711,714],{"href":712,"rel":713},"https://fonts.google.com/noto/specimen/Noto+Sans+JP",[26],"Google Fonts",", extract ",[42,717,718],{},"static/NotoSansJP-Regular.ttf",", drop it next to ",[42,721,722],{},"main.go",", and run ",[42,725,726],{},"go run main.go",[13,728,730],{"id":729},"grab-the-static-ttf-not-the-variable-font","Grab the static TTF, not the variable font",[18,732,733,734,737,738,741],{},"Open the Google Fonts page, hit ",[37,735,736],{},"Get font"," → ",[37,739,740],{},"Download all",", unzip. You get two things that look interchangeable and aren't:",[743,744,745,756],"ul",{},[746,747,748,751,752,755],"li",{},[42,749,750],{},"NotoSansJP-VariableFont_wght.ttf"," at the root — the ",[37,753,754],{},"variable"," font, ~7 MB, carries every weight between 100 and 900 in a single file",[746,757,758,760,761,764,765,768],{},[42,759,48],{}," — nine separate TTFs, ",[42,762,763],{},"NotoSansJP-Thin.ttf"," through ",[42,766,767],{},"NotoSansJP-Black.ttf",", each ~5 MB",[18,770,771,772,202],{},"Pick from ",[42,773,48],{},[18,775,776,777,780,781,784,785,788,789,792,793,796,797,800],{},"gpdf's TrueType parser is deliberately scoped. It handles glyph outlines, composite glyphs, ",[42,778,779],{},"cmap",", and ",[42,782,783],{},"hmtx"," — the tables you need to render fixed-weight type. It does not evaluate ",[42,786,787],{},"fvar",", ",[42,790,791],{},"gvar",", or ",[42,794,795],{},"HVAR",", which are the OpenType tables that make variable fonts actually variable. Hand it the ",[42,798,799],{},"VariableFont_wght.ttf"," and the parser either errors out or falls through to the default instance glyphs, silently ignoring any weight axis you thought you were setting.",[18,802,803],{},"The file-size math also argues against it. A variable font bundles every weight's outlines — that's the whole point. If you use only Regular, you're paying for eight weights of outline data that never render. Static Regular is 5 MB; the variable font is 7 MB. Subsetting will prune both down, but the static file is cleaner input.",[13,805,807],{"id":806},"the-four-lines-that-matter","The four lines that matter",[18,809,810],{},"Everything interesting is in the constructor options:",[59,812,814],{"className":61,"code":813,"language":63,"meta":64,"style":64},"doc := gpdf.NewDocument(\n    gpdf.WithFont(\"NotoSansJP\", font),\n    gpdf.WithDefaultFont(\"NotoSansJP\", 11),\n)\n",[42,815,816,831,854,876],{"__ignoreMap":64},[68,817,818,821,823,825,827,829],{"class":70,"line":71},[68,819,820],{"class":186},"doc ",[68,822,196],{"class":74},[68,824,274],{"class":186},[68,826,202],{"class":74},[68,828,279],{"class":173},[68,830,282],{"class":74},[68,832,833,836,838,840,842,844,846,848,850,852],{"class":70,"line":82},[68,834,835],{"class":186},"    gpdf",[68,837,202],{"class":74},[68,839,353],{"class":173},[68,841,208],{"class":74},[68,843,211],{"class":74},[68,845,360],{"class":214},[68,847,211],{"class":74},[68,849,190],{"class":74},[68,851,367],{"class":186},[68,853,305],{"class":74},[68,855,856,858,860,862,864,866,868,870,872,874],{"class":70,"line":89},[68,857,835],{"class":186},[68,859,202],{"class":74},[68,861,379],{"class":173},[68,863,208],{"class":74},[68,865,211],{"class":74},[68,867,360],{"class":214},[68,869,211],{"class":74},[68,871,190],{"class":74},[68,873,392],{"class":339},[68,875,305],{"class":74},[68,877,878],{"class":70,"line":99},[68,879,159],{"class":74},[18,881,882,883,886,887,890,891,890,894,897,898,901],{},"The family name (",[42,884,885],{},"\"NotoSansJP\"",") is arbitrary. gpdf uses it as a lookup key — not a filesystem path, not a field read from the font's metadata. Call it ",[42,888,889],{},"\"body\""," or ",[42,892,893],{},"\"jp\"",[42,895,896],{},"\"Noto\""," if that reads better in your codebase. Just keep it consistent with the argument you pass to ",[42,899,900],{},"template.FontFamily(...)"," later.",[18,903,904,906,907,910,911,914],{},[42,905,379],{}," is the one that saves you from writing ",[42,908,909],{},"template.FontFamily(\"NotoSansJP\")"," on every single ",[42,912,913],{},"c.Text"," call. Skip it and gpdf falls back to Helvetica for unlabeled text, and Helvetica covers zero CJK codepoints. You'll get tofu boxes on half the document and spend an hour figuring out why only the headings render.",[13,916,918],{"id":917},"which-weights-do-you-actually-need","Which weights do you actually need?",[18,920,921],{},"Most invoices, receipts, and reports need two: Regular and Bold. Register both:",[59,923,925],{"className":61,"code":924,"language":63,"meta":64,"style":64},"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\", 11),\n)\n",[42,926,927,955,984,988,1002,1025,1049,1071],{"__ignoreMap":64},[68,928,929,932,934,937,939,941,943,945,947,949,951,953],{"class":70,"line":71},[68,930,931],{"class":186},"reg",[68,933,190],{"class":74},[68,935,936],{"class":186},"  _ ",[68,938,196],{"class":74},[68,940,199],{"class":186},[68,942,202],{"class":74},[68,944,205],{"class":173},[68,946,208],{"class":74},[68,948,211],{"class":74},[68,950,44],{"class":214},[68,952,211],{"class":74},[68,954,159],{"class":74},[68,956,957,960,962,965,967,969,971,973,975,977,980,982],{"class":70,"line":82},[68,958,959],{"class":186},"bold",[68,961,190],{"class":74},[68,963,964],{"class":186}," _ ",[68,966,196],{"class":74},[68,968,199],{"class":186},[68,970,202],{"class":74},[68,972,205],{"class":173},[68,974,208],{"class":74},[68,976,211],{"class":74},[68,978,979],{"class":214},"NotoSansJP-Bold.ttf",[68,981,211],{"class":74},[68,983,159],{"class":74},[68,985,986],{"class":70,"line":89},[68,987,86],{"emptyLinePlaceholder":85},[68,989,990,992,994,996,998,1000],{"class":70,"line":99},[68,991,820],{"class":186},[68,993,196],{"class":74},[68,995,274],{"class":186},[68,997,202],{"class":74},[68,999,279],{"class":173},[68,1001,282],{"class":74},[68,1003,1004,1006,1008,1010,1012,1014,1016,1018,1020,1023],{"class":70,"line":111},[68,1005,835],{"class":186},[68,1007,202],{"class":74},[68,1009,353],{"class":173},[68,1011,208],{"class":74},[68,1013,211],{"class":74},[68,1015,360],{"class":214},[68,1017,211],{"class":74},[68,1019,190],{"class":74},[68,1021,1022],{"class":186}," reg",[68,1024,305],{"class":74},[68,1026,1027,1029,1031,1033,1035,1037,1040,1042,1044,1047],{"class":70,"line":121},[68,1028,835],{"class":186},[68,1030,202],{"class":74},[68,1032,353],{"class":173},[68,1034,208],{"class":74},[68,1036,211],{"class":74},[68,1038,1039],{"class":214},"NotoSansJP-Bold",[68,1041,211],{"class":74},[68,1043,190],{"class":74},[68,1045,1046],{"class":186}," bold",[68,1048,305],{"class":74},[68,1050,1051,1053,1055,1057,1059,1061,1063,1065,1067,1069],{"class":70,"line":126},[68,1052,835],{"class":186},[68,1054,202],{"class":74},[68,1056,379],{"class":173},[68,1058,208],{"class":74},[68,1060,211],{"class":74},[68,1062,360],{"class":214},[68,1064,211],{"class":74},[68,1066,190],{"class":74},[68,1068,392],{"class":339},[68,1070,305],{"class":74},[68,1072,1073],{"class":70,"line":136},[68,1074,159],{"class":74},[18,1076,1077,1078,1081,1082,1085,1086,1089,1090,1093],{},"With ",[42,1079,1080],{},"-Bold"," registered under that suffix, ",[42,1083,1084],{},"template.Bold()"," picks it up automatically. Same rule for ",[42,1087,1088],{},"-Italic"," and ",[42,1091,1092],{},"-BoldItalic",". Note that Noto Sans JP doesn't ship an italic — CJK fonts generally don't, because the glyph design doesn't have an obvious oblique. If your layout wants italic emphasis on a Japanese run, reach for color, size, or weight instead.",[18,1095,1096],{},"Marketing brochures occasionally want Medium or SemiBold for pull quotes. That's fine. Register them under any suffix and address them by family name directly:",[59,1098,1100],{"className":61,"code":1099,"language":63,"meta":64,"style":64},"gpdf.WithFont(\"NotoSansJP-Medium\", medium)\n// ...\nc.Text(\"見出し\", template.FontFamily(\"NotoSansJP-Medium\"))\n",[42,1101,1102,1126,1132],{"__ignoreMap":64},[68,1103,1104,1106,1108,1110,1112,1114,1117,1119,1121,1124],{"class":70,"line":71},[68,1105,27],{"class":186},[68,1107,202],{"class":74},[68,1109,353],{"class":173},[68,1111,208],{"class":74},[68,1113,211],{"class":74},[68,1115,1116],{"class":214},"NotoSansJP-Medium",[68,1118,211],{"class":74},[68,1120,190],{"class":74},[68,1122,1123],{"class":186}," medium",[68,1125,159],{"class":74},[68,1127,1128],{"class":70,"line":82},[68,1129,1131],{"class":1130},"sHwdD","// ...\n",[68,1133,1134,1136,1138,1140,1142,1144,1147,1149,1151,1153,1155,1158,1160,1162,1164,1166],{"class":70,"line":89},[68,1135,482],{"class":186},[68,1137,202],{"class":74},[68,1139,506],{"class":173},[68,1141,208],{"class":74},[68,1143,211],{"class":74},[68,1145,1146],{"class":214},"見出し",[68,1148,211],{"class":74},[68,1150,190],{"class":74},[68,1152,520],{"class":186},[68,1154,202],{"class":74},[68,1156,1157],{"class":173},"FontFamily",[68,1159,208],{"class":74},[68,1161,211],{"class":74},[68,1163,1116],{"class":214},[68,1165,211],{"class":74},[68,1167,1168],{"class":74},"))\n",[18,1170,1171,1172,1174,1175,1174,1177,1179],{},"The suffix-based Bold/Italic shortcut only hooks up for the literal ",[42,1173,1080],{}," / ",[42,1176,1088],{},[42,1178,1092],{}," names. Anything else, you reference by family name.",[13,1181,1183],{"id":1182},"the-size-after-subsetting","The size after subsetting",[18,1185,1186],{},"Noto Sans JP Regular is ~5 MB on disk. That number pushes people into building separate CDNs for font files or post-processing PDFs to strip embedded fonts. Neither is necessary with gpdf.",[18,1188,1189],{},"Here's what actually lands in the PDF:",[1191,1192,1193,1209],"table",{},[1194,1195,1196],"thead",{},[1197,1198,1199,1203,1206],"tr",{},[1200,1201,1202],"th",{},"Document",[1200,1204,1205],{},"Glyphs used",[1200,1207,1208],{},"Font data in PDF",[1210,1211,1212,1224,1235,1246],"tbody",{},[1197,1213,1214,1218,1221],{},[1215,1216,1217],"td",{},"One-line receipt (~15 chars)",[1215,1219,1220],{},"~14",[1215,1222,1223],{},"~11 KB",[1197,1225,1226,1229,1232],{},[1215,1227,1228],{},"Typical invoice (~200 chars)",[1215,1230,1231],{},"~80",[1215,1233,1234],{},"~28 KB",[1197,1236,1237,1240,1243],{},[1215,1238,1239],{},"10-page report (~8,000 chars)",[1215,1241,1242],{},"~900",[1215,1244,1245],{},"~180 KB",[1197,1247,1248,1251,1254],{},[1215,1249,1250],{},"Dictionary-style dump (full JIS Level 1)",[1215,1252,1253],{},"~6,800",[1215,1255,1256],{},"~2.1 MB",[18,1258,1259],{},"(gpdf v1.0, static subsetting on. Numbers shift by a few KB depending on which glyph IDs fall in the CFF and hmtx tables.)",[18,1261,1262],{},"For an invoice that ends up 50 KB, more than half of the bytes are font data. That's still a rounding error next to the 5 MB you'd embed without subsetting, and the PDF viewer opens it instantly.",[13,1264,1266],{"id":1265},"noto-sans-jp-vs-noto-sans-cjk-jp-dont-mix-these-up","Noto Sans JP vs Noto Sans CJK JP — don't mix these up",[18,1268,1269],{},"There are two Noto families that both claim to handle Japanese, and the naming makes them sound interchangeable. They aren't.",[18,1271,1272,1275],{},[37,1273,1274],{},"Noto Sans JP"," is the one you want. Distributed as TTF, one language, each weight is a separate file. This is the Google Fonts download.",[18,1277,1278,1281,1282,1285,1286,202],{},[37,1279,1280],{},"Noto Sans CJK JP"," is the pan-CJK super-family. Distributed as OpenType Collection (",[42,1283,1284],{},".ttc","), a single file containing Japanese, Simplified Chinese, Traditional Chinese, and Korean glyphs unified in one package. It's what shipped in earlier Noto releases and what you'll find on ",[42,1287,1288],{},"notofonts.github.io/noto-cjk",[18,1290,1291,1292,1294,1295,1297],{},"gpdf supports TTF directly. TTC is a container format — you'd need to pick the right face index before handing bytes to ",[42,1293,353],{},", and the ",[42,1296,779],{}," inside each face is tuned for a specific CJK locale, which means you're making implicit choices about Han unification. Easier to make those choices explicitly by picking the JP-specific TTF.",[18,1299,1300,1301,1304,1305,890,1308,1311],{},"Starting today? Use Noto Sans JP. Already have ",[42,1302,1303],{},"NotoSansCJK-Regular.ttc"," in a legacy project? Extract the JP face with ",[42,1306,1307],{},"pyftsubset",[42,1309,1310],{},"fonttools"," and check the resulting TTF into your repo as the canonical artifact.",[13,1313,1315],{"id":1314},"embedding-the-font-into-the-binary","Embedding the font into the binary",[18,1317,1318],{},"PDF generators usually run in containers, and the cleanest way to ship the font is to compile it in:",[59,1320,1322],{"className":61,"code":1321,"language":63,"meta":64,"style":64},"package main\n\nimport (\n    _ \"embed\"\n\n    \"github.com/gpdf-dev/gpdf\"\n)\n\n//go:embed NotoSansJP-Regular.ttf\nvar notoJP []byte\n\nfunc main() {\n    doc := gpdf.NewDocument(\n        gpdf.WithFont(\"NotoSansJP\", notoJP),\n        gpdf.WithDefaultFont(\"NotoSansJP\", 11),\n    )\n    // ...\n}\n",[42,1323,1324,1330,1334,1340,1352,1356,1364,1368,1372,1377,1392,1396,1406,1420,1443,1465,1469,1474],{"__ignoreMap":64},[68,1325,1326,1328],{"class":70,"line":71},[68,1327,75],{"class":74},[68,1329,79],{"class":78},[68,1331,1332],{"class":70,"line":82},[68,1333,86],{"emptyLinePlaceholder":85},[68,1335,1336,1338],{"class":70,"line":89},[68,1337,93],{"class":92},[68,1339,96],{"class":74},[68,1341,1342,1345,1347,1350],{"class":70,"line":99},[68,1343,1344],{"class":186},"    _ ",[68,1346,211],{"class":74},[68,1348,1349],{"class":78},"embed",[68,1351,108],{"class":74},[68,1353,1354],{"class":70,"line":111},[68,1355,86],{"emptyLinePlaceholder":85},[68,1357,1358,1360,1362],{"class":70,"line":121},[68,1359,102],{"class":74},[68,1361,131],{"class":78},[68,1363,108],{"class":74},[68,1365,1366],{"class":70,"line":126},[68,1367,159],{"class":74},[68,1369,1370],{"class":70,"line":136},[68,1371,86],{"emptyLinePlaceholder":85},[68,1373,1374],{"class":70,"line":146},[68,1375,1376],{"class":1130},"//go:embed NotoSansJP-Regular.ttf\n",[68,1378,1379,1382,1385,1388],{"class":70,"line":156},[68,1380,1381],{"class":74},"var",[68,1383,1384],{"class":186}," notoJP ",[68,1386,1387],{"class":74},"[]",[68,1389,1391],{"class":1390},"spNyl","byte\n",[68,1393,1394],{"class":70,"line":162},[68,1395,86],{"emptyLinePlaceholder":85},[68,1397,1398,1400,1402,1404],{"class":70,"line":167},[68,1399,170],{"class":74},[68,1401,174],{"class":173},[68,1403,177],{"class":74},[68,1405,180],{"class":74},[68,1407,1408,1410,1412,1414,1416,1418],{"class":70,"line":183},[68,1409,269],{"class":186},[68,1411,196],{"class":74},[68,1413,274],{"class":186},[68,1415,202],{"class":74},[68,1417,279],{"class":173},[68,1419,282],{"class":74},[68,1421,1422,1424,1426,1428,1430,1432,1434,1436,1438,1441],{"class":70,"line":221},[68,1423,288],{"class":186},[68,1425,202],{"class":74},[68,1427,353],{"class":173},[68,1429,208],{"class":74},[68,1431,211],{"class":74},[68,1433,360],{"class":214},[68,1435,211],{"class":74},[68,1437,190],{"class":74},[68,1439,1440],{"class":186}," notoJP",[68,1442,305],{"class":74},[68,1444,1445,1447,1449,1451,1453,1455,1457,1459,1461,1463],{"class":70,"line":237},[68,1446,288],{"class":186},[68,1448,202],{"class":74},[68,1450,379],{"class":173},[68,1452,208],{"class":74},[68,1454,211],{"class":74},[68,1456,360],{"class":214},[68,1458,211],{"class":74},[68,1460,190],{"class":74},[68,1462,392],{"class":339},[68,1464,305],{"class":74},[68,1466,1467],{"class":70,"line":255},[68,1468,400],{"class":74},[68,1470,1471],{"class":70,"line":261},[68,1472,1473],{"class":1130},"    // ...\n",[68,1475,1476],{"class":70,"line":266},[68,1477,706],{"class":74},[18,1479,1480,1481,1484],{},"Binary grows from ~8 MB to ~13 MB. In return, your Docker image has one artifact instead of two, ",[42,1482,1483],{},"COPY --from=builder /app /app"," is all you need, and nobody can ship a broken container missing the font file. For a batch job generating thousands of PDFs a day, this is the right default.",[13,1486,1488],{"id":1487},"related-reading","Related reading",[743,1490,1491,1498,1508,1515],{},[746,1492,1493,1497],{},[22,1494,1496],{"href":1495},"/blog/embed-japanese-font","How do I embed a Japanese font in gpdf?"," — the general recipe, applies to any CJK TTF",[746,1499,1500,1504,1505],{},[22,1501,1503],{"href":1502},"/blog/gofpdf-migration","gofpdf is archived. Here's how to migrate to gpdf."," — migration map from ",[42,1506,1507],{},"pdf.AddUTF8Font",[746,1509,1510,1514],{},[22,1511,1513],{"href":1512},"/blog/go-pdf-library-showdown-2026","Go PDF Library Showdown 2026"," — how gpdf compares on CJK specifically",[746,1516,1517,1522,1523,1525],{},[22,1518,1521],{"href":1519,"rel":1520},"https://gpdf.dev/docs/guide/fonts",[26],"Fonts guide"," — the full ",[42,1524,353],{}," reference and variant naming rules",[13,1527,1529],{"id":1528},"try-gpdf","Try gpdf",[18,1531,1532],{},"gpdf is a Go library for generating PDFs. MIT licensed, zero external dependencies, native CJK support.",[59,1534,1538],{"className":1535,"code":1536,"language":1537,"meta":64,"style":64},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[42,1539,1540],{"__ignoreMap":64},[68,1541,1542,1544,1547],{"class":70,"line":71},[68,1543,63],{"class":78},[68,1545,1546],{"class":214}," get",[68,1548,1549],{"class":214}," github.com/gpdf-dev/gpdf\n",[18,1551,1552,1556,1557],{},[22,1553,1555],{"href":24,"rel":1554},[26],"⭐ Star on GitHub"," · ",[22,1558,1561],{"href":1559,"rel":1560},"https://gpdf.dev/docs/quickstart",[26],"Read the docs",[1563,1564,1565],"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);}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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":64,"searchDepth":82,"depth":82,"links":1567},[1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578],{"id":15,"depth":82,"text":16},{"id":31,"depth":82,"text":32},{"id":56,"depth":82,"text":57},{"id":729,"depth":82,"text":730},{"id":806,"depth":82,"text":807},{"id":917,"depth":82,"text":918},{"id":1182,"depth":82,"text":1183},{"id":1265,"depth":82,"text":1266},{"id":1314,"depth":82,"text":1315},{"id":1487,"depth":82,"text":1488},{"id":1528,"depth":82,"text":1529},"2026-04-15","Register the static NotoSansJP-Regular.ttf with gpdf.WithFont. Skip the variable font — gpdf's pure-Go parser does not read fvar tables. Subsetting lands around 30 KB.",false,"md",{"name":1584,"totalTime":1585,"tools":1586,"steps":1589},"Use Noto Sans JP as the default font in a gpdf document","PT10M",[1587,1588],"Go 1.22+","NotoSansJP-Regular.ttf (static TTF from Google Fonts)",[1590,1593,1596,1599],{"name":1591,"text":1592},"Download the static TTF from Google Fonts","Grab Noto Sans JP from fonts.google.com, unzip the bundle, and pick static/NotoSansJP-Regular.ttf. Do not use the NotoSansJP-VariableFont_wght.ttf sitting at the root.",{"name":1594,"text":1595},"Load the bytes at startup","Read NotoSansJP-Regular.ttf with os.ReadFile, or compile it in with //go:embed for a single-artifact binary.",{"name":1597,"text":1598},"Register the font at document construction","Pass gpdf.WithFont(\"NotoSansJP\", fontBytes) and gpdf.WithDefaultFont(\"NotoSansJP\", 11) to gpdf.NewDocument. No AddUTF8Font, no filesystem path.",{"name":1600,"text":1601},"Write Japanese text and generate","Call c.Text(\"請求書\") inside a column. doc.Generate() returns []byte and gpdf subsets only the glyphs you actually used into the final PDF.",null,{},"/blog/noto-sans-jp-with-gpdf",{"title":5,"description":1580},"blog/004.noto-sans-jp-with-gpdf",[1608,1609,1610],"recipe","cjk","tutorial","Pa_qo0A9IKywvaQbcsuRmUxB9WbNQ2lpH74ZV1Nx_ZQ",1776529258852]