How do I use Source Han Sans JP with gpdf?
Register the TTF variant of Source Han Sans JP from Adobe's GitHub release with gpdf.WithFont. Seven weights, SIL OFL, same glyphs as Noto Sans JP.
The question, in other words
You want to use Source Han Sans JP — Adobe's open-source pan-CJK sans-serif, released in 2014 as the product of the Adobe–Google partnership — in a gpdf document. Maybe your team pins fonts to GitHub release tags for reproducibility, maybe you inherited a design system that standardized on Source Han years ago, maybe you just prefer Adobe's release cadence. Whatever the reason, three things are worth getting straight before you download anything: which file to grab, what the actual relationship to Noto Sans JP is, and which format gpdf can read.
TL;DR
Download SourceHanSansJP-Regular.ttf from the adobe-fonts/source-han-sans release page (the TTF bundle, not the default OTF), pass it to gpdf.WithFont("SourceHanSansJP", bytes), and set it as the default. Source Han Sans JP and Noto Sans JP share the same glyph outlines — if none of Adobe's tooling story matters to you, Noto is a friendlier download.
The complete example
package main
import (
"log"
"os"
"github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
font, err := os.ReadFile("SourceHanSansJP-Regular.ttf")
if err != nil {
log.Fatal(err)
}
doc := gpdf.NewDocument(
gpdf.WithPageSize(gpdf.A4),
gpdf.WithMargins(document.UniformEdges(document.Mm(20))),
gpdf.WithFont("SourceHanSansJP", font),
gpdf.WithDefaultFont("SourceHanSansJP", 11),
)
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("報告書", template.FontSize(24), template.Bold())
c.Text("Source Han Sans JP — Adobe 配布の無料 CJK フォント。")
})
})
data, err := doc.Generate()
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("report.pdf", data, 0o644); err != nil {
log.Fatal(err)
}
}
Drop the TTF next to main.go, go run main.go. A one-page PDF with Japanese lands in report.pdf.
Source Han Sans JP is Noto Sans CJK JP
The one fact that saves you hours of reading: Source Han Sans and Noto Sans CJK are the same fonts. Adobe did the glyph design, metrics, and coverage work. Google handled a parallel distribution channel under the Noto umbrella. Both launched on 2014-07-15. The outlines, hmtx, and JIS X 0213 / Adobe-Japan1-6 coverage are identical, bit for bit. When Adobe ships a version bump, the glyph changes propagate to Noto within weeks.
What actually differs is branding and packaging:
| Source Han Sans JP | Noto Sans JP | |
|---|---|---|
| Publisher | Adobe | |
| Canonical source | adobe-fonts/source-han-sans | notofonts.github.io + Google Fonts |
| Default format | OTF (CFF outlines) | TTF (static) + variable |
| Release model | GitHub release tags, versioned manually | Google Fonts CDN + git repos |
| Language bundling | Per-language TTF + pan-CJK OTC | JP-only |
Pick Source Han Sans JP when your team pins fonts to Adobe's GitHub tags, mirrors Adobe internally, or wants the pan-CJK OTC bundle for other pipelines. Pick Noto Sans JP when you want the shortest path to a TTF file. See the Noto Sans JP recipe for that path.
Why TTF, and not OTF
Adobe's default asset for Source Han Sans is .otf — specifically CFF-based OpenType. gpdf's font parser lives in one file (pdf/font/truetype.go) and it reads glyf, loca, cmap, hmtx, and composite glyphs. It does not read CFF or CFF2 outlines. Hand it a CFF-flavored .otf and the parser rejects the file at document construction, long before you generate anything.
The Adobe release page publishes both OTF and TTF variants. Grab the TTF bundle. If your release archive happens to contain only OTF (occasionally true for point releases), two clean alternatives:
- Switch to Noto Sans JP. Google Fonts serves static TTFs directly; the glyph data is identical. Zero conversion, same output.
- Convert once, commit the result.
fonttools(otf2ttf) produces a TTF in a minute. Check it into your repo or an internal artifact server so the conversion is never in your build path.
Avoid anything that does the conversion at build time. Font conversion tools change behavior across versions, and a silently different hmtx table will shift your line breaks after a pip install -U.
The seven weights
Source Han Sans JP publishes ExtraLight → Heavy, one file per weight:
SourceHanSansJP-ExtraLight.ttf
SourceHanSansJP-Light.ttf
SourceHanSansJP-Normal.ttf
SourceHanSansJP-Regular.ttf
SourceHanSansJP-Medium.ttf
SourceHanSansJP-Bold.ttf
SourceHanSansJP-Heavy.ttf
For most business documents, Regular and Bold cover what you need:
reg, _ := os.ReadFile("SourceHanSansJP-Regular.ttf")
bold, _ := os.ReadFile("SourceHanSansJP-Bold.ttf")
doc := gpdf.NewDocument(
gpdf.WithFont("SourceHanSansJP", reg),
gpdf.WithFont("SourceHanSansJP-Bold", bold),
gpdf.WithDefaultFont("SourceHanSansJP", 11),
)
The suffix -Bold is the contract that wires template.Bold() to the Bold TTF. Skip that registration and template.Bold() falls back to a synthesized bold — a stroke overlay on the Regular glyphs. Legible for table headings, but visibly thinner than the real Bold outlines at display sizes.
CJK fonts don't ship italic variants as a rule, and Source Han Sans JP is no exception. If your layout needs italic emphasis on a Japanese run, reach for a heavier weight or color — an oblique transform on CJK glyphs looks broken rather than emphatic.
Pan-CJK, JP-only, or the Super OTC
Adobe publishes Source Han Sans in several granularities. They are not interchangeable for a Go PDF generator:
- SourceHanSans.ttc (Super OTC) — every CJK language in one 20 MB+ TrueType Collection. gpdf does not select a face index inside a
.ttc; you'd need to slice out the JP face first withfonttoolsand register the result. Skip the Super OTC. - Region-specific OTF (e.g.
SourceHanSans-Regular.otf) — all CJK scripts unified, CFF outlines. Not readable by gpdf. - Language-specific TTF (
SourceHanSansJP-Regular.ttf) — JP-only,glyfoutlines. This is the one to grab.
If your document mixes Japanese with Korean or Chinese in the same page, register language-specific families side by side: SourceHanSansJP plus SourceHanSansKR. Switch explicitly with template.FontFamily where the text changes script. Reaching for the pan-CJK unified OTF would have fixed this with Han unification, but that introduces its own surprises for readers who expect JP-shaped kanji in JP text.
When to pick Source Han over Noto
Same outlines, different distribution. Source Han Sans JP makes sense when:
- Your ops team prefers pinning to Adobe's GitHub release tags for reproducibility
- You already mirror
github.com/adobe-fontsinternally (common at enterprises with locked-down artifact policies) - The pan-CJK OTC bundle is useful elsewhere in your pipeline — a desktop publishing step, a DTP handoff, a brand system that standardizes on the Adobe name
Noto Sans JP is the better pick when:
- You want the shortest route to a TTF (
https://fonts.google.com/noto/specimen/Noto+Sans+JP→ zip → done) - Converting OTF to TTF isn't something you want in your build
- Your project already pulls other Google Fonts via an existing workflow
The rendered PDF looks the same either way. The decision is operational — where the file lives, how you version it, how ops feels about it — not aesthetic.
Related reading
- How do I use Noto Sans JP with gpdf? — the same glyphs, published as TTF out of the box
- How do I embed a Japanese font in gpdf? — the general CJK embedding recipe
- How do I use IPAex Gothic in gpdf? — the IPA-licensed alternative for Japanese institutional submissions
- Why does my PDF show tofu boxes for Japanese? — troubleshooting missing glyphs
Try gpdf
gpdf is a Go library for generating PDFs. MIT licensed, zero external dependencies, native CJK support.
go get github.com/gpdf-dev/gpdf