/** * 図が使う 2 つの字。どちらも package の依存として同梱する。 * * 描いた SVG は字をこの 2 つの名前でしか名指さない。端末の字の名前を持たないので、 * 同梱した字が読み込まれていない時に、端末の字へ黙って落ちて幅が変わることが無い。 * 頁に字を読み込むのは `@cardenelabs/dragon/fonts` の入口 (`load-fonts.ts`) が持つ。 */ export const FONTS = { sans: "Noto Sans JP Variable", mono: "JetBrains Mono Variable" } as const; /** * 和文の字の英数字と記号の幅 (1000 分率)。使う太さ (500 / 600 / 650 / 700) のうち一番広い値。 * `scripts/font-widths.mjs` が同梱の字をブラウザに読ませて測った値で、字を上げた時は測り直して貼る。 * 表に無い字のうち U+2E80 以降 (仮名と漢字と全角の記号) は全角 (1000) とする。 */ export const SANS_ADVANCE: Readonly> = {"0":590,"1":590,"2":590,"3":590,"4":590,"5":590,"6":590,"7":590,"8":590,"9":590," ":228,"!":371,"\"":575,"#":590,"$":590,"%":963,"&":740,"'":325,"(":378,")":378,"*":507,"+":590,",":325,"-":371,".":325,"/":390,":":325,";":325,"<":590,"=":590,">":590,"?":514,"@":1007,"A":642,"B":682,"C":657,"D":715,"E":616,"F":586,"G":718,"H":758,"I":330,"J":568,"K":686,"L":579,"M":854,"N":750,"O":771,"P":668,"Q":771,"R":682,"S":624,"T":626,"U":748,"V":619,"W":915,"X":627,"Y":581,"Z":614,"[":378,"\\":390,"]":378,"^":590,"_":568,"`":626,"a":591,"b":644,"c":528,"d":645,"e":581,"f":372,"g":598,"h":640,"i":305,"j":306,"k":605,"l":315,"m":964,"n":641,"o":626,"p":645,"q":645,"r":437,"s":495,"t":421,"u":638,"v":576,"w":863,"x":562,"y":575,"z":512,"{":378,"|":297,"}":378,"~":590,"…":1000,"−":590,"×":1000,"→":1000,"←":1000,"↑":1000,"↓":1000,"–":545,"—":908,"‘":325,"’":325,"“":575,"”":575,"°":404,"±":1000,"·":593,"•":379}; /** 等幅の字の幅 (1000 分率)。どの字も同じ幅。 */ export const MONO_ADVANCE = 600; /** 全角として数える字の始まり。仮名と漢字と全角の記号はここから後ろにある。 */ export const WIDE_FROM = 0x2e80; export type Family = keyof typeof FONTS; /** 字の大きさを 1000 とした時の幅。上の表はこの単位で持つ。 */ export const EM = 1000; /** 1 字の幅 (1000 分率)。表に無い字は全角とする。 */ export function advance(ch: string, family: Family): number { if ((ch.codePointAt(0) ?? 0) >= WIDE_FROM) return EM; if (family === "mono") return MONO_ADVANCE; return SANS_ADVANCE[ch] ?? EM; }